<?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>Fri, 27 Jan 2012 19:08:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>cURL and paste</title>
		<link>http://atlee.ca/blog/2011/08/16/curl-and-paste/</link>
		<comments>http://atlee.ca/blog/2011/08/16/curl-and-paste/#comments</comments>
		<pubDate>Wed, 17 Aug 2011 04:17:31 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://atlee.ca/blog/?p=975</guid>
		<description><![CDATA[cURL and paste&#8230;two great tastes that apparently don&#8217;t go well at all together! I&#8217;ve been writing a bunch of simple wsgi apps lately, some of which handle file uploads. Take this tiny application: import webob &#160; def app&#40;environ, start_response&#41;: req = webob.Request&#40;environ&#41; req.body_file.read&#40;&#41; return webob.Response&#40;&#34;OK!&#34;&#41;&#40;environ, start_response&#41; &#160; import paste.httpserver paste.httpserver.serve&#40;app, port=8090&#41; Then throw some files [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://curl.haxx.se/" target="_blank">cURL</a> and <a href="http://pythonpaste.org/" target="_blank">paste</a>&#8230;two great tastes that apparently don&#8217;t go well at all together!</p>
<p>I&#8217;ve been writing a bunch of simple <a href="http://wsgi.org/wsgi/" target="_blank">wsgi</a> apps lately, some of which handle file uploads.</p>
<p>Take this tiny application:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> webob
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> app<span style="color: black;">&#40;</span>environ, start_response<span style="color: black;">&#41;</span>:
    req = webob.<span style="color: black;">Request</span><span style="color: black;">&#40;</span>environ<span style="color: black;">&#41;</span>
    req.<span style="color: black;">body_file</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> webob.<span style="color: black;">Response</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;OK!&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#40;</span>environ, start_response<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> paste.<span style="color: black;">httpserver</span>
paste.<span style="color: black;">httpserver</span>.<span style="color: black;">serve</span><span style="color: black;">&#40;</span>app, port=<span style="color: #ff4500;">8090</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Then throw some files at it with cURL:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>catlee<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">%</span> <span style="color: #000000; font-weight: bold;">for</span> f <span style="color: #000000; font-weight: bold;">in</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #660033;">-type</span> f<span style="color: #7a0874; font-weight: bold;">&#41;</span>; <span style="color: #000000; font-weight: bold;">do</span> <span style="color: #000000; font-weight: bold;">time</span> curl <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>; <span style="color: #000000; font-weight: bold;">done</span>
curl <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.00s user 0.00s system <span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">1.013</span> total
curl <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.01s user 0.00s system <span style="color: #000000;">63</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">0.013</span> total
curl <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.01s user 0.00s system <span style="color: #000000;">64</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">0.012</span> total
curl <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.01s user 0.00s system <span style="color: #000000;">81</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">0.015</span> total
curl <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.01s user 0.00s system <span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">1.014</span> total
curl <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.00s user 0.00s system <span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">1.009</span> total</pre></div></div>

<p>Huh? Some files take a second to upload?</p>
<p>I discovered after much digging, and rewriting my (more complicated) app several times, that the problem is that cURL sends an extra &#8220;Expect: 100-continue&#8221; header. This is supposed to let a web server respond with &#8220;100 Continue&#8221; immediately or reject an upload based on the request headers.</p>
<p>The problem is that paste&#8217;s httpserver doesn&#8217;t send this by default, and so cURL will wait for a second before giving up and sending the rest of the request.</p>
<p>The magic to turn this off is the &#8216;-0&#8242; to cURL, which forces HTTP/1.0 mode:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>catlee<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">%</span> <span style="color: #000000; font-weight: bold;">for</span> f <span style="color: #000000; font-weight: bold;">in</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #660033;">-type</span> f<span style="color: #7a0874; font-weight: bold;">&#41;</span>; <span style="color: #000000; font-weight: bold;">do</span> <span style="color: #000000; font-weight: bold;">time</span> curl <span style="color: #660033;">-0</span> <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>; <span style="color: #000000; font-weight: bold;">done</span>
curl <span style="color: #660033;">-0</span> <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.00s user 0.00s system <span style="color: #000000;">66</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">0.012</span> total
curl <span style="color: #660033;">-0</span> <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.01s user 0.00s system <span style="color: #000000;">64</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">0.012</span> total
curl <span style="color: #660033;">-0</span> <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.00s user 0.01s system <span style="color: #000000;">58</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">0.014</span> total
curl <span style="color: #660033;">-0</span> <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.01s user 0.00s system <span style="color: #000000;">66</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">0.012</span> total
curl <span style="color: #660033;">-0</span> <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.00s user 0.00s system <span style="color: #000000;">59</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">0.013</span> total
curl <span style="color: #660033;">-0</span> <span style="color: #660033;">-s</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #660033;">--data-binary</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$f</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8090</span>  0.01s user 0.00s system <span style="color: #000000;">65</span><span style="color: #000000; font-weight: bold;">%</span> cpu <span style="color: #000000;">0.012</span> total</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2011/08/16/curl-and-paste/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Linux on a new Thinkpad T510</title>
		<link>http://atlee.ca/blog/2010/10/27/linux-on-a-new-thinkpad-t510/</link>
		<comments>http://atlee.ca/blog/2010/10/27/linux-on-a-new-thinkpad-t510/#comments</comments>
		<pubDate>Wed, 27 Oct 2010 19:19:27 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[Hardware]]></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=759</guid>
		<description><![CDATA[I got a new Thinkpad T510 at work to replace my aging MacBook Pro. I asked for a Thinkpad instead of another MacBook because I wanted hardware with better hardware support, in particular the trackpad. I got into the habit of bringing a USB mouse everywhere I went because the trackpad on the MacBook was [...]]]></description>
			<content:encoded><![CDATA[<p>I got a new Thinkpad T510 at work to replace my aging MacBook Pro.  I asked for a Thinkpad instead of another MacBook because I wanted hardware with better hardware support, in particular the trackpad.  I got into the habit of bringing a USB mouse everywhere I went because the trackpad on the MacBook was so unreliable on linux.</p>
<p>So when my new T510 arrived, I was pretty excited.  And, except for one tiny problem (of the PEBKAC kind), transferring all my files from the old machine to the new one went flawlessly.</p>
<p>Here&#8217;s how I set up the new machine:</p>
<ul>
<li>Download image from <a href="http://www.sysresccd.org/Download">sysresccd.org</a>.  Follow the <a href="http://www.sysresccd.org/Sysresccd-manual-en_How_to_install_SystemRescueCd_on_an_USB-stick">instructions</a> to make a bootable USB drive.</li>
<li>Boot up computer off USB drive.  Resize the existing NTFS partition to be really small.  Add 2 new partitions in the new-free space: one for the boot partition for linux, and one to be encrypted and be formatted with lvm.</li>
<li>Format boot partition as ext3.  Setup encrypted partition with &#8216;cryptsetup luksFormat /dev/sda6; cryptsetup luksOpen /dev/sda6 crypt_sda6&#8242;.  Setup LVM with &#8216;pvcreate /dev/mapper/crypt_sda6&#8242;.  Setup two volumes, one for swap, and one for the root partition.</li>
<li>Connect network cable between old laptop and new one.  Configure local network.</li>
<li>Copy files from old /boot to new /boot.</li>
<li>Copy files from old / to new /.  Here&#8217;s where I messed up.  My command was: &#8216;rsync -aPxX 192.168.2.1:/ /target/&#8217;.</li>
<li>Install grub.</li>
<li>Reboot!</li>
</ul>
<p>At this point the machine came up ok, but wasn&#8217;t prompting to decrypt my root drive, and so I had to do some manual steps to get the root drive to mount initially.  Fixing up /etc/crypttab and the initramfs solved this.</p>
<p>However even after this I was having some problems.  I couldn&#8217;t connect to wireless networks with Network Manager.  I couldn&#8217;t run gnome-power-manager.  Files in /var/lib/mysql were owned by ntp!  Then I realized that my initial rsync had copied over files preserving the user/group <strong>names</strong>, not the uid/gid values.  And since I wasn&#8217;t booting off a Debian image, the id/name mappings were quite different.  Re-running rsync with &#8216;&#8211;numeric-ids&#8217; got all the ownerships fixed up.  After the next reboot things were working flawlessly.</p>
<p>Now after a few weeks of using it, I&#8217;m enjoying it a lot more than my MacBook Pro.  It boots up faster.  It connects to wireless networks faster.  It suspends/unsuspends faster.  It&#8217;s got real, live, page-up/page-down keys!  The trackpad actually works!</p>
]]></content:encoded>
			<wfw:commentRss>http://atlee.ca/blog/2010/10/27/linux-on-a-new-thinkpad-t510/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<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 ``p`` is on &#34;&#34;&#34; [...]]]></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 a [...]]]></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 this useful! [...]]]></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 [...]]]></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, [...]]]></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 &#8216;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>1</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 [...]]]></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>
	</channel>
</rss>

