<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>chris' random ramblings &#187; Tips</title>
	<atom:link href="http://atlee.ca/blog/category/tips/feed/" rel="self" type="application/rss+xml" />
	<link>http://atlee.ca/blog</link>
	<description>programming, photography, media, and anything else that strikes my fancy</description>
	<lastBuildDate>Tue, 11 May 2010 15:15:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Getting free diskspace in python, on Windows</title>
		<link>http://atlee.ca/blog/2010/05/10/getting-free-diskspace-in-python-on-windows/</link>
		<comments>http://atlee.ca/blog/2010/05/10/getting-free-diskspace-in-python-on-windows/#comments</comments>
		<pubDate>Tue, 11 May 2010 03:00:53 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/?p=747</guid>
		<description><![CDATA[Amazingly, one of the most popular links on this site is the quick tip, Getting free diskspace in python.
One of the comments shows that this method doesn&#8217;t work on Windows.  Here&#8217;s a version that does:

import win32file
def freespace&#40;p&#41;:
    &#34;&#34;&#34;
    Returns the number of free bytes on the drive that [...]]]></description>
			<content:encoded><![CDATA[<p>Amazingly, one of the most popular links on this site is the quick tip, <a href="http://atlee.ca/blog/2008/02/23/getting-free-diskspace-in-python/">Getting free diskspace in python.</a></p>
<p>One of the comments shows that this method doesn&#8217;t work on Windows.  Here&#8217;s a version that does:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> win32file
<span style="color: #ff7700;font-weight:bold;">def</span> freespace<span style="color: black;">&#40;</span>p<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Returns the number of free bytes on the drive that ``p`` is on
    &quot;&quot;&quot;</span>
    secsPerClus, bytesPerSec, nFreeClus, totClus = win32file.<span style="color: black;">GetDiskFreeSpace</span><span style="color: black;">&#40;</span>p<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> secsPerClus <span style="color: #66cc66;">*</span> bytesPerSec <span style="color: #66cc66;">*</span> nFreeClus</pre></div></div>

<p>The win32file module is part of the <a href="http://sourceforge.net/projects/pywin32/">pywin32</a> extension module.</p>
]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2010/05/10/getting-free-diskspace-in-python-on-windows/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Two great, completely unrelated links</title>
		<link>http://atlee.ca/blog/2010/03/31/two-great-completely-unrelated-links/</link>
		<comments>http://atlee.ca/blog/2010/03/31/two-great-completely-unrelated-links/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 20:47:46 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Religion]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/?p=693</guid>
		<description><![CDATA[Yesterday was a bit of an overwhelming day.  After getting home at 1am after a long bus ride home, I was unwinding by catching up on some news and email.  I came across these two links, both of which really lifted my mood.
The first, Grokking the Zen of the Vi Wu-Wei, talks about [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday was a bit of an overwhelming day.  After getting home at 1am after a long bus ride home, I was unwinding by catching up on some news and email.  I came across these two links, both of which really lifted my mood.</p>
<p>The first, <a href="http://jeetworks.org/grokking-the-zen-of-the-vi-wu-wei">Grokking the Zen of the Vi Wu-Wei</a>, talks about a programmer&#8217;s journey from emacs to BBEdit to vim.  This post is a great read in and of itself, but what&#8217;s <strong>really</strong> worth it, is the link around the middle of the post to <a href="http://stackoverflow.com/questions/1218390/what-is-your-most-productive-shortcut-with-vim/1220118#1220118">http://stackoverflow.com/questions/1218390/what-is-your-most-productive-shortcut-with-vim/1220118#1220118</a>.  This was truly a joy to read.  Definitely the best answer I&#8217;ve ever seen on Stack Overflow, and quite possibly the best discussion of vi I&#8217;ve ever read.  It taught me a lot, but I enjoyed reading it for more than that.  It was almost like being on a little adventure, discovering all these little hidden secrets about the neighbourhood you&#8217;ve been living in for years.  Like I said, it was 1am.</p>
<p>The second, <a href="http://blogs.telegraph.co.uk/news/damianthompson/100032121/the-pope-the-judge-the-paedophile-priest-and-the-new-york-times/">The Pope, the judge, the paedophile priest and The New York Times</a>, gave me some reassurance that things aren&#8217;t always as they seem as reported by the media.  Regardless of how you feel about the Church or the Pope, it seems that journalistic integrity has fallen by the wayside here.  From the article:</p>
<blockquote><p>Fr Thomas Brundage, the former Archdiocese of Milwaukee Judicial Vicar who presided over the canonical criminal case of the Wisconsin child abuser Fr Lawrence Murphy, has broken his silence to give a devastating account of the scandal – and of the behaviour of The New York Times, which resurrected the story.</p>
<p>It looks as if the media were in such a hurry to to blame the Pope for this wretched business that <strong>not one news organisation contacted Fr Brundage</strong>. As a result, crucial details were unreported.</p></blockquote>
<p>The entire article is worth a read.</p>
]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2010/03/31/two-great-completely-unrelated-links/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>One useful script, a linux version</title>
		<link>http://atlee.ca/blog/2009/11/13/one-useful-script-a-linux-version/</link>
		<comments>http://atlee.ca/blog/2009/11/13/one-useful-script-a-linux-version/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 14:55:18 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/?p=630</guid>
		<description><![CDATA[Johnathan posted links to 3 scripts he finds useful.  His sattap script looked handy, so I hacked it up for linux.  Run it to do a screen capture, and upload the image to a website you have ssh access into.  The link is printed out, and put into the clipboard.
Hope you find [...]]]></description>
			<content:encoded><![CDATA[<p>Johnathan posted links to <a href="http://blog.johnath.com/2009/11/11/three-stupid-scripts-i-find-useful/">3 scripts he finds useful</a>.  His sattap script looked handy, so I hacked it up for linux.  Run it to do a screen capture, and upload the image to a website you have ssh access into.  The link is printed out, and put into the clipboard.</p>
<p>Hope you find this useful!</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
<span style="color: #666666; font-style: italic;"># sattap - Send a thing to a place</span>
<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-e</span>
&nbsp;
<span style="color: #007800;">SCP_USER</span>=<span style="color: #ff0000;">'catlee'</span>
<span style="color: #007800;">SCP_HOST</span>=<span style="color: #ff0000;">'people.mozilla.org'</span>
<span style="color: #007800;">SCP_PATH</span>=<span style="color: #ff0000;">'~/public_html/sattap/'</span>
&nbsp;
<span style="color: #007800;">HTTP_URL</span>=<span style="color: #ff0000;">&quot;http://people.mozilla.org/~catlee/sattap/&quot;</span>
&nbsp;
<span style="color: #007800;">FILENAME</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">date</span> <span style="color: #000000; font-weight: bold;">|</span> md5sum <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">head</span> <span style="color: #660033;">-c</span> <span style="color: #000000;">8</span><span style="color: #000000; font-weight: bold;">`</span>.png
<span style="color: #007800;">FILEPATH</span>=<span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$FILENAME</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> Capturing...
import <span style="color: #007800;">$FILEPATH</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> Copying to <span style="color: #007800;">$SCP_HOST</span>
<span style="color: #c20cb9; font-weight: bold;">scp</span> <span style="color: #007800;">$FILEPATH</span> <span style="color: #800000;">${SCP_USER}</span><span style="color: #000000; font-weight: bold;">@</span><span style="color: #800000;">${SCP_HOST}</span>:<span style="color: #007800;">$SCP_PATH</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> Deleting <span style="color: #7a0874; font-weight: bold;">local</span> copy
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #007800;">$FILEPATH</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$HTTP_URL</span><span style="color: #007800;">$FILENAME</span> <span style="color: #000000; font-weight: bold;">|</span> xclip <span style="color: #660033;">-selection</span> clipboard
<span style="color: #7a0874; font-weight: bold;">echo</span> Your <span style="color: #c20cb9; font-weight: bold;">file</span> should be at <span style="color: #007800;">$HTTP_URL</span><span style="color: #007800;">$FILENAME</span>, <span style="color: #c20cb9; font-weight: bold;">which</span> is also <span style="color: #000000; font-weight: bold;">in</span> your paste buffer</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2009/11/13/one-useful-script-a-linux-version/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Exporting MQ patches</title>
		<link>http://atlee.ca/blog/2009/03/23/exporting-mq-patches/</link>
		<comments>http://atlee.ca/blog/2009/03/23/exporting-mq-patches/#comments</comments>
		<pubDate>Mon, 23 Mar 2009 17:30:52 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[mq]]></category>
		<category><![CDATA[patch]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/?p=328</guid>
		<description><![CDATA[I&#8217;ve been trying to use Mercurial Queues to manage my work on different tasks in several repositories.  I try to name all my patches with the name of the bug it&#8217;s related to; so for my recent work on getting Talos not skipping builds, I would call my patch &#8216;bug468731&#8242;.
I noticed that I was [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been trying to use <a href="http://hgbook.red-bean.com/hgbookch12.html#x16-26700012">Mercurial Queues</a> to manage my work on different tasks in several repositories.  I try to name all my patches with the name of the bug it&#8217;s related to; so for my recent work on getting Talos not skipping builds, I would call my patch &#8216;bug468731&#8242;.</p>
<p>I noticed that I was running this series of steps a lot:<br />
<code>cd ~/mozilla/buildbot-configs<br />
hg qdiff > ~/patches/bug468731-buildbot-configs.patch<br />
cd ~/mozilla/buildbotcustom<br />
hg qdiff > ~/patches/bug468731-buildbotcustom.patch<br />
</code><br />
&#8230;and then uploading the resulting patch files as attachments to the bug.  There&#8217;s a lot of repetition and extra mental work in those steps:</p>
<ul>
<li>I have to type the bug number manually <em>twice</em>.  This is annoying, and error-prone.  I&#8217;ve made a typo on more than one occasion and then wasted a few minutes trying to track down where the file went.</li>
<li>I have to type the correct repository name for each patch.  Again, I&#8217;ve managed to screw this up in the past.  Often I have several terminals open, one for each repository, and I can get mixed up as to which repository I&#8217;ve currently got active.</li>
<li>mercurial already knows the bug number, since I&#8217;ve used it in the name of my patch.</li>
<li>mercurial already knows which repository I&#8217;m in.</li>
</ul>
<p>I wrote the mercurial extension below to help with this.  It will take the current patch name, and the basename of the current repository, and save a patch in ~/patches called [patch_name]-[repo_name].patch.  It will also compare the current patch to any previous ones in the patches directory, and save a new file if the patches are different, or tell you that you&#8217;ve already saved this patch.</p>
<p>To enable this extension, save the code below somewhere like ~/.hgext/mkpatch.py, and then add &#8220;mkpatch = ~/.hgext/mkpatch.py&#8221; to your .hgrc&#8217;s extensions section.  Then you can run &#8216;hg mkpatch&#8217; to automatically create a patch for you in your ~/patches directory!</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, hashlib
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> mercurial <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">commands</span>, util
<span style="color: #ff7700;font-weight:bold;">from</span> hgext <span style="color: #ff7700;font-weight:bold;">import</span> mq
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> mkpatch<span style="color: black;">&#40;</span>ui, repo, <span style="color: #66cc66;">*</span>pats, <span style="color: #66cc66;">**</span>opts<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Saves the current patch to a file called &lt;patch_name&gt;-&lt;repo_name&gt;.patch
    in your patch directory (defaults to ~/patches)
    &quot;&quot;&quot;</span>
    repo_name = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">basename</span><span style="color: black;">&#40;</span>ui.<span style="color: black;">config</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'paths'</span>, <span style="color: #483d8b;">'default'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> opts.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'patchdir'</span><span style="color: black;">&#41;</span>:
        patch_dir = opts.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'patchdir'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">del</span> opts<span style="color: black;">&#91;</span><span style="color: #483d8b;">'patchdir'</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        patch_dir = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">expanduser</span><span style="color: black;">&#40;</span>ui.<span style="color: black;">config</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkpatch'</span>, <span style="color: #483d8b;">'patchdir'</span>, <span style="color: #483d8b;">&quot;~/patches&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    ui.<span style="color: black;">pushbuffer</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    mq.<span style="color: black;">top</span><span style="color: black;">&#40;</span>ui, repo<span style="color: black;">&#41;</span>
    patch_name = ui.<span style="color: black;">popbuffer</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span>patch_dir<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">os</span>.<span style="color: black;">makedirs</span><span style="color: black;">&#40;</span>patch_dir<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isdir</span><span style="color: black;">&#40;</span>patch_dir<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span> util.<span style="color: black;">Abort</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s is not a directory&quot;</span> <span style="color: #66cc66;">%</span> patch_dir<span style="color: black;">&#41;</span>
&nbsp;
    ui.<span style="color: black;">pushbuffer</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    mq.<span style="color: black;">diff</span><span style="color: black;">&#40;</span>ui, repo, <span style="color: #66cc66;">*</span>pats, <span style="color: #66cc66;">**</span>opts<span style="color: black;">&#41;</span>
    patch_data = ui.<span style="color: black;">popbuffer</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    patch_hash = hashlib.<span style="color: #dc143c;">new</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'sha1'</span>, patch_data<span style="color: black;">&#41;</span>.<span style="color: black;">digest</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    full_name = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>patch_dir, <span style="color: #483d8b;">&quot;%s-%s.patch&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>patch_name, repo_name<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    i = <span style="color: #ff4500;">0</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span>full_name<span style="color: black;">&#41;</span>:
        file_hash = hashlib.<span style="color: #dc143c;">new</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'sha1'</span>, <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>full_name<span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">digest</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> file_hash == patch_hash:
            ui.<span style="color: black;">status</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Patch is identical to &quot;</span>, full_name, <span style="color: #483d8b;">&quot;; not saving&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span>
        full_name = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>patch_dir, <span style="color: #483d8b;">&quot;%s-%s.patch.%i&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>patch_name, repo_name, i<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        i += <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>full_name, <span style="color: #483d8b;">&quot;w&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span>patch_data<span style="color: black;">&#41;</span>
    ui.<span style="color: black;">status</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Patch saved to &quot;</span>, full_name<span style="color: black;">&#41;</span>
&nbsp;
mkpatch_options = <span style="color: black;">&#91;</span>
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #483d8b;">&quot;patchdir&quot;</span>, <span style="color: #483d8b;">''</span>, <span style="color: #483d8b;">&quot;patch directory&quot;</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#93;</span>
cmdtable = <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">&quot;mkpatch&quot;</span>: <span style="color: black;">&#40;</span>mkpatch, mkpatch_options + mq.<span style="color: black;">cmdtable</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'^qdiff'</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">&quot;hg mkpatch [OPTION]... [FILE]...&quot;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2009/03/23/exporting-mq-patches/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>ssh on-the-fly port forwarding</title>
		<link>http://atlee.ca/blog/2008/12/09/ssh-on-the-fly-port-forwarding/</link>
		<comments>http://atlee.ca/blog/2008/12/09/ssh-on-the-fly-port-forwarding/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 02:35:54 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/?p=248</guid>
		<description><![CDATA[Check out this great tip from nion&#8217;s blog:
ssh on-the-fly port forwarding.
I&#8217;ve often wanted to open up new port forwards, but haven&#8217;t wanted to shut down my existing session.

If you follow this by # character (and thus type ~#) you get a list of all forwarded connections.
Using ~C you can open an internal ssh shell that [...]]]></description>
			<content:encoded><![CDATA[<p>Check out this great tip from nion&#8217;s blog:</p>
<p><a href="http://nion.modprobe.de/blog/archives/656-guid.html">ssh on-the-fly port forwarding</a>.</p>
<p>I&#8217;ve often wanted to open up new port forwards, but haven&#8217;t wanted to shut down my existing session.</p>
<blockquote><p>
If you follow this by # character (and thus type ~#) you get a list of all forwarded connections.<br />
Using ~C you can open an internal ssh shell that enables you to add and remove local/remote port forwardings</p>
<p>ssh> help<br />
Commands:<br />
  -L[bind_address:]port:host:hostport Request local forward<br />
  -R[bind_address:]port:host:hostport Request remote forward<br />
  -KR[bind_address:]port Cancel remote forward</p>
<p>ssh> -L 8080:localhost:8080
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2008/12/09/ssh-on-the-fly-port-forwarding/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>python reload: danger, here be dragons</title>
		<link>http://atlee.ca/blog/2008/11/21/python-reload-danger-here-be-dragons/</link>
		<comments>http://atlee.ca/blog/2008/11/21/python-reload-danger-here-be-dragons/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 15:26:40 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[buildbot]]></category>
		<category><![CDATA[problem]]></category>
		<category><![CDATA[reload]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/?p=211</guid>
		<description><![CDATA[At Mozilla, we use buildbot to coordinate performing builds, unit tests, performance tests, and l10n repacks across all of our build slaves.
There is a lot of activity on a project the size of Firefox, which means that the build slaves are kept pretty busy most of the time.
Unfortunately, like most software out there, our buildbot [...]]]></description>
			<content:encoded><![CDATA[<p>At <a href="http://mozilla.com">Mozilla</a>, we use <a href="http://buildbot.net">buildbot</a> to coordinate performing builds, unit tests, performance tests, and l10n repacks across all of our build slaves.</p>
<p>There is a lot of activity on a project the size of Firefox, which means that the build slaves are kept pretty busy most of the time.</p>
<p>Unfortunately, like most software out there, our buildbot code has bugs in it.  buildbot provides two ways of picking up new changes to code and configuration: &#8216;buildbot restart&#8217; and &#8216;buildbot reconfig&#8217;.</p>
<p>Restarting buildbot is the cleanest thing to do: it shuts down the existing buildbot process, and starts a new one once the original has shut down cleanly.  The problem with restarting is that it interrupts any builds that are currently active.</p>
<p>The second option, &#8216;reconfig&#8217;, is usually a great way to pick up changes to buildbot code without interrupting existing builds.  &#8216;reconfig&#8217; is implemented by sending SIGHUP to the buildbot process, which triggers a python <a href="http://docs.python.org/library/functions.html#reload">reload()</a> of certain files.</p>
<p>This is where the problem starts.</p>
<p>Reloading a module basically re-initializes the module, including redefining any classes that are in the module&#8230;which is what you want, right?  The whole reason you&#8217;re reloading is to pick up changes to the code you have in the module!</p>
<p>So let&#8217;s say you have a module, foo.py, with these classes:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Foo<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Foo.foo&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Bar<span style="color: black;">&#40;</span>Foo<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Bar.foo&quot;</span>
        Foo.<span style="color: black;">foo</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span></pre></div></div>

<p>and you&#8217;re using it like this:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> foo
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b = foo.<span style="color: black;">Bar</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b.<span style="color: black;">foo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Bar.<span style="color: black;">foo</span>
Foo.<span style="color: black;">foo</span></pre></div></div>

<p>Looks good!  Now, let&#8217;s do a reload, which is what buildbot does on a &#8216;reconfig&#8217;:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">reload</span><span style="color: black;">&#40;</span>foo<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>module <span style="color: #483d8b;">'foo'</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #483d8b;">'foo.pyc'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b.<span style="color: black;">foo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Bar.<span style="color: black;">foo</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
  File <span style="color: #483d8b;">&quot;/Users/catlee/test/foo.py&quot;</span>, line <span style="color: #ff4500;">13</span>, <span style="color: #ff7700;font-weight:bold;">in</span> foo
    Foo.<span style="color: black;">foo</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: unbound method foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> must be called <span style="color: #ff7700;font-weight:bold;">with</span> Foo instance <span style="color: #ff7700;font-weight:bold;">as</span> first argument <span style="color: black;">&#40;</span>got Bar instance instead<span style="color: black;">&#41;</span></pre></div></div>

<p>Whoops!  What happened?  The TypeError exception is complaining that Foo.foo must be called with an instance of Foo as the first argument.  <em>(NB: we&#8217;re calling the unbound method on the class here, not a bound method on the instance, which is why we need to pass in &#8217;self&#8217; as the first argument.  This is typical when calling your parent class)</em></p>
<p>But wait!  Isn&#8217;t Bar a sub-class of Foo?  And why did this work before?  Let&#8217;s try this again, but let&#8217;s watch what happens to Foo and Bar this time, using the <a href="http://docs.python.org/library/functions.html#id">id()</a> function:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> foo
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b = foo.<span style="color: black;">Bar</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>foo.<span style="color: black;">Bar</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">3217664</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">reload</span><span style="color: black;">&#40;</span>foo<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>module <span style="color: #483d8b;">'foo'</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #483d8b;">'foo.pyc'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>foo.<span style="color: black;">Bar</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">3218592</span></pre></div></div>

<p><em>(The <a href="http://docs.python.org/library/functions.html#id">id()</a> function returns a unique identifier for objects in python; if two objects have the same id, then they refer to the same object)</em></p>
<p>The id&#8217;s are different, which means that we get a new Bar class after we reload&#8230;I guess that makes sense.  Take a look at our b object, which was created before the reload:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> b.__class__
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'foo.Bar'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>b.__class__<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">3217664</span></pre></div></div>

<p>So b is an instance of the <em>old</em> Bar class, not the new one.  Let&#8217;s look deeper:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> b.__class__.__bases__
<span style="color: black;">&#40;</span><span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'foo.Foo'</span><span style="color: #66cc66;">&gt;</span>,<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>b.__class__.__bases__<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">3216336</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>foo.<span style="color: black;">Foo</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">3218128</span></pre></div></div>

<p>A ha!  The old Bar&#8217;s base class (Foo) is different than what&#8217;s currently defined in the module.  After we reloaded the foo module, the Foo class was redefined, which is presumably what we want.  The unfortunate side effect of this is that any references by name to the class &#8216;Foo&#8217; will pick up the new Foo class, including <strong>code in methods of subclasses</strong>.  There are probably other places where this has unexpected results, but for us, this is the biggest problem.</p>
<p>Reloading essentially breaks class inheritance for objects whose lifetime spans the reload.  Using <a href="http://docs.python.org/library/functions.html#super">super()</a> in the normal way doesn&#8217;t even work, since you usually refer to your instance&#8217;s class by name:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Bar<span style="color: black;">&#40;</span>Foo<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Bar.foo&quot;</span>
        <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>Bar, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">foo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>If you&#8217;re using new-style classes, it looks like you can get around this by looking at your __class__ attribute:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Bar<span style="color: black;">&#40;</span>Foo<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Bar.foo&quot;</span>
        <span style="color: #008000;">super</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.__class__, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">foo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Buildbot isn&#8217;t using new-style classes&#8230;yet&#8230;so we can&#8217;t use super().  Another workaround I&#8217;m playing around with is to use the inspect module to get at the class hierarchy:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> get_parent<span style="color: black;">&#40;</span>obj, n=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">inspect</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">inspect</span>.<span style="color: black;">getmro</span><span style="color: black;">&#40;</span>obj.__class__<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>n<span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Bar<span style="color: black;">&#40;</span>Foo<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Bar.foo&quot;</span>
        get_parent<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">foo</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2008/11/21/python-reload-danger-here-be-dragons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>nmudiff is awesome</title>
		<link>http://atlee.ca/blog/2008/05/15/nmudiff-is-awesome/</link>
		<comments>http://atlee.ca/blog/2008/05/15/nmudiff-is-awesome/#comments</comments>
		<pubDate>Thu, 15 May 2008 19:23:42 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[diff]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/?p=169</guid>
		<description><![CDATA[Man, I wish I had known about this before!
nmudiff is a program to email an NMU diff to the Debian Bug Tracking System.
I often make quick little changes to debian packages to fix bugs or typos, and it&#8217;s always been a bit of a pain to generate a patch to send to the maintainer.
nmudiff uses [...]]]></description>
			<content:encoded><![CDATA[<p>Man, I wish I had known about this before!</p>
<p>nmudiff is a program to email an NMU diff to the Debian Bug Tracking System.</p>
<p>I often make quick little changes to debian packages to fix bugs or typos, and it&#8217;s always been a bit of a pain to generate a patch to send to the maintainer.</p>
<p>nmudiff uses debdiff (another very useful command I just learned about) to generate the patch, and email it to the bug tracking system with the appropriate tags.</p>
]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2008/05/15/nmudiff-is-awesome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Should have done this a long time ago&#8230;</title>
		<link>http://atlee.ca/blog/2008/04/11/should-have-done-this-a-long-time-ago/</link>
		<comments>http://atlee.ca/blog/2008/04/11/should-have-done-this-a-long-time-ago/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 19:47:19 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/2008/04/11/should-have-done-this-a-long-time-ago/</guid>
		<description><![CDATA[In zsh:

alias ':q'=exit

I can&#8217;t count the number of times I&#8217;ve typed &#8216;:q&#8217; by mistake in a shell expecting it to quit.
Now it will  
]]></description>
			<content:encoded><![CDATA[<p>In zsh:</p>
<p><code><br />
alias ':q'=exit<br />
</code></p>
<p>I can&#8217;t count the number of times I&#8217;ve typed &#8216;:q&#8217; by mistake in a shell expecting it to quit.</p>
<p>Now it will <img src='http://atlee.ca/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2008/04/11/should-have-done-this-a-long-time-ago/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting free diskspace in python</title>
		<link>http://atlee.ca/blog/2008/02/23/getting-free-diskspace-in-python/</link>
		<comments>http://atlee.ca/blog/2008/02/23/getting-free-diskspace-in-python/#comments</comments>
		<pubDate>Sat, 23 Feb 2008 21:05:33 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/2008/02/23/getting-free-diskspace-in-python/</guid>
		<description><![CDATA[To calculate the amount of free disk space in Python, you can use the os.stafvfs() function.
For some reason, I can never find the docs for os.statvfs() on the first or second try (it&#8217;s in the &#8220;Files and Directories&#8221; section in the os module), and I never remember how it works, so I&#8217;m posting this as [...]]]></description>
			<content:encoded><![CDATA[<p>To calculate the amount of free disk space in <a href="http://python.org/">Python</a>, you can use the <a href="http://docs.python.org/lib/os-file-dir.html">os.stafvfs()</a> function.</p>
<p>For some reason, I can never find the docs for os.statvfs() on the first or second try (it&#8217;s in the &#8220;Files and Directories&#8221; section in the os module), and I never remember how it works, so I&#8217;m posting this as a note to myself, and maybe to help out anybody else wanting to do the same thing.</p>
<p>A simple free space function can be written as:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">def</span> freespace<span style="color: black;">&#40;</span>p<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Returns the number of free bytes on the drive that ``p`` is on
    &quot;&quot;&quot;</span>
    s = <span style="color: #dc143c;">os</span>.<span style="color: #dc143c;">statvfs</span><span style="color: black;">&#40;</span>p<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> s.<span style="color: black;">f_bsize</span> <span style="color: #66cc66;">*</span> s.<span style="color: black;">f_bavail</span></pre></div></div>

<p>I use the <strong>f_bavail</strong> attribute instead of <strong>f_bfree</strong>, since the latter includes blocks that are reserved for the the super-user&#8217;s use.</p>
<p>I&#8217;m not sure, however, on the distinction between <strong>f_bsize</strong> and <strong>f_frsize</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2008/02/23/getting-free-diskspace-in-python/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Flash on 64 bit linux in 3 easy steps</title>
		<link>http://atlee.ca/blog/2007/04/03/flash-on-64-bit-linux-in-3-easy-steps/</link>
		<comments>http://atlee.ca/blog/2007/04/03/flash-on-64-bit-linux-in-3-easy-steps/#comments</comments>
		<pubDate>Tue, 03 Apr 2007 16:31:01 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/2007/04/03/flash-on-64-bit-linux-in-3-easy-steps/</guid>
		<description><![CDATA[
aptitude/apt-get/wajig install nspluginwrapper
Download and unpack flash from www.adobe.com, and run linux32 ./flashplayer-installer
nspluginwrapper -i $HOME/.mozilla/plugins/libflashplayer.so

]]></description>
			<content:encoded><![CDATA[<ol>
<li>aptitude/apt-get/wajig install nspluginwrapper</li>
<li>Download and unpack flash from www.adobe.com, and run linux32 ./flashplayer-installer</li>
<li>nspluginwrapper -i $HOME/.mozilla/plugins/libflashplayer.so</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2007/04/03/flash-on-64-bit-linux-in-3-easy-steps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
