<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1388352290632479227</id><updated>2012-01-20T14:40:42.934-05:00</updated><category term='i18n'/><category term='floss'/><category term='packaging'/><category term='opensource'/><category term='python'/><category term='debugging'/><category term='test drive'/><category term='servers'/><category term='python3'/><category term='debian'/><category term='otone'/><category term='mailman'/><category term='virtual machine'/><category term='music'/><category term='onote'/><category term='ubuntu'/><category term='canonical'/><category term='uds-o'/><title type='text'>Pumpichank</title><subtitle type='html'>We Fear Change</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.wefearchange.org/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>46</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-4100272120662564024</id><published>2012-01-18T19:05:00.000-05:00</published><updated>2012-01-18T19:14:11.692-05:00</updated><title type='text'>Debian packaging for Python 2 and 3</title><content type='html'>Time for another installment of my &lt;a href="http://www.wefearchange.org/2011/12/lessons-in-porting-to-python-3.html"&gt;ongoing&lt;/a&gt; &lt;a href="http://www.wefearchange.org/2012/01/python-3-porting-fun-redux.html"&gt;mission&lt;/a&gt; to convert the world to Python 3!&amp;nbsp; This time, a little Debian packaging-fu for modifying an existing Python 2 package to include support for Python 3 from the same source package.&lt;br /&gt;&lt;br /&gt;Today, I added a python3-feedparser package to Ubuntu Precise.&amp;nbsp; What's interesting about this is that, despite &lt;a href="https://code.google.com/p/feedparser/issues/detail?id=320"&gt;various&lt;/a&gt; &lt;a href="https://code.google.com/p/feedparser/issues/detail?id=323"&gt;reported&lt;/a&gt; problems, &lt;a href="https://code.google.com/p/feedparser/"&gt;upstream feedparser 5.1&lt;/a&gt; claims to support Python 3, via &lt;a href="http://docs.python.org/py3k/library/2to3.html"&gt;2to3&lt;/a&gt; conversion.&amp;nbsp; And indeed it does (although the test suite does not).&lt;br /&gt;&lt;br /&gt;Before today, Ubuntu had &lt;a href="https://launchpad.net/ubuntu/precise/+source/feedparser"&gt;feedparser&lt;/a&gt; 5.0.1 in its archive, and while some work has been done to update the &lt;a href="http://anonscm.debian.org/viewvc/python-modules/packages/feedparser/trunk/debian/changelog?view=markup"&gt;Debian package to 5.1&lt;/a&gt;, this has not been released.&amp;nbsp; The uninteresting precursor to Python 3 packaging was to upgrade the Ubuntu version of the python-feedparser source package to 5.1.&amp;nbsp; I'll spare you the boring details about missing data files in the upstream tarball, and other problems, since they don't really relate to the Python 3 effort.&lt;br /&gt;&lt;br /&gt;The first step was to verify that feedparser 5.1 works with Python 3.2 in a virtualenv, and indeed it does.&amp;nbsp; This is good news because it means that the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;setup.py&lt;/span&gt; does the right thing, which is always the best way to start supporting Python 3.&amp;nbsp; I've found that it's much easier to build a solid Debian package if you have a solid &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;setup.py&lt;/span&gt; in upstream to begin with.&lt;br /&gt;&lt;br /&gt;Now, what I'd like to do is to give you a recipe for modifying your existing &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;debian/&lt;/span&gt; directory files to add Python 3 support to a package that already exists for Python 2.&amp;nbsp; This is a little trickier for feedparser because it used an older &lt;a href="http://manpages.ubuntu.com/manpages/intrepid/man7/debhelper.7.html"&gt;debhelper&lt;/a&gt; standard, and carried some crufty old stuff in its rules file.&amp;nbsp; My first step was to update this to debhelper compatibility level 8 and greatly simplify the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;debian/rules&lt;/span&gt; file.&amp;nbsp; Here's what it might have looked like with just Python 2 support, so let's start there.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#!/usr/bin/make -f&lt;br /&gt;export DH_VERBOSE=1&lt;br /&gt;&lt;br /&gt;%:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dh $@ --with python2&lt;br /&gt;&lt;br /&gt;override_dh_auto_clean:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dh_auto_clean&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rm -rf build .*egg-info&lt;br /&gt;&lt;br /&gt;override_dh_auto_test:&lt;br /&gt;ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cd feedparser &amp;amp;&amp;amp; python ./feedparsertest.py&lt;br /&gt;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @echo "nocheck set, not running tests"&lt;br /&gt;endif&lt;br /&gt;&lt;br /&gt;override_dh_installdocs:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dh_installdocs -Xtests&lt;/blockquote&gt;&lt;br /&gt;This is all pretty standard stuff.&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh_python2&lt;/span&gt; is used (the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;--with python2&lt;/span&gt; option to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh&lt;/span&gt;), and we just provide a couple of overrides for idiosyncrasies in the feedparser package.&amp;nbsp; We clean a couple of extra things that aren't cleaned automatically, and we run the test suite in the slightly non-standard way that upstream requires.&amp;nbsp; Also, we override the installation of a huge amount of test files that would otherwise get installed as documentation (they aren't docs).&lt;br /&gt;&lt;br /&gt;So far so good.&amp;nbsp; What do we have to do to add support for Python 3?&lt;br /&gt;&lt;br /&gt;First, we need to make a few modifications to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;debian/control&lt;/span&gt; file.&amp;nbsp; The current convention with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh_python2&lt;/span&gt; is to use an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;X-Python-Version&lt;/span&gt; header in the source package stanza, so we just need to add this header to the same stanza for Python 3:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;X-Python3-Version: &amp;gt;= 3.2&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;This just says we support any Python 3 version from 3.2 onwards.&amp;nbsp; You also need to add a few additional packages to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Build-Depends&lt;/span&gt;.&amp;nbsp; In the feedparser case, I added the following build dependencies: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python3&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python3-chardet&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python3-setuptools&lt;/span&gt;.&amp;nbsp; Even though for Python 2 there are a couple of other build dependencies (e.g. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python-libxml2&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python-utidylib&lt;/span&gt;) these aren't available for Python 3, but lucky for us, they are optional anyway.&lt;br /&gt;&lt;br /&gt;Next, you need to add a new binary package stanza.&amp;nbsp; There was already a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python-feedparser&lt;/span&gt; binary package stanza for Python 2 support.&amp;nbsp; In Debian, Python 3 is provided as a separate stack, meaning packages for Python 3 will always start with the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python3-&lt;/span&gt; prefix.&amp;nbsp; Thus, it is pretty easy to just copy the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python-feedparser&lt;/span&gt; stanza and paste it to the bottom of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;debian/rules&lt;/span&gt;, changing the package name to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python3-feedparser&lt;/span&gt;.&amp;nbsp; You have to update the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Depends&lt;/span&gt; line to use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;${python3:Depends}&lt;/span&gt; and I updated the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Recommends&lt;/span&gt; line to name &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python3-chardet&lt;/span&gt;, and that was about it.&amp;nbsp; Here's what the new stanza looks like:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Package: python3-feedparser&lt;br /&gt;Architecture: all&lt;br /&gt;Depends: ${misc:Depends}, ${python3:Depends}&lt;br /&gt;Recommends: python3-chardet&lt;br /&gt;Description: Universal Feed Parser for Python&lt;br /&gt;&amp;nbsp;Python module for downloading and parsing syndicated feeds. It can&lt;br /&gt;&amp;nbsp;handle RSS 0.90, Netscape RSS 0.91, Userland RSS 0.91, RSS 0.92, RSS&lt;br /&gt;&amp;nbsp;0.93, RSS 0.94, RSS 1.0, RSS 2.0, Atom, and CDF feeds.&lt;br /&gt;&amp;nbsp;.&lt;br /&gt;&amp;nbsp;It provides the same API to all formats, and sanitizes URIs and HTML.&lt;br /&gt;&amp;nbsp;.&lt;br /&gt;&amp;nbsp;This is the Python 3 version of the package.&lt;/blockquote&gt;Again, so far so good.&amp;nbsp; Now let's look at the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;debian/rules&lt;/span&gt; file.&lt;br /&gt;&lt;br /&gt;The first thing to do is to add support for &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh_python3&lt;/span&gt;, which is analogous to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh_python2&lt;/span&gt;, and is the only accepted helper for Python 3.&amp;nbsp; The rules line then becomes:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;%:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dh $@ --with python2,python3&lt;/blockquote&gt;Now, one problem with debhelper is that it doesn't have any built-in support for Python 3 like it does for Python 2.&amp;nbsp; This means &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh&lt;/span&gt; will not automatically build or install any Python 3 packages, so you have to do this manually.&amp;nbsp; Eventually, &lt;a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=597105"&gt;this will be fixed&lt;/a&gt;, and fortunately with a solid &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;setup.py&lt;/span&gt; file, you don't have to do to much, but it's something to be aware of.&amp;nbsp; In the feedparser case, we need to add overrides for &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh_auto_build&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh_auto_install&lt;/span&gt;.&amp;nbsp; Here's what these rules look like:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;override_dh_auto_build:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dh_auto_build&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; set -ex; for python in $(shell py3versions -r); do \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $$python setup.py build; \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; done;&lt;br /&gt;&lt;br /&gt;override_dh_auto_install:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dh_auto_install&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; set -ex; for python in $(shell py3versions -r); do \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $$python setup.py install --root=$(CURDIR)/debian/tmp --install-layout=deb; \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; done;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cp feedparser/sgmllib3.py $(CURDIR)/debian/tmp/usr/lib/python3/dist-packages/feedparser_sgmllib3.py&lt;/blockquote&gt;Not too bad, eh?&amp;nbsp; You'll notice that the first thing these rules do is call the standard &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh_auto_build&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh_auto_install&lt;/span&gt; respectively.&amp;nbsp; This preserves the Python 2 support.&amp;nbsp; Then we just loop over all the available Python 3 versions, doing a fairly normal equivalent of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;setup.py install&lt;/span&gt; (split into a build step and an install step).&amp;nbsp; The install rule looks a little odd, but should be familiar to Debian Python hackers.&amp;nbsp; It just installs the package into the proper Debian locations, and will pretty much be the same for any Python 3 package you build.&lt;br /&gt;&lt;br /&gt;The one odd bit is the last line in the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;override_dh_auto_install&lt;/span&gt; rule.&amp;nbsp; This is there just to work around an peculiarity in the feedparser 5.1 upstream package, where it depends on &lt;a href="http://docs.python.org/library/sgmllib.html"&gt;sgmllib.py,&lt;/a&gt; but that is no longer in the Python standard library in Python 3.&amp;nbsp; Upstream provides an already 2to3 converted version of it, and recommends you install the module as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sgmllib.py&lt;/span&gt; somewhere on your Python 3 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sys.path&lt;/span&gt;.&amp;nbsp; Well, I don't like the namespace pollution that would cause, so I install the file as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;feedparser_sgmllib3.py&lt;/span&gt; and add a &lt;a href="http://wiki.debian.org/UsingQuilt"&gt;quilt patch&lt;/a&gt; to the package to try an import of that module if importing &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sgmllib&lt;/span&gt; fails (as it will on Python 3).&lt;br /&gt;&lt;br /&gt;An aside: If you look in the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;debian/rules&lt;/span&gt; file for what I actually uploaded, you'll see some additional modifications to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;override_dh_auto_test&lt;/span&gt;.&amp;nbsp; This just works around the upstream bug where some test suite data files were accidentally omitted from the release tarball.&amp;nbsp; You can pretty much ignore those lines for the purposes of this article.&lt;br /&gt;&lt;br /&gt;We're almost done.&amp;nbsp; The last thing we need to do is make sure that debhelper installs the right files into the right binary packages.&amp;nbsp; We want the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python-feedparser&lt;/span&gt; binary package to include only the Python 2 files, and the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python3-feedparse&lt;/span&gt;r binary package to only include the Python 3 files.&amp;nbsp; Keep in mind that when a source package builds only a single binary package (as was the case before I added Python 3 support), debhelper will include everything under the build directory's &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;debian/tmp&lt;/span&gt; subdirectory in the single binary package.&amp;nbsp; That's why you see things get installed into &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$(CURDIR)/debian/tmp&lt;/span&gt;.&amp;nbsp; But when a source package builds multiple binary packages, as is now the case here, we have to tell debhelper which files go into which binary packages.&amp;nbsp; We do this by adding two new files to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;debian&lt;/span&gt; directory: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python-feedparser.install&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python3-feedparser.install&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Reading the manpage for &lt;a href="http://manpages.ubuntu.com/manpages/precise/man1/dh_install.1.html"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dh_install&lt;/span&gt;&lt;/a&gt; will explain the reasons for this, and describe the format of the file contents.&amp;nbsp; In our case, we're really lucky, because for Python 2, everything gets installed under &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;usr/lib/python2.*&lt;/span&gt; and in Python 3, everything gets installed under &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;usr/lib/python3&lt;/span&gt; (relative to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$(CURDIR)/debian/tmp&lt;/span&gt;).&amp;nbsp; You'll notice a few things here.&amp;nbsp; Because we could be building for multiple versions of Python 2, we have to wildcard the actual directory under &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;usr/lib&lt;/span&gt;, e.g. it might be &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python2.6&lt;/span&gt; or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python2.7&lt;/span&gt;.&amp;nbsp; But because we have &lt;a href="http://www.python.org/dev/peps/pep-3147/"&gt;PEP 3147&lt;/a&gt; and &lt;a href="http://www.python.org/dev/peps/pep-3149/"&gt;PEP 3149&lt;/a&gt; in Python 3.2, there's only one directory for all supported versions of Python 3, so we don't need to wildcard the subdirectory.&amp;nbsp; Also, if you look at the actual &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.install&lt;/span&gt; files in the package, you'll see a few other trailing path components, so the actual contents of the files are:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;usr/lib/python2.*/*-packages/*&lt;/blockquote&gt;and&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;usr/lib/python3/*-packages/*&lt;/blockquote&gt;for the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python-feedparser.install&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python3-feedparser.install&lt;/span&gt; files respectively.&amp;nbsp; The trailing bits just wildcard what on a Debian system will always be &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dist-packages&lt;/span&gt;, just for safety (cargo culting FTW!).&lt;br /&gt;&lt;br /&gt;And that really is it!&amp;nbsp; Of course, things could be a little more complicated if you have extension modules, but maybe not that much more so, and if the package you're adding Python 3 support to isn't &lt;a href="http://pypi.python.org/pypi/distribute"&gt;setuptools&lt;/a&gt;-based, you may have more work to do even still.&amp;nbsp; The feedparser package has a few other oddities that are really unrelated to adding Python 3 support, so I'm ignoring them here, but feel free to ask for additional details in the comments, in IRC, or in email.&lt;br /&gt;&lt;br /&gt;Hopefully this gives you some insight into how to extend an existing Python 2 Debian package into including Python 3 support, given that your upstream already supports Python 3.&amp;nbsp; Now, go forth and hack!&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Addendum&lt;/i&gt;: my colleague &lt;a href="http://www.chiark.greenend.org.uk/ucgi/%7Ecjwatson/blosxom"&gt;Colin Watson&lt;/a&gt; just today packaged up &lt;a href="http://blog.python.org/2011/03/meet-team-benjamin-peterson.html"&gt;Benjamin Peterson&lt;/a&gt;'s very fine Python package called &lt;a href="http://pypi.python.org/pypi/six/1.1.0"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;six&lt;/span&gt;&lt;/a&gt;.&amp;nbsp; This is a nice package that provides some excellent Python 2 and 3 compatibility utilities.&amp;nbsp; You may find this helpful if you're trying to support both Python 2 and Python 3 in a single code base, especially if you have to support back to Python 2.4 (poor you :).&amp;nbsp; This will be available in Ubuntu Precise, although if you're submitting patches back upstream, you may have to convince the upstream author to accept the additional dependency.&amp;nbsp; It's worth it to add a little more Python 3 love to the world.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-4100272120662564024?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/4100272120662564024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2012/01/debian-package-for-python-2-and-3.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4100272120662564024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4100272120662564024'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2012/01/debian-package-for-python-2-and-3.html' title='Debian packaging for Python 2 and 3'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-3297811300221918582</id><published>2012-01-06T12:27:00.002-05:00</published><updated>2012-01-07T16:14:40.415-05:00</updated><title type='text'>Python 3 Porting Fun Redux</title><content type='html'>My &lt;a href="http://www.wefearchange.org/2011/12/lessons-in-porting-to-python-3.html"&gt;last post on Python 3 porting&lt;/a&gt; got some really great responses, and I've learned a lot from the feedback I've seen.&amp;nbsp; I'm here to rather briefly outline a few additional tips and tricks that folks have sent me and that I've learned by doing other ports since then.&amp;nbsp; Please keep them coming, either in the blog comments or to me via email.&amp;nbsp; Or better yet, blog about your experiences yourself and I'll link to them from here.&lt;br /&gt;&lt;br /&gt;One of the big lessons I'm trying to adopt is to support Python 3 in pure-Python code with a single code base.&amp;nbsp; Specifically, I'm trying to avoid using &lt;a href="http://docs.python.org/py3k/library/2to3.html"&gt;2to3&lt;/a&gt; as much as possible.&amp;nbsp; While I think 2to3 is an excellent tool that can make it easier to get started supporting both Python 2 and Python 3 from a single branch of code, it does have some disadvantages.&amp;nbsp; The biggest problem with 2to3 is that it's slow; it can take a long time to slog through your Python code, which can be a significant impediment to your development velocity.&amp;nbsp; Another 2to3 problem is that it doesn't always play nicely with other development tools, such as &lt;a href="http://packages.python.org/distribute/setuptools.html#test"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;python setup.py test&lt;/span&gt;&lt;/a&gt; and &lt;a href="http://pypi.python.org/pypi/virtualenv"&gt;virtualenv&lt;/a&gt;, and you occasionally have to write additional custom fixers for conversion that 2to3 doesn't handle.&lt;br /&gt;&lt;br /&gt;Given that almost all the code I'm writing these days targets Python 2.6 as the minimal supported Python 2 version, 2to3 may just be unnecessary.&amp;nbsp; With my &lt;a href="https://bugs.freedesktop.org/show_bug.cgi?id=26420"&gt;dbus-python port to Python 3&lt;/a&gt;, and with my own &lt;a href="http://pypi.python.org/pypi?%3Aaction=search&amp;amp;term=flufl&amp;amp;submit=search"&gt;flufl&lt;/a&gt; packages, I'm experimenting with ignoring 2to3 and trying to write one code base for all of Python 2.6, 2.7, and 3.2.&amp;nbsp; My colleague &lt;a href="http://www.voidspace.org.uk/python/weblog/index.shtml"&gt;Michael Foord&lt;/a&gt; has been pretty successful with this approach going back all the way to Python 2.4, so 2.6 as a minimum should be no problem!&amp;nbsp; C extensions are pretty easy because you have the C preprocessor to help you.&amp;nbsp; But it turns out that it's usually not too difficult in pure-Python either.&amp;nbsp; I've done this in my latest release of the &lt;a href="http://pypi.python.org/pypi/flufl.bounce/2.0"&gt;flufl.bounce&lt;/a&gt; package, and intend to eliminate 2to3 in my other flufl packages soon too.&lt;br /&gt;&lt;br /&gt;The first thing I've done is add &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;print_function&lt;/span&gt; to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;__future__&lt;/span&gt; import in all my modules.&amp;nbsp; Previously, I was only importing &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;unicode_literals&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;absolute_import&lt;/span&gt;.&amp;nbsp; But doctests tend to use a lot of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;print&lt;/span&gt; statements, so switching to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;print()&lt;/span&gt; function explicitly removes one big 2to3 conversion.&amp;nbsp; Aside from having to unlearn decades of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;print&lt;/span&gt; statement muscle memory, the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;print()&lt;/span&gt; function is actually rather nice.&amp;nbsp; So my module template now looks like this (with the copyright comment block omitted):&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;from __future__ import absolute_import, print_function, unicode_literals&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;__metaclass__ = type&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;__all__ = [&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;Speaking of doctests, you really want them to have the same set of future imports as all your other code.&amp;nbsp; I'll talk more about how my own packages set up doctests later, but for now, it's useful to know that I create a &lt;a href="http://docs.python.org/py3k/library/doctest.html#doctest.DocFileSuite"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;doctest.DocFileSuite&lt;/span&gt;&lt;/a&gt; for every doctest in my package.&amp;nbsp; These suites all have a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;setup()&lt;/span&gt; function and Python's testing framework will call these at the appropriate time, passing in a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;testobj&lt;/span&gt; parameter.&amp;nbsp; This argument has a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;globs&lt;/span&gt; attribute which serves as the module globals for the doctest.&amp;nbsp; All you need to do to enable the future imports in your doctests is to do something like this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;def setup(testobj):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; testobj.globs['absolute_import'] = absolute_import&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; testobj.globs['print_function'] = print_function&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; testobj.globs['unicode_literals'] = unicode_literals&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; except NameError:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pass&lt;/blockquote&gt;&lt;br /&gt;The try-except really is only necessary if you keep using 2to3, since that tool will remove the future imports from all the modules it processes.&amp;nbsp; The future imports still exist in Python 3 of course, since future imports are never, ever removed.&amp;nbsp; So if you ditch 2to3, you can get rid of the try-except too.&lt;br /&gt;&lt;br /&gt;In the latest release of flufl.bounce, I changed the API so that the detected email addresses are all explicitly bytes objects in Python 3 (and 8-bit strings in Python 2).&amp;nbsp; This caused some problems with my doctests because the repr of Python 3 bytes objects is different than the repr of 8-bit strings in Python 2.&amp;nbsp; When you print the object in Python 2, you get just the contents of the string, but when you print them in Python 3, you get the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;b''&lt;/span&gt;-prefix.&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;% python&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Python 2.7.2+ (default, Dec 18 2011, 17:30:39) &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[GCC 4.6.2] on linux2&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; print b'foo'&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;foo&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;% python3&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Python 3.2.2+ (default, Dec 19 2011, 12:03:32) &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[GCC 4.6.2] on linux2&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; print(b'foo')&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;b'foo'&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This means your doctest cannot be written to easily support both versions of Python when bytes/8-bit strings are used.&amp;nbsp; I use the following helper to get around this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;def print_bytes(obj):&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if bytes is not str:&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; obj = repr(obj)[2:-1]&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print(obj)&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Remember that in Python 2, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bytes&lt;/span&gt; is just an alias for &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;str&lt;/span&gt; so this code only gets invoked in Python 3.&lt;br /&gt;&lt;br /&gt;Another fun bytes/8-bit-string issue is that in Python 3, bytes objects have no &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.format() &lt;/span&gt;method.&amp;nbsp; So if you're doing something like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;b'foo {0}'.format(obj)&lt;/span&gt; this will work in Python 2, but fail in Python 3. The best I've come up with for this is to use concatenation instead, or do the format using unicodes and then encode them to their bytes object (but then you have the additional fun of choosing an appropriate encoding!).&lt;br /&gt;&lt;br /&gt;Did you know that the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;re&lt;/span&gt; module can scan either unicodes or bytes in Python 3?&amp;nbsp; The switch is made by passing in either a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bytes&lt;/span&gt; pattern or a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;str&lt;/span&gt; pattern, and then passing in the appropriate type of object to parse.&amp;nbsp; But, if you use the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;r''&lt;/span&gt;-prefix (i.e. raw strings) for saner handling of backslashes, you've got another problem when you want to parse bytes.&amp;nbsp; Python does not support &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;rb''&lt;/span&gt;-prefixes, meaning you can have either raw string literals or bytes string literals but not both.&amp;nbsp; You have to forgo one or the other, and I usually come down on the side of ditching the raw strings and suffering the pain of backslash proliferation.&lt;br /&gt;&lt;br /&gt;Some of the code I was porting was using &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;itertools.izip_longest()&lt;/span&gt;, but this doesn't exist in Python 3.&amp;nbsp; Instead you have &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;itertools.zip_longest()&lt;/span&gt;.&amp;nbsp; You'll have to do a conditional import (i.e. try-except) around this to get the right version.&lt;br /&gt;&lt;br /&gt;Do you use &lt;a href="http://docs.zope.org/zope.interface/"&gt;zope.interfaces&lt;/a&gt;?&amp;nbsp; You'll be interested to know that the syntax we've long been accustomed to for declaring that a class implements an interface does not work in Python 3.&amp;nbsp; For example:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;from zope.interface import Interface, implements&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;class MyInterface(Interface):&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pass&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;class MyClass:&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; implements(MyInterface)&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;This is because the stack hacking that &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;implements()&lt;/span&gt; uses doesn't work in Python 3.&amp;nbsp; Fortunately, the latest version of zope.interface has a new class decorator that you can use instead.&amp;nbsp; This works in Python 2.6 and 2.7 too, so change your code to use this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;from zope.interface import Interface, implementer&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;class MyInterface(Interface):&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pass&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;@implementer(MyInterface)&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;class MyClass:&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pass&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;I kind of like the use of class decorators better anyway.&lt;br /&gt;&lt;br /&gt;Here's a tricky one.&amp;nbsp; Did you know that Python 2 provides some codecs for doing interesting conversions such as Caeser rotation (i.e. rot13)?&amp;nbsp; Thus, you can do things like:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; 'foo'.encode('rot-13')&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;'sbb'&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;This doesn't work in Python 3 though, because even though certain str-to-str codecs like rot-13 still exist, the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;str.encode()&lt;/span&gt; interface requires that the codec return a bytes object. In order to use str-to-str codecs in both Python 2 and Python 3, you'll have to pop the hood and use a lower-level API, getting and calling the codec directly:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; from codecs import getencoder&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; encoder = getencoder('rot-13')&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; rot13string = encoder(mystring)[0]&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;You have to get the zeroth-element from the return value of the encoder because of the codecs API.&amp;nbsp; A bit ugly, but it works in both versions of Python.&lt;br /&gt;&lt;br /&gt;That's all for now.&amp;nbsp; Happy porting!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-3297811300221918582?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/3297811300221918582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2012/01/python-3-porting-fun-redux.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/3297811300221918582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/3297811300221918582'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2012/01/python-3-porting-fun-redux.html' title='Python 3 Porting Fun Redux'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-5665692602402258282</id><published>2011-12-07T15:41:00.001-05:00</published><updated>2011-12-09T19:21:33.831-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python3'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Lessons in porting to Python 3</title><content type='html'>Yesterday, I completed my &lt;a href="https://code.launchpad.net/%7Ebarry/python-dbus/py3k-works"&gt;port of dbus-python to Python 3&lt;/a&gt;, and &lt;a href="https://bugs.freedesktop.org/show_bug.cgi?id=26420"&gt;submitted my patch upstream&lt;/a&gt;.&amp;nbsp; While I've yet to hear any feedback from Simon about my patch, I'm fairly confident that it's going in the right direction.&amp;nbsp; This version should allow existing Python 2 applications to run largely unchanged, and minimizes the differences that clients will have to make to use the Python 3 version.&lt;br /&gt;&lt;br /&gt;Some of the changes are specific to the &lt;a href="http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html"&gt;dbus-python&lt;/a&gt; project, and I included a &lt;a href="http://bazaar.launchpad.net/%7Ebarry/python-dbus/py3k-works/view/head:/PY3PORT.rst"&gt;detailed summary of those changes&lt;/a&gt; and my rationale behind them.&amp;nbsp; There are lots of good lessons learned during this porting exercise that I want to share with you, have a discussion about, and see if there aren't things we core Python developers can do in &lt;a href="http://www.python.org/dev/peps/pep-0398/"&gt;Python 3.3&lt;/a&gt; to make it even easier to migrate to Python 3.&lt;br /&gt;&lt;br /&gt;First, some background.&amp;nbsp; &lt;a href="http://www.freedesktop.org/wiki/Software/dbus"&gt;D-Bus&lt;/a&gt; is a &lt;a href="http://www.freedesktop.org/wiki/Home"&gt;freedesktop.org&lt;/a&gt; project for same-system interprocess communication, and it's an essential component of any Linux desktop.&amp;nbsp; The D-Bus system and C API are mature and well-defined, and there are bindings available for many programming language, Python included of course.&amp;nbsp; The existing dbus-python package is only compatible with Python 2, and most recommendations are to use the Gnome version of Python bindings should you want to use D-Bus with Python 3.&amp;nbsp; For us in &lt;a href="https://wiki.ubuntu.com/PrecisePangolin/ReleaseSchedule"&gt;Ubuntu&lt;/a&gt;, this isn't acceptable though because we must have a solution that supports KDE and potentially even non-UI based D-Bus Python servers.&amp;nbsp; Several ports of dbus-python to Python 3 have been attempted in the past, but none have been accepted upstream, so naturally I took it as a challenge to work on a new version of the port.&amp;nbsp; After some discussion with the upstream maintainer Simon McVittie, I had a few requirements in mind:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;One code base for both Python 2 and Python 3.&amp;nbsp; It's simply too difficult to support multiple development branches, so one branch must be compilable in both versions of Python.&amp;nbsp; Because dbus-python is not setuptools-based, I not to rely on &lt;a href="http://docs.python.org/library/2to3.html"&gt;2to3&lt;/a&gt; to auto-convert the Python layer.&amp;nbsp; This is more difficult, but given the next requirement, entirely possible.&lt;/li&gt;&lt;li&gt;Minimum Python versions to support are &lt;a href="http://www.python.org/download/releases/2.6.7/"&gt;2.6&lt;/a&gt; and &lt;a href="http://www.python.org/download/releases/3.2.2/"&gt;3.2&lt;/a&gt; (&lt;a href="http://www.python.org/download/releases/2.7.2/"&gt;Python 2.7&lt;/a&gt; is also supported).&amp;nbsp; Python 2.6 contains almost everything you need to do a high quality port of both the Python layer and the C extension layer with a single code base.&amp;nbsp; Python 2.7 has one or two additional helpers, but they aren't important enough to count Python 2.6 out.&amp;nbsp; For dbus-python, this specifically means dropping support for &lt;a href="http://www.python.org/download/releases/2.5.6/"&gt;Python 2.5&lt;/a&gt;, which is more than 5 years old at the time of this writing.&amp;nbsp; Also, it makes no sense to support Python 3.0 or 3.1 as neither of those are in wide-spread use.&lt;/li&gt;&lt;li&gt;Minimize any API changes seen by Python 2 code, and minimize the changes needed to port clients to Python 3.&amp;nbsp; For the former, this means everything from keeping Python APIs unchanged to keeping the inheritance hierarchy the same.&amp;nbsp; Python 2 programs will see a few small changes after the application of my patches; I'll describe them below but they should be inconsequential for the vast majority of Python 2 applications.&amp;nbsp; While it's unavoidable that Python 3 applications will see a different API, these differences have been minimized.&lt;/li&gt;&lt;/ul&gt;There are two main issues that had to be sorted out for this port, and in general for most ports to Python 3: bytes vs. strings, and ints vs. longs.&amp;nbsp; For the latter, you probably know that where Python 2 has two integer types, Python 3 has only one. In Python 3, all integers are longs, and there is no &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;L&lt;/span&gt; suffix for integer literals.&amp;nbsp; This turned out to be trickier in the dbus-python case because dbus supports a numeric stack of various integer widths, and in Python 2 these are implemented as subclasses of the built-in int and long types.&amp;nbsp; Because there are only longs in Python 3, the inheritance hierarchy a Python application will see changes between Python 2 and Python 3.&amp;nbsp; This is unavoidable.&lt;br /&gt;&lt;br /&gt;I also made the decision to change some object types to longs in both versions of Python, where I thought it was highly unlikely that Python clients would care.&amp;nbsp; Specifically, many dbus objects have a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;variant_level&lt;/span&gt; attribute, which is usually zero, but can be any positive integer.&amp;nbsp; For implementation simplicity, I changed these to longs in Python 2 also.&lt;br /&gt;&lt;br /&gt;Ah, bytes vs. strings is always where things get interesting when porting to Python 3.&amp;nbsp; It's the single most brain hurty exercise you will have to go through.&amp;nbsp; Remember that Python 2 lets you cheat.&amp;nbsp; If you not sure whether the entity you're dealing with is some bytes, or some (usually ASCII-encoded) string, just use a Python 2 str type (a.k.a. 8-bit string) and let Python's automatic conversion rules change it to a unicode when the two types meet.&amp;nbsp; You can't get away with this in Python 3 though, for very good reasons - it's error prone, and can lead to data corruption or the annoyingly ubiquitous and hard to predict &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;UnicodeError&lt;/span&gt;s.&lt;br /&gt;&lt;br /&gt;In Python 3, you must be clear about what are bytes and what are strings (i.e. unicodes), and you must be explicit when converting between the two.&amp;nbsp; Yes, this can be &lt;a href="http://lucumr.pocoo.org/2011/12/7/thoughts-on-python3/"&gt;painful at times&lt;/a&gt; but in my opinion, it's crucial that you do so.&amp;nbsp; It's that important to eliminate &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;UnicodeError&lt;/span&gt;s that you can't defend against and your users won't understand or be able to correct.&amp;nbsp; Once you're clear in your own mind as to which are strings and which are bytes, it's usually not that hard to reflect that clearly in your code, especially if you leave Python 2.5 and anything earlier behind, which I highly recommend.&lt;br /&gt;&lt;br /&gt;dbus-python presented an interesting challenge here.&amp;nbsp; It has several data types in its C API that are defined as UTF-8 encoded &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;char*&lt;/span&gt;'s.&amp;nbsp; At first blush, it seemed to me that these should be reflected in Python 3 as bytes objects to simplify the conversion in the extension module to and from &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;char*&lt;/span&gt;'s.&amp;nbsp; It turns out that this was a bad idea from an implementation stand point, and dbus-python's upstream maintainer had already expressed his opinion that these data types should be exposed as unicodes in Python 3.&amp;nbsp; After having failed at my initial attempts at making them bytes, I now agree that they must be unicodes, both for implementation simplicity and for minimal impact on porting user code.&lt;br /&gt;&lt;br /&gt;The biggest problem I ran into with the choice of bytes is that the callback dispatch code in dbus-python is complex, difficult to understand and debug, driven by external data, and written with a deep assumption of operating on strings.&amp;nbsp; For example, when the dbus C API receives a signal, it must determine whether there is a Python function registered to handle that signal, and it does this by comparing a number of client-registered parameters, such as the method name, the interface, and the object path.&amp;nbsp; If the dbus C API was turning these parameters into bytes, but the clients had registered strings, then the comparisons in the callback dispatch routines would fail, either loudly with an exception, or silently with failing comparisons.&amp;nbsp; The former were relatively easy to track down and fix, by explicitly decoding client-registered strings to bytes.&amp;nbsp; But the latter, silent failures, were nearly impossible to debug.&amp;nbsp; Add to that the fact that there were so many roads into the registration system, that it was also very difficult to coerce all incoming data early enough so that coercion wasn't necessary at comparison time.&amp;nbsp; I was left with the unappealing alternative of forcing all client code to also change their data from using strings to using bytes, which I realized would be much too high a burden on clients porting their applications to Python 3.&amp;nbsp; Simon was right, but it was a useful exercise to fail at anyway.&lt;br /&gt;&lt;br /&gt;(By way of comparison, it took me the better part of a week and a half to try to get the test suite passing when these objects were bytes, which I was ultimately unable to do, and about a day to get them passing when everything was unicodes.&amp;nbsp; That's gotta tell you something right there, and hopefully not that "I suck" :).&lt;br /&gt;&lt;br /&gt;Let's look at some practical advice that may help you in your own porting efforts.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Target nothing older than Python 2.6 or Python 3.2.&amp;nbsp; I mentioned this before, but it's really going to make your life easier.&amp;nbsp; Specifically, drop Python 2.5 and earlier and you will thank yourself&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[1]&lt;/span&gt;.&amp;nbsp; If you absolutely cannot do this, consider waiting to port to Python 3.&amp;nbsp; Note that while Python 2.7 has a few additional conveniences for supporting both Python 2 and Python 3 in a single code base, I did not find them compelling enough to drop Python 2.6 support.&lt;/li&gt;&lt;li&gt;Where you have C types with reprs, make those reprs return unicodes in both versions.&amp;nbsp; Many dbus-python types have somewhat complicated reprs because they return different strings depending on whether their &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;variant_level&lt;/span&gt;s are zero or non-zero.&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#ifdef&lt;/span&gt;'ing all of these was just too much work. Because most code probably doesn't care about the specific type of the repr, and because Python 2 allows unicode reprs, and because I have a very clever hack for this&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[2]&lt;/span&gt;&lt;/span&gt;, I decided to make all reprs return unicodes in both versions of Python.&lt;/li&gt;&lt;li&gt;Include the following &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;__future__&lt;/span&gt; imports in your Python code: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;print_function&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;absolute_import&lt;/span&gt;, and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;unicode_literals&lt;/span&gt;.&amp;nbsp; In Python 2.6 and 2.7, these enable features that are the default in Python 3, and so make it easier to support both with one codebase.&amp;nbsp; Specifically, change all your &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;print&lt;/span&gt; statements to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;print()&lt;/span&gt; functions, and remove all your &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;u''&lt;/span&gt; prefixes from your unicode literals.&amp;nbsp; Be sure to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;b''&lt;/span&gt; prefix all your byte literals&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[3]&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Wherever possible, in your extension modules, change all your &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyInt&lt;/span&gt;s to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyLong&lt;/span&gt;s.&amp;nbsp; In dbus-python, this means that the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;variant_level&lt;/span&gt; attributes are longs in both Python versions, as are values that represent such things as UNIX file descriptors.&amp;nbsp; The only place where I kept &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyInt&lt;/span&gt;s in Python 2 (and their requisite &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#ifdef&lt;/span&gt;s to use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyLong&lt;/span&gt;s in Python 3) was in the numeric stack inheritance hierarchy, mostly so that Python 2 code which cares about such things would not have to change.&lt;/li&gt;&lt;li&gt;Define a Python variable and a C macro for determining whether you're running in Python 2 or Python 3.&amp;nbsp; The former is used in dbus-python because under Python 3, there is no &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;UTF8String&lt;/span&gt; type any more, among other subtle differences.&amp;nbsp; The latter is used to simply the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#ifdef&lt;/span&gt; tests where they're needed&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[4]&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;In your C code, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#include &amp;lt;bytesobject.h&amp;gt;&lt;/span&gt;&lt;bytesobject.h&gt; &lt;bytesobject.h&gt;.&amp;nbsp; This header exposes aliases for all &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyString&lt;/span&gt; calls so that you can use the Python 3 idiom of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyBytes&lt;/span&gt;.&amp;nbsp; Then globally replace all &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyString_&lt;i&gt;Foo&lt;/i&gt;()&lt;/span&gt; calls with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyBytes_&lt;i&gt;Foo&lt;/i&gt;()&lt;/span&gt; and the code will look clean and be compilable under both versions of Python.&amp;nbsp; You may need to add explicit &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyUnicode&lt;/span&gt; calls where you need to discern between bytes and strings, but again, this code will be completely portable between Python 2 and Python 3.&lt;/bytesobject.h&gt;&lt;/bytesobject.h&gt;&lt;/li&gt;&lt;li&gt;&lt;bytesobject.h&gt;Try to write your functions to accept both unicodes and bytes, but always normalize them to one type or the other for internal use, and choose one or the other to return.&amp;nbsp; Some Python stdlib methods are &lt;i&gt;polymorphic&lt;/i&gt; in that they return bytes when handed bytes, and unicodes when handed unicodes.&amp;nbsp; This can be convenient in some cases, but problematic in others.&amp;nbsp; Choose carefully when porting your APIs.&lt;/bytesobject.h&gt;&lt;/li&gt;&lt;li&gt;&lt;bytesobject.h&gt;Don't use trailing-&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;L&lt;/span&gt; long literals if you can help it.&lt;/bytesobject.h&gt;&lt;/li&gt;&lt;li&gt;&lt;bytesobject.h&gt;Switch to using &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Py_TYPE()&lt;/span&gt; everywhere instead of de-references &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ob_type&lt;/span&gt; explicitly.&amp;nbsp; The structures are laid out differently between Python 2 and Python 3, and this Python-supplied macro hides the ugliness from you.&lt;/bytesobject.h&gt;&lt;/li&gt;&lt;/ul&gt;&lt;bytesobject.h&gt;Here are a few other miscellaneous issues you should be aware of:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;br /&gt;&lt;bytesobject.h&gt;Metaclasses are defined differently in Python 2 and Python 3, and you cannot write any Python code snippet that is even compilable between the two.&amp;nbsp; That's because the syntax for defining a class that derives from a metaclass in Python 3 is illegal syntax in Python 2. Your module simply won't compile.&amp;nbsp; My solution was to use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;exec()&lt;/span&gt; on a string.&amp;nbsp; For this reason, I suggest keeping metaclass subclasses as simple as possible, so that string is nice and small.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;Get rid of all your uses of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;iteritems()&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;iterkeys()&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;itervalues()&lt;/span&gt;, and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;xrange()&lt;/span&gt;.&amp;nbsp; You probably don't need the optimization these provide, and they do not exist in Python 3.&amp;nbsp; You can conditionalize around them, but I think in most cases it's not worth it.&amp;nbsp; If you really need the optimization, then you'll have to figure out a way around the missing names in Python 3.&amp;nbsp; But note that Python 3 is already more efficient for the first three, since you get back dictview objects instead of concrete lists.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyArg_Parse()&lt;/span&gt; and friends lack a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;'y'&lt;/span&gt; code in Python 2.&amp;nbsp; In Python 3, these return bytes objects.&amp;nbsp; Where I absolutely needed bytes in Python 3 and strs in Python 2, I just &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#ifdef&lt;/span&gt;'d around the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyArg_Parse()&lt;/span&gt; calls.&amp;nbsp; In Python 3, there's no equivalent of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;'z'&lt;/span&gt; for bytes objects (which accept &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;None&lt;/span&gt;s and set the output variable to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;NULL&lt;/span&gt; in that case).&amp;nbsp; If this is important to you, you might need to write an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;O&amp;amp;&lt;/span&gt; converter.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;Watch out for &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;next()&lt;/span&gt; vs. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;__next__()&lt;/span&gt; when writing iterators.&amp;nbsp; Python 2 uses the former while Python 3 uses the latter.&amp;nbsp; Best to define the method once, and then support compatibility via &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;`next = __next__`&lt;/span&gt; in your class definition.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;operator.isSequenceType()&lt;/span&gt; is gone in Python 3.&amp;nbsp; Here's the code I use for compatibility:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;blockquote class="tr_bq" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;def is_sequence(obj):&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from collections import Sequence&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; except ImportError:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from operator import isSequenceType&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return operator.isSequenceType(obj)&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return isinstance(obj, Sequence)&lt;/bytesobject.h&gt;&lt;/blockquote&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;If you by chance use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyCObject&lt;/span&gt;s in your extension module, you'll have to switch these to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyCapsule&lt;/span&gt;s for Python 3.&amp;nbsp; If you're lucky enough to be able to drop Python 2.6, you can use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyCapsule&lt;/span&gt;s everywhere, since they are available in Python 2.7.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;Let me close by saying that you shouldn't be frightened off by the prospect either of porting your code to Python 3, or supporting both Python 2 and Python 3 in a single code base.&amp;nbsp; It's definitely doable, and we in the Python community are gaining more experience at it every day.&amp;nbsp; I strongly feel that we are well on the track of Guido's original goal of mainstream Python 3 acceptance within 5 years of Python 3's release.&amp;nbsp; I think we're soon going to see a critical mass of Python 3 ports, after which time, you'll just seem old and creaky if you don't port to Python 3.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;There are some other excellent references for helping you port out there on the 'net, and for the most part, I've tried not to duplicate their information.&amp;nbsp; Here are some useful places to start:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://python3porting.com/toc.html"&gt;&lt;bytesobject.h&gt;http://python3porting.com/toc.html&lt;/bytesobject.h&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://docs.python.org/howto/cporting.html"&gt;&lt;bytesobject.h&gt;http://docs.python.org/howto/cporting.html&lt;/bytesobject.h&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://docs.python.org/py3k/c-api/index.html"&gt;&lt;bytesobject.h&gt;http://docs.python.org/py3k/c-api/index.html&lt;/bytesobject.h&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;bytesobject.h&gt;Enjoy!&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt; &lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;b&gt;&lt;u&gt;&lt;span style="font-size: large;"&gt;Footnotes:&lt;/span&gt;&lt;/u&gt;&lt;/b&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;ul&gt;&lt;/ul&gt;&lt;bytesobject.h&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[1]&lt;/span&gt;&lt;/span&gt; It is not impossible to support both Python 3 and versions of Python 2 earlier than 2.6, just more difficult.&amp;nbsp; &lt;a href="http://mail.python.org/pipermail/python-dev/2011-December/114839.html"&gt;Michael Foord&lt;/a&gt; has had success doing this for libraries of his such as &lt;a href="http://pypi.python.org/pypi/mock/0.7.2%0A"&gt;mock&lt;/a&gt;.&amp;nbsp; I just think it's more trouble than it's worth in most cases.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;br /&gt;&lt;bytesobject.h&gt; &lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[2]&lt;/span&gt; Here's the clever hack, but first a set-up.&amp;nbsp; The reprs of many of the dbus-python objects are conditional on whether the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;variant_level&lt;/span&gt; is zero or not.&amp;nbsp; The &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;variant_level&lt;/span&gt; is only included in the repr when it is greater than zero (with zero being the typical value).&amp;nbsp; This just means there are usually two calls to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyUnicode_FromFormat()&lt;/span&gt; in each C repr implementation, and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#ifdef&lt;/span&gt;'ing them to use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyString_FromFormat()&lt;/span&gt; in Python 2 would just double the pain.&amp;nbsp; In addition, the reprs all include the repr of their &lt;i&gt;parent&lt;/i&gt; objects, i.e. their base class repr.&amp;nbsp; The problem is that these base-class reprs will be &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyBytes&lt;/span&gt; in Python 2 and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyUnicode&lt;/span&gt;s in Python 3, and there's nothing we can do about that.&amp;nbsp; As it turns out, Python 2.6 and Python 3.2 have a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;%V&lt;/span&gt; format with some very interesting semantics.&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;%V&lt;/span&gt; consumes two arguments, a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyObject*&lt;/span&gt; and a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;char*&lt;/span&gt;, but it only uses one of them.&amp;nbsp; When the first argument is not &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;NULL&lt;/span&gt;, it uses that and ignores the second argument.&amp;nbsp; But when the first argument is &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;NULL&lt;/span&gt;, it will use the second argument.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;How can this help produce portable code?&amp;nbsp; I define the following macro and use this everywhere the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;%V&lt;/span&gt; format code is given:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;blockquote class="tr_bq" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;#define REPRV(obj) \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (PyUnicode_Check(obj) ? (obj) : NULL), \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (PyUnicode_Check(obj) ? NULL : PyBytes_AS_STRING(obj))&lt;/bytesobject.h&gt;&lt;/blockquote&gt;&lt;bytesobject.h&gt;which would be used at a call site something like this:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;return PyUnicode_FromFormat("...%V...", REPRV(parent_repr));&lt;/bytesobject.h&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;bytesobject.h&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;In Python 2, where &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;parent_repr&lt;/span&gt; is a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyBytes&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;REPRV()&lt;/span&gt; will return &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;NULL&lt;/span&gt; as the first argument, and via &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyBytes_AS_STRING()&lt;/span&gt;, a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;char*&lt;/span&gt; in the second argument. In Python 3, where &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;parent_repr&lt;/span&gt; is a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyUnicode&lt;/span&gt;, the first argument will just be the object and the second argument will be &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;NULL&lt;/span&gt; (but it is ignored by Python).&amp;nbsp; As long as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;parent_repr&lt;/span&gt; is either a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyUnicode&lt;/span&gt; or a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyBytes&lt;/span&gt; (a.k.a. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PyString&lt;/span&gt;), this works perfectly, and keeps the call sites simple and sane.&amp;nbsp; Beware though because if &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;parent_repr&lt;/span&gt; can be any other type, this will crash your program.&amp;nbsp; Fortunately, Python doesn't allow for arbitrary repr types - they must be bytes or unicodes, so in practice this is pretty safe.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[3]&lt;/span&gt; &lt;a href="http://mail.python.org/pipermail/python-dev/2011-December/114803.html"&gt;A recent thread in python-dev&lt;/a&gt; points out that this recommendation may not be practical if you're building &lt;a href="http://www.python.org/dev/peps/pep-3333/"&gt;PEP 3333&lt;/a&gt;-compliant WSGI applications.&amp;nbsp; My take on it is that PEP 3333's definition of "native strings" is a mistake, but sadly one that we have to live with for now.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[4]&lt;/span&gt;&lt;/span&gt; Here's what my Python-level flag looks like:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;import sys&lt;/bytesobject.h&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;is_py3 = getattr(sys.version_info, 'major', sys.version_info[0]) == 3&lt;/bytesobject.h&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;bytesobject.h&gt;Now I can use this in other code to switch behavior between Python 2 and Python 3.&amp;nbsp; For example, in dbus-python to import the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;UTF8String&lt;/span&gt; type in Python 2 only:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;blockquote class="tr_bq" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;from dbus import is_py3&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;if is_py3:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&amp;nbsp;&amp;nbsp; from _dbus_bindings import UTF8String&lt;/bytesobject.h&gt;&lt;/blockquote&gt;&lt;bytesobject.h&gt;This is much easier and less error prone then doing the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sys.version_info&lt;/span&gt; test everywhere.&amp;nbsp; The other problem is that &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sys.version_info&lt;/span&gt; is a namedtuple only in Python 2.7, so in Python 2.6, it has no attribute called &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;'major'&lt;/span&gt;.&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;br /&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;The C-level macro looks like this:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;#if PY_MAJOR_VERSION &amp;gt;= 3&lt;br /&gt;#define PY3K&lt;br /&gt;#endif&lt;/bytesobject.h&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;bytesobject.h&gt;&amp;nbsp;So now C code only needs to do:&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;bytesobject.h&gt;&lt;/bytesobject.h&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;#ifdef PY3K&lt;/bytesobject.h&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;/* Do something Python 3-ish */&lt;/bytesobject.h&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;#else&lt;/bytesobject.h&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;bytesobject.h&gt;/* Do something Python 2-ish */&lt;/bytesobject.h&gt;&lt;/div&gt;&lt;bytesobject.h&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#endif&lt;/span&gt;&lt;/bytesobject.h&gt;&lt;/blockquote&gt;&lt;br /&gt;You might also find the &lt;a href="http://packages.python.org/six/"&gt;six&lt;/a&gt; package to be useful here, at least for writing portable Python code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-5665692602402258282?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/5665692602402258282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/12/lessons-in-porting-to-python-3.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/5665692602402258282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/5665692602402258282'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/12/lessons-in-porting-to-python-3.html' title='Lessons in porting to Python 3'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-6526892903791075974</id><published>2011-11-23T16:20:00.001-05:00</published><updated>2011-11-23T17:43:24.329-05:00</updated><title type='text'>An update on Ubuntu's Python plans</title><content type='html'>Earlier this month, I attended &lt;a href="http://uds.ubuntu.com/"&gt;UDS-P&lt;/a&gt; (the Ubuntu Developers Summit for &lt;a href="https://wiki.ubuntu.com/PrecisePangolin/ReleaseSchedule"&gt;12.04 Precise Pangolin&lt;/a&gt;).&amp;nbsp; 12.04 is an LTS release, or &lt;a href="https://wiki.ubuntu.com/LTS"&gt;Long Term Support&lt;/a&gt;, meaning it will be officially supported on both the desktop and server for five years.&lt;br /&gt;&lt;br /&gt;During the summit we reiterated our &lt;a href="https://blueprints.launchpad.net/ubuntu/+spec/foundations-p-python-versions"&gt;plans for Python on Ubuntu&lt;/a&gt;, both for 12.04 LTS, and our vision of Python two years from now for the next LTS, 14.04.&amp;nbsp; I'm here to provide an update from my &lt;a href="http://www.wefearchange.org/2011/05/python-plans-for-ubuntu-1110-and-1204.html"&gt;last report&lt;/a&gt;, which was written after UDS-O for 11.10.&lt;br /&gt;&lt;br /&gt;As per those previous plans, we've &lt;a href="https://wiki.ubuntu.com/Python"&gt;removed Python 2.6 from Ubuntu 12.04&lt;/a&gt;.&amp;nbsp; Now you have only Python 2.7 and 3.2.&amp;nbsp; Dropping Python 2.6 may cause some inconvenience for data centers which like to upgrade only between LTS's but don't want to have to upgrade both their operation system and their Python version.&amp;nbsp; Canonical services such as &lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt; and &lt;a href="https://landscape.canonical.com/"&gt;Landscape&lt;/a&gt; fall into this camp.&amp;nbsp; The biggest problem is that Python 2.7 is not available for the last LTS, i.e. &lt;a href="https://wiki.ubuntu.com/Releases"&gt;10.04&lt;/a&gt;.&amp;nbsp; To mitigate this, we decided to create a &lt;a href="https://launchpad.net/%7Epythoneers/+archive/lts"&gt;PPA containing Python 2.7 and a bunch of packages&lt;/a&gt; that services such as Launchpad will need to do their porting.&amp;nbsp; This now exists, although it hasn't yet been tested with any development branches of Launchpad or Landscape as far as I'm aware.&amp;nbsp; If you have your own data center porting task ahead of you, you can also use this PPA, and if there are additional packages you need for 10.04, you can create your own PPA which depends on ours, and build those extra packages there.&lt;br /&gt;&lt;br /&gt;But that's all boring stuff.&amp;nbsp; Let's have some fun!&lt;br /&gt;&lt;br /&gt;The other decision we made concerns &lt;a href="http://www.python.org/download/releases/3.2.2/"&gt;Python 3&lt;/a&gt;.&amp;nbsp; I strongly feel that the Python community is very close to the tipping point in Python 3 adoption.&amp;nbsp; Yes, there's still tons of code that needs porting, but we're seeing more and more activity every day.&amp;nbsp; Even large frameworks such as &lt;a href="http://twistedmatrix.com/pipermail/twisted-python/2011-November/024731.html"&gt;Twisted&lt;/a&gt; are working on Python 3 branches.&amp;nbsp; I wrote &lt;a href="http://www.python.org/dev/peps/pep-0404/"&gt;PEP 404&lt;/a&gt; that (somewhat tongue in check) expresses official Python pronouncement on the migration path from Python 2.7 to Python 3.&amp;nbsp; There will not be a Python 2.8, so the time to begin porting your code is now.&lt;br /&gt;&lt;br /&gt;And it's really not that difficult.&amp;nbsp; There are several great guides available to help you with porting your pure Python packages to Python 3, available on both &lt;a href="http://docs.python.org/howto/pyporting.html"&gt;python.org&lt;/a&gt; and &lt;a href="http://python3porting.com/"&gt;python3porting.com&lt;/a&gt;.&amp;nbsp; There are packages such as &lt;a href="http://packages.python.org/six/"&gt;six&lt;/a&gt; available to ease the trickier bits of porting, and I have another blog post coming that describes my experiences in porting dbus-python. This latter task is made more complex by being a fairly involved C extension module.&amp;nbsp; Again, both &lt;a href="http://docs.python.org/howto/cporting.html"&gt;python.org&lt;/a&gt; and &lt;a href="http://python3porting.com/cextensions.html"&gt;python3porting.com&lt;/a&gt; have useful guides for porting extension modules, although they have missed a few things.&amp;nbsp; I wrote a &lt;a href="http://mail.python.org/pipermail/python-porting/2011-November/000247.html"&gt;mailing list article &lt;/a&gt;on some of the things that I had to do, but the blog post will include more detail.&lt;br /&gt;&lt;br /&gt;Other distros such as &lt;a href="http://fedoraproject.org/wiki/Python3"&gt;Fedora&lt;/a&gt; are also starting to work on porting essential packages to Python 3, and here's where free software and open source rules.&amp;nbsp; Our distros can work together to help nudge the Python community over that tipping point.&amp;nbsp; Fedora is working from a bottom-up approach, where they are porting packages as needed by request, and we in Ubuntu are working top-down, by identifying several desktop applications that we'll port, along with their dependency stack.&amp;nbsp; We'll both be pushing our changes to the upstream projects so every Python developer can benefit, no matter what platform they are on.&lt;br /&gt;&lt;br /&gt;My long term vision is that Ubuntu 14.04 won't even have Python 2 on the CD images (if we &lt;a href="https://help.ubuntu.com/community/Installation/FromUSBStick"&gt;even have CD images&lt;/a&gt; in two years), and we'll also move Python 2.7 off to universe.&amp;nbsp; It will never completely go away, but the operating system and all the applications you get in a default install will run on Python 3.&amp;nbsp; I'm much more sanguine about this goal now that I was even six months ago, but that's not to say it still won't be a lot of work.&lt;br /&gt;&lt;br /&gt;The time is now to move to Python 3, if for no other reason than to fix all those pesky &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;UnicodeErrors&lt;/span&gt;.&amp;nbsp; I think there's a lot more of value in Python 3 too of course, and &lt;a href="http://www.python.org/dev/peps/pep-0398/"&gt;Python 3.3&lt;/a&gt; will be&lt;a href="http://docs.python.org/dev/whatsnew/3.3.html"&gt; even more awesome&lt;/a&gt;.&amp;nbsp; I expect Python 3.3 or 3.4 to be in Ubuntu 14.04.&lt;br /&gt;&lt;br /&gt;The place to be for all Python 3 porting efforts is the &lt;a href="http://mail.python.org/mailman/listinfo/python-porting"&gt;python-porting&lt;/a&gt; mailing list.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;UPDATE&lt;/b&gt;: &lt;i&gt;Fixed Python 3.3/3.4 plans to correctly read for Ubuntu 14.04 (thanks Nick!) &lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-6526892903791075974?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/6526892903791075974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/11/update-on-ubuntus-python-plans.html#comment-form' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6526892903791075974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6526892903791075974'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/11/update-on-ubuntus-python-plans.html' title='An update on Ubuntu&apos;s Python plans'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-342530618926691588</id><published>2011-10-12T19:07:00.001-04:00</published><updated>2011-10-12T19:07:37.046-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='i18n'/><title type='text'>Python internationalization without exploding your brain</title><content type='html'>Today I helped a colleague out with a pesky internationalization (i18n) problem in a Python 2 application.&amp;nbsp; The problem was subtle enough that I thought I'd write this article to save others from the same brain exploding pain.&lt;br /&gt;&lt;br /&gt;First, your Python application is multi-language friendly, right?&amp;nbsp; I mean, I'm as functionally monolinguistic as most Americans, but I love the diversity of languages we have in the world, and appreciate that people really want to use their desktop and applications in their native language.&amp;nbsp; Fortunately, it's not that hard to write good i18n'd Python code, and there are many tools available for helping volunteers translate your application, such as &lt;a href="http://translate.sourceforge.net/wiki/pootle/index?redirect=1"&gt;Pootle&lt;/a&gt; and &lt;a href="https://help.launchpad.net/Translations/YourProject"&gt;Launchpad translations&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So there really is no excuse not to i18n your Python application.&amp;nbsp; In fact, &lt;a href="http://www.list.org/"&gt;GNU Mailman&lt;/a&gt; has been &lt;a href="http://wiki.list.org/display/DEV/Internationalization"&gt;i18n'd for many years&lt;/a&gt;, and pioneered the supporting code in Python's standard library, namely the &lt;a href="http://docs.python.org/library/gettext.html" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;gettext module&lt;/a&gt;.&amp;nbsp; As part of the Mailman 3 effort, I've also written a higher level library called &lt;a href="http://pypi.python.org/pypi/flufl.i18n" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;flufl.i18n&lt;/a&gt; which makes it &lt;a href="http://packages.python.org/flufl.i18n/docs/using.html"&gt;even easier to i18n your application&lt;/a&gt;, even in tricky multi-language contexts such as server programs, where you might need to get a German translation and a French translation in one operation, then turn around and get Japanese, Italian,and English for the next operation.&lt;br /&gt;&lt;br /&gt;In any case, my colleague was having a problem in a typically simple command line program.&amp;nbsp; What's common about these types of applications is that you fire them up once, they run then exit, and they only have to deal with one language during the entire execution of the program, specifically the language defined in the &lt;a href="http://pubs.opengroup.org/onlinepubs/007904875/basedefs/xbd_chap07.html"&gt;user's locale&lt;/a&gt;.&amp;nbsp; If you read the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;gettext&lt;/span&gt; module's documentation, you'd be inclined to do this at the very start of your application:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;from gettext import gettext as _&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;gettext.textdomain(my_program_name)&lt;/div&gt;&lt;br /&gt;then, you'd wrap translatable strings in code like this:&lt;br /&gt; &lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;print _('Here is something I want to tell you')&lt;/div&gt;&lt;br /&gt;What &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;gettext&lt;/span&gt; does is look up the source string in a translation catalog, returning the text in the appropriate language, which will then be printed.&amp;nbsp; There are some additional details regarding i18n that I won't go into here.&amp;nbsp; If you're curious, ask in the comments, and I'll try to fill things in.&lt;br /&gt;&lt;br /&gt;Anyway, if you do write the above code, you'll be in for a heap of trouble, as my colleague soon found out.&amp;nbsp; Just running his program with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;--help&lt;/span&gt; in a French locale, he was getting the dreaded &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;UnicodeEncodeError&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"UnicodeEncodeError: 'ascii' codec can't encode character"&lt;/div&gt;&lt;br /&gt;I've also seen reports of such errors when trying to send translated strings to a log file (a practice which I generally discourage, since I think log messages usually shouldn't be translated).&amp;nbsp; In any case, I'm here to tell you why the above "obvious" code is wrong, and what you should do instead.&lt;br /&gt;&lt;br /&gt;First, why is that code wrong, and why does it lead to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;UnicodeEncodeErrors&lt;/span&gt;?&amp;nbsp; What might not be obvious from the Python 2 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;gettext&lt;/span&gt; documentation is that &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;gettext.gettext() &lt;/span&gt;always returns 8-bit strings (a.k.a. byte strings in Python 3 terminology), and these 8-bit strings are encoded with the charset defined in the language's&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt; catalog file.&amp;nbsp; Now, it's generally best practice in Python to always deal with human readable text using unicodes, converting any bytes to unicode as early as possible.&amp;nbsp; This is traditionally more problematic in Python 2, where English programs can cheat and use 8-bit strings and usually not crash, since their character range overlaps with ASCII and you only ever print to English locales, which are compatible with ASCII.&amp;nbsp; As soon as you use text that's not ASCII though, you're probably going to run into trouble.&amp;nbsp; By using unicodes everywhere, you can generally avoid such problems, and in fact it will make your life much easier when you eventually switch to Python 3.&lt;br /&gt;&lt;br /&gt;So the 8-bit strings that &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;gettext.gettext()&lt;/span&gt; hands you will really just hurt you, and to avoid the pain, you'd want to convert them back to unicodes before you print them to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;stdout&lt;/span&gt; or a log file.&amp;nbsp; However, converting to unicodes makes the i18n APIs much less convenient, so no one does it until there's way too much code to fix.&lt;br /&gt;&lt;br /&gt;What you really want in Python 2 is something like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;from gettext import ugettext as _&lt;/div&gt;&lt;br /&gt;which you'd think you should be able to do, the "u" prefix meaning "give me unicode".&amp;nbsp; But for reasons I can only describe as based on our misunderstandings of unicode and i18n back in the days this module was originally written, you can't actually do that, because &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ugettext()&lt;/span&gt; is not exposed as a module-level function.&amp;nbsp; It is available in the &lt;a href="http://docs.python.org/library/gettext.html#class-based-api"&gt;class-based API&lt;/a&gt;, but that's a more advanced API that again almost no one uses.&amp;nbsp; Sadly, it's too late to fix this in Python 2.&amp;nbsp; The good news is that in Python 3 it &lt;i&gt;is&lt;/i&gt; fixed, not by exposing &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ugettext()&lt;/span&gt;, but by changing the most commonly used &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;gettext&lt;/span&gt; module APIs to return unicode strings directly, as it always should have done.&amp;nbsp; In Python 3, the obvious code just works:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;from gettext import gettext as _&lt;/div&gt;&lt;br /&gt;What can you do in Python 2 then?&amp;nbsp; Here's what you should use instead of the two lines of code at the beginning of this article:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;_ = gettext.translation(my_program_name).ugettext&lt;/div&gt;&lt;br /&gt;and now you can wrap all your translatable strings in &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;_('Foo')&lt;/span&gt; and it should Just Work.&amp;nbsp; Or you can use the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;flufl.i18n&lt;/span&gt; API, which always uses &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ugettext&lt;/span&gt; and always returns unicode strings.&lt;br /&gt;&lt;br /&gt;The one-liner above was in fact the solution my colleague implemented to fix his bug, so I didn't really help him much.&amp;nbsp; I just explained why his fix was the correct one and the original code was buggy.&amp;nbsp; At least now you know too!&lt;br /&gt;&lt;br /&gt;(The fact that this works correctly in Python 3 is yet another reason to switch to Python 3!)&lt;br /&gt;&lt;br /&gt;Aside: It's really fun to install a desktop in a language you cannot read.&amp;nbsp; Fortunately, French, like other Latin-drived languages, has enough familiarity that I can mostly get by with the standard Ubuntu installer.&amp;nbsp; It also doesn't hurt that I've done about a bazillion installs of &lt;a href="http://cdimages.ubuntu.com/releases/oneiric/"&gt;Ubuntu Oneiric&lt;/a&gt; (&lt;a href="http://www.ubuntu.com/"&gt;due out tomorrow&lt;/a&gt;!) so I pretty much know what each screen and prompt means even without going to &lt;a href="http://translate.google.com/"&gt;Google Translate&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Also interesting was that I could never reproduce the crash when &lt;a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh"&gt;ssh'd&lt;/a&gt; into the French locale VM. It would only crash for me when I was logged into a terminal on the VM's graphical desktop.&amp;nbsp; The only difference between the two that I could tell was that in the desktop's terminal, &lt;a href="http://manpages.ubuntu.com/manpages/hardy/man1/locale.1.html"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;locale(8)&lt;/span&gt;&lt;/a&gt; returned French values (e.g. &lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;fr_FR.UTF-8&lt;/span&gt;) for everything, but in the ssh console, it returned the French values for everything except the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;LC_CTYPE&lt;/span&gt; environment variable.&amp;nbsp; For the life of me, I could not get &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;LC_CTYPE&lt;/span&gt; set to anything other than &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;en_US.UTF-8&lt;/span&gt; in the ssh context, so the reproducible test case would just return the English text, and not crash.&amp;nbsp; This happened even if I explicitly set that environment variable either as a separate &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;export&lt;/span&gt; command in the shell, or as a prefix to the normally crashing command.&amp;nbsp; Maybe there's something in ssh that causes this, but I couldn't find it.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-342530618926691588?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/342530618926691588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/10/python-internationalization-without.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/342530618926691588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/342530618926691588'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/10/python-internationalization-without.html' title='Python internationalization without exploding your brain'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-1229040718457204119</id><published>2011-09-01T18:59:00.000-04:00</published><updated>2011-09-06T16:27:31.480-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='packaging'/><category scheme='http://www.blogger.com/atom/ns#' term='debian'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='canonical'/><title type='text'>sbuild with local, newer, dependencies</title><content type='html'>&lt;a href="http://wiki.debian.org/sbuild"&gt;sbuild&lt;/a&gt; is an excellent tool for locally building Ubuntu and Debian packages.&amp;nbsp; It fits into roughly the same problem space as the more popular &lt;a href="http://wiki.debian.org/PbuilderTricks"&gt;pbuilder&lt;/a&gt;, but for many reasons, I prefer sbuild.&amp;nbsp; It's based on &lt;a href="http://wiki.debian.org/Schroot"&gt;schroot&lt;/a&gt; to create chroot environments for any distribution and version you might want.&amp;nbsp; For example, I have chroots for Ubuntu Oneiric, Natty, Maverick, and Lucid, Debian Sid, Wheezy, and Squeeze, for both i386 and amd64.&amp;nbsp; It uses an overlay filesystem so you can easily set up the primary snapshot with whatever packages or prerequisites you want, and the individual builds will create a new session with an overlaid temporary filesystem on top of that, so the build results will not affect your primary snapshot.&amp;nbsp; sbuild can also be configured to save the session depending on the success or failure of your build, which is fantastic for debugging build failures.&amp;nbsp; I've been told that &lt;a href="http://launchpad.net/"&gt;Launchpad&lt;/a&gt;'s build farm uses a customized version of sbuild, and in my experience, if you can get a package to build locally with sbuild, it will build fine in the main archive or a &lt;a href="https://help.launchpad.net/Packaging/PPA"&gt;PPA&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Right out of the box, sbuild will work great for individual package builds, with very little configuration or setup.&amp;nbsp; The Ubuntu Security Team's &lt;a href="https://wiki.ubuntu.com/SecurityTeam/BuildEnvironment"&gt;wiki page&lt;/a&gt; has some excellent instructions for getting started (you can stop reading when you get to UMT :).&lt;br /&gt;&lt;br /&gt;One thing that sbuild doesn't do very well though, is help you build a stack of packages.&amp;nbsp; By that I mean, when you have a new package that itself has new dependencies, you need to build those dependencies first, and then build your new package based on those dependencies.&amp;nbsp; Here's an example.&lt;br /&gt;&lt;br /&gt;I'm working on &lt;a href="https://bugs.launchpad.net/ubuntu/+source/pyside/+bug/832864/+index"&gt;bug 832864&lt;/a&gt; and I wanted to see if I could build the newer Debian Sid version of the PySide package.&amp;nbsp; However, this requires newer apiextractor, generatorrunner, and shiboken packages (and technically speaking, debhelper too, but I'm working around that), so you have to arrange for the chroot to have those newer packages when it builds PySide, rather than the ones in the Oneiric archive.&amp;nbsp; This is something that PPAs do very nicely, because when you build a package in your PPA, it will use the other packages in that PPA as dependencies before it uses the standard archive.&amp;nbsp; The problem with PPAs though is that when the &lt;a href="https://launchpad.net/builders"&gt;Launchpad build farm&lt;/a&gt; is overloaded, you might have to wait several hours for your build.&amp;nbsp; Those long turnarounds don't help productivity much. ;)&lt;br /&gt;&lt;br /&gt;What I wanted was something like the PPA dependencies, but with the speed and responsiveness of a local build.&amp;nbsp; After reading the &lt;a href="http://manpages.ubuntu.com/manpages/hardy/man1/sbuild.1.html"&gt;sbuild manpage&lt;/a&gt;, and "suffering" through a scan of its source code (sbuild is written in &lt;a href="http://www.tbray.org/ongoing/When/200x/2004/12/08/-big/IMG_3061.jpg.html"&gt;Perl&lt;/a&gt; :), I found that this wasn't really supported by sbuild.&amp;nbsp; However, sbuild does have hooks that can run at various times during the build, which seemed promising.&amp;nbsp; My colleague &lt;a href="https://wiki.ubuntu.com/KeesCook"&gt;Kees Cook&lt;/a&gt; was a contributor to sbuild, so a quick IRC chat indicated that most people create a local repository, populating it with the dependencies as you build them.&amp;nbsp; Of course, I want to automate that as much as possible.&amp;nbsp; The requisite googling found a few hints here and there, but nothing to pull it all together.&amp;nbsp; With some willful hackery, I managed to get it working.&lt;br /&gt;&lt;br /&gt;Rather than post some code that will almost immediately go out of date, let me point you to the bzr repository where you &lt;a href="http://bazaar.launchpad.net/%7Ebarry/+junk/repotools/files"&gt;can find the code&lt;/a&gt;.&amp;nbsp; There are two scripts: &lt;a href="http://bazaar.launchpad.net/%7Ebarry/+junk/repotools/view/head:/prep.sh"&gt;prep.sh &lt;/a&gt;and &lt;a href="http://bazaar.launchpad.net/%7Ebarry/+junk/repotools/view/head:/scan.sh"&gt;scan.sh&lt;/a&gt;, along with a &lt;a href="http://bazaar.launchpad.net/%7Ebarry/+junk/repotools/view/head:/sbuildrc.ex"&gt;snippet for your ~/.sbuildrc&lt;/a&gt; file to make it even easier.&amp;nbsp; sbuild will call scan.sh first, but here's the important part: it calls that outside the chroot, as you (not root). You'll probably want to change &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$where&lt;/span&gt; though; this is where you drop the .deb and .dsc files for the dependencies.&amp;nbsp; Note too, that you'll need to add an entry to your &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/etc/schroot/default/fstab&lt;/span&gt; file so that your outside-the-chroot repo directory gets mapped to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/repo&lt;/span&gt; inside the chroot.&amp;nbsp; For example:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Expose local apt repository to the chroot&lt;/div&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/home/barry/ubuntu/repo&amp;nbsp;&amp;nbsp;&amp;nbsp; /repo&amp;nbsp;&amp;nbsp;&amp;nbsp; none&amp;nbsp;&amp;nbsp; rw,bind&amp;nbsp; 0 0&lt;/span&gt;&lt;/blockquote&gt;An apt repository needs a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Packages&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Packages.gz&lt;/span&gt; file for binary packages, and a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Sources&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Sources.gz&lt;/span&gt; file for the source packages.&amp;nbsp; &lt;a href="http://wiki.debian.org/SecureApt"&gt;Secure APT&lt;/a&gt; also requires a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Release&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Release.gpg&lt;/span&gt; file signed with a known key.&amp;nbsp; The scan.sh file sets all this up, using the apt-ftparchive command.&amp;nbsp; The first apt-ftparchive call creates the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Sources&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Sources.gz&lt;/span&gt; file.&amp;nbsp; It scans all your .dsc files and generates the proper entries, then creates a compressed copy, which is what apt actually "downloads".&amp;nbsp; The tricky thing here is that without changing directories before calling apt-ftparchive, your outside-the-chroot paths will leak into this file, in the form of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Directory:&lt;/span&gt; headers in &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Sources.gz&lt;/span&gt;.&amp;nbsp; Because that path won't generally be available inside the chroot, we have to get rid of those headers.&amp;nbsp; I'm sure there's an apt-ftparchive option to do this, but I couldn't find it.&amp;nbsp; I accidentally discovered that cd'ing to the directory with the .dsc files was enough to trick the command into omitting the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Directory:&lt;/span&gt; headers.&lt;br /&gt;&lt;br /&gt;The second call to apt-ftparchive creates the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Packages&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Packages.gz&lt;/span&gt; files.&amp;nbsp; As with the source files, we get some outside-the-chroot paths leaking in, this time as path prefixes to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Filename:&lt;/span&gt; header value.&amp;nbsp; Again, we have to get rid of these prefixes, but cd'ing to the directory with the .deb files doesn't do the trick.&amp;nbsp; No doubt there's some apt-ftparchive magical option for this too, but sed'ing out the paths works well enough.&lt;br /&gt;&lt;br /&gt;The third apt-ftparchive file creates the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Release&lt;/span&gt; file.&amp;nbsp; I shameless stole this from the security team's &lt;a href="http://bazaar.launchpad.net/%7Eubuntu-security/ubuntu-security-tools/trunk/view/head:/repo-tools/update_repo"&gt;update_repo&lt;/a&gt; script.&amp;nbsp; The tricky part here is getting &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Release&lt;/span&gt; signed with a gpg key that will be available to apt inside the chroot.&amp;nbsp; sbuild comes with its own signing key, so all you have to do is specify its public and private keys when signing the file.&amp;nbsp; However, because the public file from&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;pre style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/var/lib/sbuild/apt-keys/sbuild-key.pub&lt;/pre&gt;&lt;/blockquote&gt;won't be available inside the chroot, the script copies it to what will be &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/repo&lt;/span&gt; inside the chroot.&amp;nbsp; You'll see later how this comes into play.&lt;br /&gt;&lt;br /&gt;Okay, so now we have the repository set up well enough for sbuild to carry on.&amp;nbsp; Later, before the build commences, sbuild will call prep.sh, but this script gets called inside the chroot, as the root user.&amp;nbsp; Of course, at this point &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/repo&lt;/span&gt; is mounted in the chroot too.&amp;nbsp; All prep.sh needs to do is add a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sources.list.d&lt;/span&gt; entry so apt can find your local repository, and it needs to add the public key of the sbuild signing key pair to apt's keyring.&amp;nbsp; After it does this, it needs to do one more &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;apt-get update&lt;/span&gt;.&amp;nbsp; It's useful to know that at the point when sbuild calls prep.sh, it's already done one &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;apt-get update&lt;/span&gt;, so this does add a duplicate step, but at least we're fortunate enough that prep.sh gets called before sbuild installs all the build dependencies.&amp;nbsp; Once prep.sh is run, the chroot will have your overriding dependent packages, and will proceed with a normal build.&lt;br /&gt;&lt;br /&gt;Simple, huh?&lt;br /&gt;&lt;br /&gt;Besides getting rid of the hackery mentioned above, there are a few things that could be done better:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Different &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/repo&lt;/span&gt; mounts for each different chroot&lt;/li&gt;&lt;li&gt;A command line switch to disable the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/repo&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Automatically placing .debs into the outside-the-chroot repo directory&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Anyway, it all seems to hang together.&amp;nbsp; Please let me know what you think, and if you find better workarounds for the icky hacks.&lt;br /&gt;&lt;pre&gt; &lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-1229040718457204119?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/1229040718457204119/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/09/sbuild-with-local-newer-dependencies.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/1229040718457204119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/1229040718457204119'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/09/sbuild-with-local-newer-dependencies.html' title='sbuild with local, newer, dependencies'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-2531683985336510419</id><published>2011-07-20T21:37:00.000-04:00</published><updated>2011-07-20T21:37:43.262-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='otone'/><category scheme='http://www.blogger.com/atom/ns#' term='onote'/><title type='text'>ONOTE and OTONE - A musical project</title><content type='html'>I'm starting a new musical project, which I'm calling &lt;b&gt;OTONE&lt;/b&gt; and/or &lt;b&gt;ONOTE&lt;/b&gt;.&amp;nbsp; Actually, I've been working on this project for several years without realizing what I wanted to do with it.&amp;nbsp; It coalesced in my mind when I thought of the acronyms above.&amp;nbsp; Here's what they stand for:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The One Tune One Night Experiment (OTONE)&lt;/li&gt;&lt;li&gt;The One Night One Tune Experiment (ONOTE)&lt;/li&gt;&lt;/ol&gt;I'm not yet sure what the difference between the two are yet (though see below), but here's the idea behind the project.&lt;br /&gt;&lt;br /&gt;If you're like me, you can easily sweat over a song and its recording for &lt;i&gt;ever&lt;/i&gt;, tweaking the mix, or hearing another melody, or (worst of all) agonizing over every word of a lyric that was like pulling teeth in the first place.&amp;nbsp; Sometimes you think if you just do one more take of the guitar, you can get it perfect, or oh! it just needs a little bit of tamborine right &lt;i&gt;there&lt;/i&gt;.&amp;nbsp; Sometimes the arrangement just doesn't sit quite right, or you know in your gut that lurking out there somewhere there's a better way to get from the bridge to the last chorus.&lt;br /&gt;&lt;br /&gt;Well, I'm kind of frustrated with that because it can lead to never actually finishing a song and getting it out there for folks to hear.&amp;nbsp; At some point you reach diminishing returns, where the little tweaks don't really improve the song enough.&amp;nbsp; Probably most importantly, the whole thing can put the brakes on the creative process.&amp;nbsp; I liken it to software maintenance vs. creating a new project from scratch.&lt;br /&gt;&lt;br /&gt;Software maintenance is important, useful, and can be fun, but the juices really get flowing when you're starting a new project.&amp;nbsp; You get this rush of an idea and your fingers can't type fast enough to translate them into code.&amp;nbsp; It's this latter feeling that I want to better capture with music.&lt;br /&gt;&lt;br /&gt;A brilliant friend and awesome drummer once said, "&lt;i&gt;you have to get the crappy songs out in order to get to the good ones&lt;/i&gt;."&amp;nbsp; A similar thought is "&lt;i&gt;let 1000 flowers bloom&lt;/i&gt;."&amp;nbsp; The more you write the easier it gets, and the more likely that out will come some cool songs.&amp;nbsp; Thus OTONE/ONOTE.&lt;br /&gt;&lt;br /&gt;The idea is to produce one song in one evening, and not sweat the details (too much).&amp;nbsp; I have a small backlog of tunes that I've written using this approach (without realizing it) and plan on posting them to my website and social media over the next few weeks.&amp;nbsp; Going forward, I'm going to set aside one night a week or fortnight, and see what happens.&amp;nbsp; I'll post those too.&amp;nbsp; I'll very likely put them under a non-commercial &lt;a href="http://creativecommons.org/"&gt;Creative Commons&lt;/a&gt; license, but I haven't yet decided whether to allow derivative works or not (I'm leaning toward "yes").&lt;br /&gt;&lt;br /&gt;I encourage my other artistic friends to take a similar approach with their music, writing, art, etc.&amp;nbsp; Feel free to use the #onote or #otone tags, but if you could link back to this article as your original impetus, I'd really appreciate it.&lt;br /&gt;&lt;br /&gt;I should mention that some of the songs were not written in one night, but all were produced in one night.&amp;nbsp; I'm trying to keep it under check, but sometimes I just can't help but twiddle the chorus now and then. :)&amp;nbsp; Maybe that's the distinction though.&amp;nbsp; OTONE can mean a song I wrote in one night, while ONOTE can be one evening devoted to producing just one song.&lt;br /&gt;&lt;br /&gt;A couple of other things to keep in mind:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The songs will be rough.&amp;nbsp; The whole point is not to cut and paste that one early bass note into the right place because that just slows you down.&amp;nbsp; Unless it doesn't and you can still finish in one night. :)&lt;/li&gt;&lt;li&gt;Part of the reason for doing this is to better learn other software.&amp;nbsp; I'm fairly proficient at Cubase 4 (but despise the dongle), and GarageBand is easy to get started (but much more difficult to do advanced stuff like arrange), Logic 9 is cool but I don't know it that well, and there are lots of free and alternative DAWs to experiment with.&amp;nbsp; Doing quick one-night projects gives me some time to explore these.&lt;/li&gt;&lt;li&gt;Give me feedback and maybe I'll flesh out the good ones.&amp;nbsp; There's no rule against coming back around to the ones you like and obsessing over the details later.&lt;/li&gt;&lt;li&gt;Remember: just because the sun's come up doesn't mean the night's over.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Now, go out and create!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-2531683985336510419?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/2531683985336510419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/07/onote-and-otone-musical-project.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2531683985336510419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2531683985336510419'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/07/onote-and-otone-musical-project.html' title='ONOTE and OTONE - A musical project'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-4392597761768647401</id><published>2011-07-13T15:15:00.005-04:00</published><updated>2011-07-13T17:28:01.119-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Ignore at your own peril</title><content type='html'>On Monday, I lost my home directory on my primary development machine.&amp;nbsp; I'd had this machine for a couple of years but it was still beefy enough to be an excellent development box.&amp;nbsp; I've upgraded it several times with each new Ubuntu release, and it was running Natty.&amp;nbsp; I had decent &lt;i&gt;&lt;a href="https://wiki.ubuntu.com/SecurityTeam/BuildEnvironment"&gt;sbuild&lt;/a&gt;&lt;/i&gt; and &lt;i&gt;&lt;a href="https://wiki.ubuntu.com/PbuilderHowto"&gt;pbuilder&lt;/a&gt;&lt;/i&gt; environments, and a bunch of &lt;a href="https://help.ubuntu.com/8.04/serverguide/C/libvirt.html"&gt;virtual machines&lt;/a&gt; for many different flavors of OS.&lt;br /&gt;&lt;br /&gt;I'd also &lt;a href="https://help.ubuntu.com/community/EncryptedHome"&gt;encrypted my home directory&lt;/a&gt; when I did the initial install.&amp;nbsp; Under Ubuntu, this creates an &lt;i&gt;&lt;a href="https://help.ubuntu.com/community/EncryptedPrivateDirectory"&gt;ecryptfs&lt;/a&gt;&lt;/i&gt; and does some mount magic after you successfully log in.&amp;nbsp; It's as close to &lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/FileVault"&gt;FileVault&lt;/a&gt; as you can get on Ubuntu, and I think it does a pretty good job without incurring much noticeable overhead.&amp;nbsp; Plus, with today's &lt;a href="http://cdimages.ubuntu.com/releases/natty/release/"&gt;Ubuntu desktop installers&lt;/a&gt;, enabling an encrypted home directory is just a trivial checkbox away.&lt;br /&gt;&lt;br /&gt;To protect your home directory, &lt;i&gt;ecryptfs&lt;/i&gt; creates a random hex passphrase that is used to decrypt the contents of your home directory.&amp;nbsp; To protect this passphrase, it encrypts it with your login password.&amp;nbsp; &lt;i&gt;ecryptfs&lt;/i&gt; stores this "wrapped" passphrase on disk in the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/.ecryptfs/wrapped-passphrase&lt;/span&gt; file.&lt;br /&gt;&lt;br /&gt;When you log in, &lt;i&gt;ecryptfs&lt;/i&gt; uses your login password to decrypt &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;wrapped-passphrase&lt;/span&gt;, and then uses the crazy long hex number inside it to decrypt your real home directory.&amp;nbsp; Usually, this works seamlessly and you never really see the guts of what's going on.&amp;nbsp; The problem of course is that if you ever lose your &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;wrapped-passphrase&lt;/span&gt; file, you're screwed because without that long hex number, your home directory cannot be decrypted.&amp;nbsp; Yay for security, boo for robustness!&lt;br /&gt;&lt;br /&gt;When you do your initial installation and choose to encrypt your home  directory, you will be prompted to write down the long hex number, i.e. your unwrapped passphrase.&amp;nbsp; Here's the moral of the story.&amp;nbsp; 1) You should do this; 2) You should remember where you put that magic piece of paper!&lt;br /&gt;&lt;br /&gt;I did #1 but failed to do #2.&lt;br /&gt;&lt;br /&gt;I'm not exactly sure how my &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/.ecryptfs&lt;/span&gt; directory got corrupted, but somehow the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;wrapped-passphrase&lt;/span&gt; file got deleted.&amp;nbsp; I'm fairly certain that I didn't do it accidentally, but you never know.&amp;nbsp; I suspect that there was some bad interaction with &lt;i&gt;sbuild&lt;/i&gt; because the only thing I'd done right before the corruption, was to update my &lt;i&gt;sbuild&lt;/i&gt; environment, and build a package in it.&amp;nbsp; Note that if you follow the &lt;a href="https://wiki.ubuntu.com/SecurityTeam/BuildEnvironment"&gt;Ubuntu Security Team's instructions for setting up your &lt;i&gt;sbuild&lt;/i&gt;&lt;/a&gt; (which I highly recommend), your unencrypted home directory will be exposed to &lt;i&gt;sbuild&lt;/i&gt;'s chroots.&amp;nbsp; This is very convenient for normal work-a-day package building.&amp;nbsp; However, it's possible that some bug in &lt;i&gt;sbuild&lt;/i&gt; caused my &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/.ecryptfs&lt;/span&gt; directory to get corrupted.&amp;nbsp; That's only a wild guess though; I'm now rebuilding my dev box on a fresh 1.5T drive starting with Oneiric alpha 2, so we'll see if this bug bites me again.&lt;br /&gt;&lt;br /&gt;This time, I'm prepared.&amp;nbsp; I stumbled upon a clever and secure way to never lose that piece of paper again.&amp;nbsp; This technique should also allow you to store and share other securely encrypted data across any of your Ubuntu machines.&lt;br /&gt;&lt;br /&gt;The first step is to set up &lt;a href="https://one.ubuntu.com/"&gt;Ubuntu One&lt;/a&gt;.&amp;nbsp; You get 2GB of data free, so why not use it!?&amp;nbsp; I have U1 set up on all my Ubuntu desktops, and it's a great place to stash things you might need everywhere.&amp;nbsp; I've been considering storing things like my &lt;a href="https://www.mozilla.com/en-US/firefox/fx/"&gt;Firefox&lt;/a&gt;, &lt;a href="http://www.chromium.org/Home"&gt;Chromium&lt;/a&gt;, and &lt;a href="http://www.claws-mail.org/"&gt;Claws-Mail&lt;/a&gt; configs in U1 because I always want to keep them in sync.&amp;nbsp; I already store my &lt;a href="http://pypi.python.org/pypi/gtimelog"&gt;Timelog Tracker&lt;/a&gt; data there, so I can enter my time and accomplishments from any desktop.&lt;br /&gt;&lt;br /&gt;(I generally do not keep most of my configuration files in U1 since I keep them under &lt;a href="http://bazaar.canonical.com/en/"&gt;Bazaar&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;Now, it would be a very simple matter of just creating a subdirectory under &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/Ubuntu One&lt;/span&gt; for each machine that has an encrypted home directory, and then just copy the contents of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/.ecyptfs&lt;/span&gt; to that.&amp;nbsp; You need a separate subdirectory per machine because even if your login password is the same everywhere, that random hex number will be different.&lt;br /&gt;&lt;br /&gt;You can do this today, but it may not be secure as you'd like, since the hex number that unlocks your encrypted home directory is "only" protected by your login password.&amp;nbsp; Crack the password, and if there's ever a security hole in U1 (or some other legal or illegal machinations) that manages to expose your &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;wrapped-passphrase&lt;/span&gt; file, then your entire home directory is vulnerable.&amp;nbsp; For a little extra security, we can use &lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/EncFS"&gt;&lt;i&gt;encfs&lt;/i&gt;&lt;/a&gt; and &lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/FUSE_%28Linux%29"&gt;&lt;i&gt;fuse&lt;/i&gt;&lt;/a&gt; to create an unencrypted front-end to an encrypted directory inside U1.&amp;nbsp; You would then copy your &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;~/.ecryptfs&lt;/span&gt; files to the unencrypted mount, and it would get stored with an additional level of encryption (and obfuscation) to U1.&amp;nbsp; Now someone would have to crack two passphrases to get to your home directory.&lt;br /&gt;&lt;br /&gt;The instructions on how to do this couldn't be simpler, and are outlined in &lt;a href="http://ubuntuforums.org/showthread.php?t=148600"&gt;this wiki article&lt;/a&gt;, and &lt;a href="https://help.ubuntu.com/community/FolderEncryption"&gt;this one&lt;/a&gt;.&amp;nbsp; For the lazy (like myself), here are the steps:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ sudo apt-get install encfs fuse-utils&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ sudo modprobe fuse&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ sudo adduser &amp;lt;your-login&amp;gt; fuse&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ sudo sh -c "echo fuse &amp;gt;&amp;gt; /etc/modules"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ mkdir ~/safe&amp;nbsp; # or whatever, contents are plaintext&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ mkdir "~/Ubuntu One/safe" # or whatever, contents are encrypted&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ encfs "~/Ubuntu One/safe" ~/safe&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# You will be prompted for a new encfs passphrase, this is your extra security&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ mkdir ~/safe/&amp;lt;your-machine&amp;gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ cp -a ~/.ecryptfs/* ~/safe/&amp;lt;your-machine&amp;gt;&lt;/div&gt;&lt;br /&gt;And now just let U1 do its synchronization magic.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-4392597761768647401?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/4392597761768647401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/07/ignore-at-your-own-peril.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4392597761768647401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4392597761768647401'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/07/ignore-at-your-own-peril.html' title='Ignore at your own peril'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-7994640580269719529</id><published>2011-06-22T13:12:00.001-04:00</published><updated>2011-06-22T18:46:56.559-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='packaging'/><category scheme='http://www.blogger.com/atom/ns#' term='debian'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>PEP 382 sprint summary</title><content type='html'>So, yesterday (June 21, 2011), six talented and motivated Python hackers from the Washington DC area met at &lt;a href="http://www.silverspringdowntown.com/go/panera-bread"&gt;Panera Bread in downtown Silver Spring&lt;/a&gt;, Maryland to sprint on &lt;a href="http://www.python.org/dev/peps/pep-0382/"&gt;PEP 382&lt;/a&gt;.  This is a Python Enhancement Proposal to introduce a better way for handling namespace packages, and our intent is to get this feature landed in &lt;a href="http://www.python.org/dev/peps/pep-0398/"&gt;Python 3.3&lt;/a&gt;.  Here then is a summary, from my own spotty notes and memory, of how the sprint went.&lt;br /&gt;&lt;br /&gt;First, just a brief outline of what the PEP does.  For more details please read the PEP itself, or join the newly resurrected &lt;a href="http://mail.python.org/mailman/listinfo/import-sig"&gt;import-sig&lt;/a&gt; for more discussions.  The PEP has two main purposes.  First, it fixes the problem of which package owns a namespace's&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; __init__.py&lt;/span&gt; file, e.g. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;zope/__init__.py&lt;/span&gt; for all the Zope packages.  In essence, it eliminate the need for these by introducing a new variant of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.pth&lt;/span&gt; files to define a namespace package.  Thus, the &lt;i&gt;zope.interfaces&lt;/i&gt; package would own &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;zope/zope-interfaces.pth&lt;/span&gt; and the &lt;i&gt;zope.components&lt;/i&gt; package would own &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;zope/zope-components.pth&lt;/span&gt;.&amp;nbsp; The presence of either &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.pth&lt;/span&gt; file is enough to define the namespace package.&amp;nbsp; There's no ambiguity or collision with these files the way there is for &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;zope/__init__.py&lt;/span&gt;.&amp;nbsp; This aspect will be very beneficial for &lt;a href="https://blueprints.launchpad.net/ubuntu/+spec/foundations-o-dhpython-transition"&gt;Debian and Ubuntu&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Second, the PEP defines the one official way of defining namespace packages, rather than the multitude of ad-hoc ways currently in use.&amp;nbsp; With the pre-PEP 382 way, it was easy to get the details subtly wrong, and unless all subpackages cooperated correctly, the packages would be broken.&amp;nbsp; Now, all you do is put a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;*&lt;/span&gt; in the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.pth&lt;/span&gt; file and you're done.&lt;br /&gt;&lt;br /&gt;Sounds easy, right?&amp;nbsp; Well, Python's import machinery is pretty complex, and there are actually two &lt;a href="http://hg.python.org/cpython/file/d1d5a7392e39/Python/import.c"&gt;parallel&lt;/a&gt; &lt;a href="http://docs.python.org/py3k/library/importlib.html"&gt;implementations&lt;/a&gt; of it in Python 3.3, so gaining traction on this PEP has been a hard slog.&amp;nbsp; Not only that, but the PEP has implications for all the packaging tools out there, and changes the API requirements for &lt;a href="http://www.python.org/dev/peps/pep-0302/"&gt;PEP 302&lt;/a&gt; loaders.&amp;nbsp; It doesn't help that import.c (the primary implementation of the import machinery) has loads of crud that predates PEP 302.&lt;br /&gt;&lt;br /&gt;On the plus side, Martin von Loewis (the PEP author) is one of the smartest Python developers around, and he's done a very good first cut of an implementation in his &lt;a href="http://hg.python.org/features/pep-382/"&gt;feature branch&lt;/a&gt;, so there's a great place to start.&lt;br /&gt;&lt;br /&gt;Eric Smith (who is the 382 BDFOP, or benevolent dictator for one pep), Jason Coombs, and I&amp;nbsp; met once before to sprint on PEP 382, and we came away with more questions than answers.&amp;nbsp; Eric, Jason, and I live near each other so it's really great to meet up with people for some face-to-face hacking.&amp;nbsp; This time, we made a wider announcement, on social media and the &lt;a href="https://pangalactic.us/mailman/listinfo/bacon-pig"&gt;BACON-PIG mailing list&lt;/a&gt;, and were joined by three other local Python developers.&amp;nbsp; The &lt;a href="http://www.python.org/psf/"&gt;PSF&lt;/a&gt; graciously agreed to &lt;a href="http://pyfound.blogspot.com/2011/03/call-for-applications-sprint-funding.html"&gt;sponsor us&lt;/a&gt;, and while we couldn't get our first, second, third, or fourth choices of venues, we did manage to score some prime real-estate and free wifi at Panera.&lt;br /&gt;&lt;br /&gt;So, what did we accomplish?&amp;nbsp; Both a lot, and a little.&amp;nbsp; Despite working from about 4pm until closing, we didn't commit much more than a few bug fixes (e.g. an uninitialized variable that was crashing the tests on Fedora), a build fix for Windows, and a few other minor things.&amp;nbsp; However, we did come away with a much better understanding of the existing code, and a plan of action to continue the work online.&amp;nbsp; All the gory details are in the &lt;a href="http://wiki.python.org/moin/Pep382Sprint"&gt;wiki page&lt;/a&gt; that I created.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;One very important thing we did was to review the existing test suite for coverage of the PEP specifications.&amp;nbsp; We identified a number of holes in the existing test suite, and we'll work on adding tests for these.&amp;nbsp; We also recognized that importlib (the pure-Python re-implementation of the import machinery) wasn't covered at all in the existing PEP 382 tests, so Michael worked on that.&amp;nbsp; Not surprisingly, once that was enabled, the tests failed, since importlib has not yet been modified to support PEP 382.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;We also came up with a number of questions where we think the PEP needs clarification.&amp;nbsp; We'll start discussion about these on the relevant mailing lists.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Finally, Eric brought up a very interesting proposal.&amp;nbsp; We all observed how difficult it is to make progress on this PEP, and Eric commented on how there's a lot of historical cruft in &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;import.c&lt;/span&gt;, much of which predates PEP 302.&amp;nbsp; That PEP defines an API for extending the import machinery with new loaders and finders.&amp;nbsp; Eric proposed that we could simplify &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;import.c&lt;/span&gt; by removing all the bits that could be re-implemented as PEP 302 loaders, specifically the import-from-filesystem stuff.&amp;nbsp; The other neat thing is that the loaders could probably be implemented in pure-Python without much of a performance hit, since we surmise that the stat calls dominate. If that's true, then we'd be able to refactor &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;importlib&lt;/span&gt; to share a lot of code with the built-in C import machinery.&amp;nbsp; This could have the potential to greatly simplify &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;import.c&lt;/span&gt; so that it contains just the PEP 302 machinery, with some bootstrapping code.&amp;nbsp; It may even be possible to move most of the PEP 382 implementation into the loaders.&amp;nbsp; At the sprint we did a quick experiment with zipping up the standard library and it looked promising, so Eric's going to take a crack at this.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This is briefly what we accomplished at the sprint.&amp;nbsp; I hope we'll continue the enthusiasm online, and if you want to join us, please do subscribe to the import-sig!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-7994640580269719529?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/7994640580269719529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/06/pep-382-sprint-summary.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/7994640580269719529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/7994640580269719529'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/06/pep-382-sprint-summary.html' title='PEP 382 sprint summary'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-7830140131997852007</id><published>2011-05-19T14:27:00.009-04:00</published><updated>2011-05-19T23:54:36.890-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='uds-o'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='canonical'/><title type='text'>Python plans for Ubuntu 11.10 and 12.04</title><content type='html'>TL;DR: Ubuntu 12.04 LTS will contain only Python 2.7 and 3.2, while Ubuntu 11.10 will contain Python 3.2, 2.7 and possibly 2.6, but possibly not.&lt;br /&gt;&lt;br /&gt;Last week, I attended the &lt;a href="http://summit.ubuntu.com/uds-o/"&gt;Ubuntu Developer Summit&lt;/a&gt; in &lt;a href="http://www.corinthia.com/en/Budapest/home/"&gt;Budapest, Hungary&lt;/a&gt;.  These semi-annual events are open to everyone, and hundreds of people participate both in person and remotely.  Budapest's was called &lt;span style="font-style: italic;"&gt;UDS-O&lt;/span&gt;, where the 'O' stands for &lt;a href="http://www.markshuttleworth.com/archives/646"&gt;Oneiric Ocelot&lt;/a&gt;, the code name for Ubuntu 11.10, which will be &lt;a href="https://wiki.ubuntu.com/OneiricReleaseSchedule"&gt;released in October 2011&lt;/a&gt;.  This is where we did the majority of planning for what changes, new features, and other developments you'll find in the next version of Ubuntu.  UDS-P will be held at the end of the year in Orlando, Florida and will cover the as yet unnamed 12.04 release, which will be a &lt;a href="https://wiki.ubuntu.com/LTS"&gt;Long Term Support&lt;/a&gt; release.&lt;br /&gt;&lt;br /&gt;LTS releases are special, because we make longer guarantees for official support: 3 years on the desktop and 5 years on the server.  Because of this, we're making decisions now to ensure that 12.04 LTS is a stable, confident platform for years to come.&lt;br /&gt;&lt;br /&gt;I attended many sessions, and there is a lot of exciting stuff coming, but I want to talk in some detail about one area that I'm deeply involved in.  What's going to happen with &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; for Oneiric and 12.04 LTS?&lt;br /&gt;&lt;br /&gt;First, a brief summary of where we are today.  &lt;a href="http://www.techdrivein.com/2011/05/ubuntu-1104-natty-narwhal-reviewed-this.html"&gt;Natty Narwhal&lt;/a&gt; is the code name for Ubuntu 11.04, which was released back in April and is the &lt;a href="http://www.ubuntu.com/download"&gt;most recent stable release&lt;/a&gt;.  It is not an LTS though; the last LTS was &lt;a href="https://wiki.ubuntu.com/LucidLynx"&gt;Ubuntu 10.04 Lucid Lynx&lt;/a&gt;, release back in October 2010.  In Lucid, the default Python (i.e. &lt;span style="font-family:courier new;"&gt;/usr/bin/python&lt;/span&gt;) is 2.6 and Python 2.7 is not officially supported or available.  Python 3.1 is available for Lucid, but not installed by default.&lt;br /&gt;&lt;br /&gt;In Natty, the default Python is &lt;a href="http://www.python.org/download/releases/2.7.1/"&gt;2.7&lt;/a&gt; with &lt;a href="http://www.python.org/download/releases/2.6.6/"&gt;2.6&lt;/a&gt; still being officially supported.  This means that you can have both Python 2.6 and 2.7 on your Natty machine, and where possible, packages were built for both Python versions.  Where this was not possible, you'll almost always find a package for Python 2.7 instead of 2.6.  Natty also has Python &lt;a href="http://www.python.org/download/releases/3.2/"&gt;3.2&lt;/a&gt; and &lt;a href="http://www.python.org/download/releases/3.1.3/"&gt;3.1&lt;/a&gt; available, with 3.2 being the default.&lt;br /&gt;&lt;br /&gt;Two more bits of background are useful to know.  In Ubuntu (inherited from &lt;a href="http://www.debian.org/"&gt;Debian&lt;/a&gt;, where most packages are initially developed), we separate Python 2 support and Python 3 support into separate "stacks", meaning entirely separate binary packages even if the source packages are the same.  This has many benefits, including allowing a system administrator to only install the Python 2 stack, or only the Python 3 stack if they want.  It also makes for our eventual transition to Python 3 much easier, because packages don't need to be renamed.  So for example, if you see a package named &lt;span style="font-style: italic;"&gt;"python-foo"&lt;/span&gt; you know this is the &lt;span style="font-style: italic;"&gt;Foo&lt;/span&gt; package for Python 2.  You might also see a &lt;span style="font-style: italic;"&gt;"python3-foo"&lt;/span&gt; which would be the Python 3 version of &lt;span style="font-style: italic;"&gt;Foo&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Also, many packages are built for all supported versions in a particular stack.  So for example, if we want to make &lt;span style="font-style: italic;"&gt;Foo&lt;/span&gt; available for both Python 2.6 and 2.7, we'll include support for both in a single &lt;span style="font-style: italic;"&gt;python-foo&lt;/span&gt; package.  Pure Python source code is generally easily shared, so this reduces the duplication (more on this in another blog posting), however extension modules, which are usually implemented in &lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/C_%28programming_language%29"&gt;C&lt;/a&gt;, must be compiled twice, and both shared libraries must be included in the same binary package.  This means if we are supporting package &lt;span style="font-style: italic;"&gt;Example&lt;/span&gt; which contains an extension module, for both Python 2.6 and 2.7, the binary package will contain two shared libraries, effectively doubling the disk consumption for extension module support.&lt;br /&gt;&lt;br /&gt;Keep all that in mind as I describe what comes next!&lt;br /&gt;&lt;br /&gt;To understand our plans for Oneiric, it's first useful to explain our goals for the next LTS, since we'll be using 11.10 as a transitional cycle.  For 12.04 LTS, we want to support just one Python 2 version and just one Python 3 version.  Because Python 2.6 is in security-fix only mode in upstream Python, we want to drop support for it in 12.04 LTS.  This will also allow us to reclaim some space on the installation CDs because we won't need to include extension modules compiled for both Python 2.6 and 2.7.  Last cycle we calculated the savings at about 10MiB, which is not insignificant on a standard CD.&lt;br /&gt;&lt;br /&gt;For 12.04 LTS, the only Python 3 version we want to support is Python 3.2.  Our thinking here is that there really isn't much code out there that depends on Python 3 yet, and Python 3.2 has &lt;a href="http://docs.python.org/dev/whatsnew/3.2.html"&gt;many&lt;/a&gt; &lt;a href="http://www.python.org/dev/peps/pep-3147/"&gt;very&lt;/a&gt; &lt;a href="http://www.python.org/dev/peps/pep-3149/"&gt;useful&lt;/a&gt; &lt;a href="http://docs.python.org/dev/whatsnew/3.2.html#email"&gt;features&lt;/a&gt; that make it (IMO) the first Python 3 to start basing production quality code on.  We're going to put our money where our mouth is here, and I'll write more on that later too.&lt;br /&gt;&lt;br /&gt;The decision to drop Python 3.1 support for 12.04 LTS is, as far as I know, completely uncontroversial, so this will happen in Oneiric.  And because &lt;a href="http://www.python.org/dev/peps/pep-0398/"&gt;Python 3.3 will not be released&lt;/a&gt; before 12.04 LTS, we will be making that change very soon, so as to provide the longest possible period of stabilization and porting between now and April 2012.  If you've been holding off on developing for Python 3, &lt;a href="http://wiki.python.org/moin/PortingPythonToPy3k"&gt;now is a great time to jump in&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;Dropping Python 2.6 is somewhat more controversial for several reasons.  First, in Ubuntu, we rely very heavily on Debian for the majority of packages, and we strongly encourage our developers to submit patches and new packages in Debian first, with requests for syncing to Ubuntu once they're available in Debian.  My take on this relationship is that, because Ubuntu has strictly timed releases while Debian has a "release-when-ready" policy, we can often use Ubuntu's development cycle to blaze a trail (sometimes on the bleeding edge ;) but it's always critical to ensure that wherever possible, Debian contains the authoritative versions of our packages.  Now that Debian has released &lt;a href="http://www.debian.org/releases/stable/"&gt;Squeeze&lt;/a&gt; and is working on its &lt;a href="http://www.debian.org/releases/testing/"&gt;Wheezy&lt;/a&gt; release, it's time for us to push our Ubuntu changes back into Debian, and work on getting the latest upstream versions into Debian, while syncing back to Ubuntu.  For this reason, we just don't want to get too far ahead of Debian in our Python support.  Our plan therefore is to continue to support Python 2.6 until Debian has completed their &lt;a href="http://release.debian.org/transitions/"&gt;transition&lt;/a&gt; to Python 2.7 as the default version (they already support both, but Python 2.6 is still the default).&lt;br /&gt;&lt;br /&gt;Our timeline therefore is to make a final decision on Python 2.6's fate for Oneiric by feature freeze.  If Debian still hasn't completed their transition by then, we'll keep Python 2.6 for Oneiric and drop it as soon as the archive opens for 12.04 LTS.  This should be pretty low risk for us, and it helps us better align ourselves with Debian, which is always a good thing!  If you feel so inclined, you can help by working on some of the &lt;a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=622279"&gt;blocker bugs for Debian's transition to Python 2.7&lt;/a&gt;, as we will also be doing.&lt;br /&gt;&lt;br /&gt;Another reason to be cautious about dropping Python 2.6 is because many of the services in our own data center are not yet ported to Python 2.7.  Probably the biggest of such services is &lt;a href="http://launchpad.net/"&gt;Launchpad&lt;/a&gt;.  Our data center machines always run the previous LTS, and Lucid does not have Python 2.7, so this makes for a kind of Catch-22 for the Launchpad team.  To address this, we've created a &lt;a href="https://launchpad.net/%7Epythoneers/+archive/lts"&gt;quasi-official&lt;/a&gt; &lt;a href="https://help.launchpad.net/Packaging/PPA"&gt;PPA&lt;/a&gt; into which we'll backport Python 2.7 and many dependent modules.  The Launchpad team can then use this PPA to work on their own port to Python 2.7 in plenty of time for 12.04 LTS.  Anybody else out there who wants to do the same can also use our PPA, and if they need additional modules backported, they can create their own PPA which depends on ours for the base support.&lt;br /&gt;&lt;br /&gt;So, that's what's happening, and why.  Feedback is of course invited here, on the ubuntu-devel mailing list, or to me directly.  If you want to follow along, you can take a look at the &lt;a href="https://blueprints.launchpad.net/ubuntu/+spec/foundations-o-python-versions"&gt;blueprint &lt;/a&gt;describing these changes, and more.&lt;br /&gt;&lt;br /&gt;In the next articles, I plan to discuss how we're going to get to Python 3 only on the Ubuntu CDs, and how we're going to help with the &lt;a href="https://blueprints.launchpad.net/ubuntu/+spec/foundations-o-dhpython-transition"&gt;migration to dh_python2&lt;/a&gt;.  Cheers!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-7830140131997852007?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/7830140131997852007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/05/python-plans-for-ubuntu-1110-and-1204.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/7830140131997852007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/7830140131997852007'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/05/python-plans-for-ubuntu-1110-and-1204.html' title='Python plans for Ubuntu 11.10 and 12.04'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-8134008799547405910</id><published>2011-04-15T09:21:00.005-04:00</published><updated>2011-04-15T10:13:08.218-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='test drive'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='virtual machine'/><title type='text'>My Natty Upgrade Test</title><content type='html'>&lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; 11.04 (code name: Natty Narwhal) &lt;a href="http://www.ubuntu.com/testing"&gt;beta 2 was just released&lt;/a&gt; and the final release is right around the corner.  Canonical internal policy is that we upgrade to the latest in-development release as soon as it goes beta, to help with bug fixing, test, and quality assurance.&lt;br /&gt;&lt;br /&gt;Now, I've been running Natty on my primary desktops (my two laptops) since before alpha 1, and I've been very impressed with the stability of the core OS.  One of my laptops cannot run &lt;a href="http://unity.ubuntu.com/"&gt;Unity&lt;/a&gt; though, so I've mostly been a classic desktop user until recently.  My other laptop can run Unity, but compiz and the wireless driver were too unstable to be usable, that is until just before beta 1.  Still, I diligently updated both machines daily and at least on the classic desktop, Natty was working great.  (Now that beta 1 is out, the wireless and compiz issues have been cleared up and it's working great too.)&lt;br /&gt;&lt;br /&gt;The real test is my beefy workstation.  This is a Dell Studio XPS 435MT 12GB, quad-core i7-920, with an ATI Radeon HD 4670 graphics card, running dual-headed into two Dell 20" 1600x1200 flat panel displays.  During the &lt;a href="http://ubuntuguide.org/wiki/Ubuntu:Maverick"&gt;Maverick&lt;/a&gt; cycle I was a little too aggressive in upgrading it, because neither the free nor the proprietary drivers were ready to handle this configuration yet.  I ended up with a system that either couldn't display any graphics, or didn't support the dual heads.  This did eventually all get resolved before the final release, but it was kind of painful.&lt;br /&gt;&lt;br /&gt;So this time, I was a little gun shy and wanted to do more testing before I committed to upgrading this machine.  Just before Natty beta 1, I dutifully downloaded the &lt;a href="http://cdimages.ubuntu.com/"&gt;daily liveCD ISO&lt;/a&gt;, and booted the machine from CD.  On the surface, things seemed promising.  I had compiz and Unity, but no dual-head.  Running from the liveCD is fairly transient though; it doesn't save enough state between reboots to be a fair test of the machine.&lt;br /&gt;&lt;br /&gt;How could I get a true test of Natty that would give me my normal development environment, run natively on the hardware, and yet be easily discarded if it turned out to not be ready yet?  Here's where USB hard drives and virtual machines come in.&lt;br /&gt;&lt;br /&gt;I'm a very heavy user of &lt;a href="http://libvirt.org/"&gt;virtual machines&lt;/a&gt;.  With plenty of disk space on this 1.5TB drive, I have maybe a dozen VMs.  This let's me run the stable Ubuntu release as a host, and have VMs for several versions of &lt;a href="http://www.debian.org"&gt;Debian&lt;/a&gt;, several older versions of Ubuntu, and even flavors of Windows, Solaris, FreeBSD, and Fedora.  (Let me know if you've successfully made a libvirt guest running as a &lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/Hackintosh"&gt;hackintosh&lt;/a&gt; for OS X!).  Some day I'll post about safe, copy-on-write backing disks.&lt;br /&gt;&lt;br /&gt;Now, the cool thing about these VMs is that I bridge the network and give all of them unique IP addresses on my internal network, so for all intents and purposes, they are real machines.  Most of them I access only through ssh, but &lt;a href="http://virt-manager.et.redhat.com/"&gt;virt-manager&lt;/a&gt; gives a nice graphical desktop when you need it.  So I can mostly test just about anything on any x86 or amd64 operating system, with my full normal development environment.&lt;br /&gt;&lt;br /&gt;So here was my thinking: create a Natty VM that wouldn't use the normal virtual disk living in a file on the host file system.  Instead, its disk would actually be on a 320GB USB external drive that I had laying around.  I'd install Natty to this VM using the daily liveCD, get my full development environment up and running, then I'd shut down the host, and reboot it to the USB drive.  This would give me a persistent Natty running natively on the hardware, and if it didn't work out, I'd just reboot back to the internal drive.  No fuss, no muss.&lt;br /&gt;&lt;br /&gt;Let's cut to the chase: I eventually got this to work, and spent a day putting Natty through its paces.  After few pre-beta-1 updates, I was satisfied that all my hardware was working great, including full resolution dual-head with Unity.  That gave me the confidence to upgrade the host OS running on the internal drive, and I've been happily using it since then.&lt;br /&gt;&lt;br /&gt;Of course, all was not smooth sailing.  I did run into a few hitches along the way.&lt;br /&gt;&lt;br /&gt;When the primary host operating system mounted the USB drive, it often got different /dev device assignments.  Sometimes it would come up as /dev/sdc and sometimes as /dev/sdg.  The problem with this is that libvirt wants to use the /dev name as the device for the VM's file system, so when this changed, I'd have to go into the VM's configuration and fix the storage device path.  This is kind of a pain through the virt-manager U/I since the storage device has to be deleted and then re-added.  You can't just change the path (I'll bet it can be done by editing the .xml configuration file directly).&lt;br /&gt;&lt;br /&gt;When creating the storage device for the VM, you have several options for the disk type.  At first, I naturally chose USB disk, since in fact, the physical device was a USB drive.  But this tended to cause the Ubiquity installer no end of trouble.  It hung very early in the installation process.  I never did investigate that or get it working, but I did realize that if you use a virtio disk and point it at the USB device path (see above), the installer worked perfectly.&lt;br /&gt;&lt;br /&gt;You have to be sure your host machine's BIOS can boot off of a USB drive.  Luckily this is a new enough machine that it works fine, but older machines may not be able to boot off a USB drive.  I think you could probably just do everything I've done above, but installing that spare drive internally and it would work just as well.  But of course opening up the case is a PITA. :)&lt;br /&gt;&lt;br /&gt;&lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/GNU_GRUB"&gt;Grub&lt;/a&gt; was a little finicky.  I first tried this just a few days before beta 1, and every time I installed the OS to the USB drive, then booted off the drive I'd immediately be dropped into a grub&amp;gt; prompt, with no way to complete the boot process.  It was like grub was not getting installed correctly, but at the time I also wasn't sure whether this idea could even work.  Note that I did not want to add the USB drive to the chain loader on the primary internal drive, I just wanted to hit F12 during the BIOS phase and select the USB drive to boot off of.  I thought this *should* work, but it didn't and I thought maybe something about the virtual environment caused grub to fail when run natively.  I asked around on our internal tech list, but I think this was really a transient problem with the pre-beta ISOs.  I tried again a day or so later with a new liveCD and everything worked perfectly.&lt;br /&gt;&lt;br /&gt;Of course, when booting off the USB drive natively, a few things are different.  The virtual machine has a different MAC address, and thus a different host name and IP address than the native host.  So after booting off the USB drive, you have to fiddle with a few things to get that to line up, depending on how you configure your machine.  E.g. /etc/hosts was incorrect.  These minor problems didn't really slow me down though.&lt;br /&gt;&lt;br /&gt;Ignoring the transient, inexplicable grub issue, this turned out to be a very nice way to test drive the new Ubuntu version on the native hardware, in a completely non-destructive way.  I'll bet it would work to test drive other operating systems as well, and if one of my fantastic readers gives me a clue about how to build a hackintosh in a VM, I'll give that a try for the fun of it.  And of course I'll let you know how it goes!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-8134008799547405910?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/8134008799547405910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/04/my-natty-upgrade-test.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/8134008799547405910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/8134008799547405910'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/04/my-natty-upgrade-test.html' title='My Natty Upgrade Test'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-6073301235500754351</id><published>2011-04-04T12:24:00.003-04:00</published><updated>2011-04-04T12:37:13.987-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mailman'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='floss'/><category scheme='http://www.blogger.com/atom/ns#' term='opensource'/><title type='text'>Release that rewrite on 11.11.11</title><content type='html'>I know that the &lt;a href="http://wiki.list.org/display/DEV/Mailman+3.0"&gt;Mailman 3 project&lt;/a&gt; is not alone in procrastinating getting out a release of its major rewrite.  It's hard work to finish a rewrite on your own copious spare time.  I was just chatting with Thomas Waldmann of the &lt;a href="http://moinmo.in/"&gt;Moin&lt;/a&gt; project on IRC, and he lamented a similar story about the &lt;a href="http://moinmo.in/MoinMoin2.0"&gt;Moin 2&lt;/a&gt; release.  Then he said something that really made me sit up straight:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;lt;ThomasWaldmann&amp;gt; 11.11.11 would be a great date for something :)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Yes, it would!  We have the &lt;a href="http://wiki.list.org/display/DEV/Google+Summer+of+Code+2011"&gt;2011 Google Summer of Code&lt;/a&gt; happening soon (students, you have until April 8th to &lt;a href="http://wiki.python.org/moin/SummerOfCode/2011"&gt;submit your applications&lt;/a&gt;) so many free and open source software projects will get some great code coming soon.  And November is far enough out that we can plan exactly what a "release" means.  Here's what I propose:&lt;br /&gt;&lt;br /&gt;Let's make November 11, 2011 the "Great FLOSS Release Day".  If you're working on an open source project undergoing a major new version rewrite, plan on doing your release on 11.11.11.  It can be a beta or final release, but get off your butts and make it happen!  There's nothing like a good deadline to motivate me, so Mailman 3 will be there.  Add a comment here if you want your project to be part of the event!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-6073301235500754351?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/6073301235500754351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/04/release-that-rewrite-on-111111.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6073301235500754351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6073301235500754351'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/04/release-that-rewrite-on-111111.html' title='Release that rewrite on 11.11.11'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-1370031589691296513</id><published>2011-03-28T18:36:00.007-04:00</published><updated>2011-03-28T20:04:21.949-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Charming Snakes and Shaving Yaks</title><content type='html'>For the last couple of days I've been &lt;a href="https://bugs.launchpad.net/ubuntu/+source/python2.7/+bug/711225/+index"&gt;debugging a fun problem&lt;/a&gt; in the Ubuntu tool called Jockey.  Jockey is a tool for managing device drivers on &lt;a href="http://www.ubuntu.com"&gt;Ubuntu&lt;/a&gt;.  It actually contains both a command-line and a graphical front-end, and a dbus backend service that does all the work (with proper authentication, since it modifies your system).  None of that is terribly relevant to the problem, although the dbus bit will come back to haunt us later.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What is important is that Jockey is a Python application, written using many Python modules interfacing to low-level tools such as apt and dbus.  The original bug report was mighty confusing.  Aside from not being reproducible by myself and others, the actual exception made no fricken sense!  Basically, it was code like this that was throwing a &lt;span class="Apple-style-span"  &gt;TypeError&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  &gt;_actions = []&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  &gt;# _actions gets appended to at various times and later...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  &gt;for item in _actions[:]:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  &gt;   # do something&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Everyone who reported the problem said the &lt;span class="Apple-style-span"  &gt;TypeError&lt;/span&gt; was getting thrown on the &lt;span class="Apple-style-span"  &gt;for&lt;/span&gt;-statement line.  The exception message indicated that Python was getting some object that it was trying to convert to an integer, but was failing.  How could you possible get that exception when either making a copy of a list or iterating over that copy?  Was the list corrupted?  Was it not actually a list but some &lt;span class="Apple-style-span"  &gt;list&lt;/span&gt;-like object that was somehow returning non-integers for its min and max indexes?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To make matters worse, this little code snippet was in Python's standard library, in the subprocess module. A quick search of Python's bug database did reveal some recent threads about changes here, made to ensure that popen objects got properly cleaned up by the garbage collector if they weren't cleaned up explicitly by the program.  Note that we're using Python 2.7 here, and after some reading of the tracker issues and the Python subprocess.py code, I just couldn't see any problem here, or at least none that could possibly lead to the error being seen.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When I originally looked at the Launchpad bug report, that was about as far as I got.  I couldn't see any possible way this bug could happen, and I couldn't reproduce it, so I set the bug to Incomplete.  Unfortunately, it kept hitting Ubuntu Natty beta testers so it wasn't going to go away.  Fortunately, Martin Pitt found a test recipe, with which I could reproduce the bug 100% of the time.  Yay!  At least it probably wasn't going to be a race condition.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;How to debug this though?  Normally, I'd just attach gdb to the thing and start tracing, but the problem was that when I set the Jockey dbus backend to use the debug version of Python, the error went away (or rather morphed into something that was &lt;i&gt;really&lt;/i&gt; unrelated).  Here's where I started to sharpen up my favorite yak shaving blade.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The parable about shaving yaks is so entirely appropriate to problems like this that I'll take a quick detour.  One of my (and my brother's) favorite shows in the 90's was &lt;a href="http://en.wikipedia.org/wiki/Ren_and_stimpy"&gt;Ren and Stimpy&lt;/a&gt;.  That show was groundbreaking, and you can see elements of it in just about every NickToons cartoon on cable today.  Some of the episodes are brilliant and others are horrible but as a whole, Ren and Stimpy are an undeniable classic of American animation.  In one particular awesome episode, Ren and Stimpy celebrate &lt;a href="http://www.youtube.com/watch?v=KC3ieK2c5Jw"&gt;Kilted Yaks-eve&lt;/a&gt; where a Yak comes up from the tub drain and shaves his stubble, leaving behind a present of the highly desired shaving scum for Stimpy in the morning.  Based on this episode (most likely!) the programming term "&lt;a href="http://en.wiktionary.org/wiki/yak_shaving"&gt;yak shaving&lt;/a&gt;" typically means having to take detour after meaningless detour before you can actually solve the problem you're having.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the context of this bug, the attempt to use the debug build of Python in the Jockey dbus backend was the first yak to shave.  Because I wanted to get more information out of the process, I tried to attach to a running backend process, but this proved to be quite difficult.  I was debugging this in a 64bit virtual machine, and gdb+debug-python was just not cooperating.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now the question is: do you debug &lt;i&gt;that&lt;/i&gt; problem (or at least get to a place where you can decide to file a bug or not), or do you punt and try a different approach?  The former is most definitely shaving the yak; it gets you no closer to fixing the original problem, but certain wastes enough of your time to make you seem productive.  Of course, it's inevitable that if you do follow that secondary bug, it'll lead to a third one, and a fourth one, and so on until you're deep in the shaving scum and no closer to a solution to the &lt;i&gt;original &lt;/i&gt;problem.  You need to be constantly on guard against these types of yak, er, rabbit holes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll spare you the gory details about hitting bugs in my text editor, &lt;a href="http://bugs.python.org/issue1294959"&gt;bugs in building Python on a multiarch system&lt;/a&gt;, and other paths that all lead to smooth chinned yaks, but not to happy Pythons.  When I punted on trying to attach to the Jockey backend, I actually decided to try to figure out exactly where the &lt;span class="Apple-style-span"  &gt;TypeError&lt;/span&gt; was occurring by using a twist on old-fashioned print statements.  By grepping the Python source I found about a dozen occurrences of the error message "an integer is required".  Which one was getting tripped?  I added a little marker text to every such occurrence and re-built a Python package to aid in debugging.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's where I &lt;i&gt;did&lt;/i&gt; detour to yak shaving.  The Ubuntu source package for Python itself, runs the full test suite on every build.  That's great for ensuring a high quality Python package, but it's terrible for turnaround time when experimentally hacking Python.  Building the package with &lt;span class="Apple-style-span"  &gt;DEB_BUILD_OPTIONS="nocheck nobench"&lt;/span&gt; is &lt;i&gt;supposed&lt;/i&gt; to work, but for some reason did not with my &lt;a href="https://wiki.ubuntu.com/SecurityTeam/BuildEnvironment"&gt;sbuild&lt;/a&gt; environment.  I guess debugging that would have been like shaving the yak's left check, but instead it was so much easier to shave his right check.  So I spent some time with my razor chopping out huge sections of the debian/rules file so that Python 2.7 would build as fast as possible.  While a seemingly meaningless task, this did actually help quite a bit since I was able to try out ideas with a much shorter turnaround.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, with many iterations on the exception marking idea, I finally nailed down the culprit.  It was in the Python C API function &lt;span class="Apple-style-span"  &gt;PyInt_AsLong()&lt;/span&gt;&lt;span class="Apple-style-span" &gt;, but even here I was unsure which arm of the conditional was getting triggered.  Another round of hack-build-scp-reset-test and I found what I suspected:&lt;span class="Apple-style-span" &gt; PyInt_AsLong(&lt;/span&gt;&lt;/span&gt;) was getting passed an object that could not be turned into an integer.  But what was that object?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So now back to the original problem with gdb.  To solve this I downloaded and built a 32bit virtual machine, and was able to reproduce the bug there.  Fortunately, in the 32bit environment I was much more successful in attaching to a running backend Jockey dbus process, and even though I didn't have the Python source available (and no, I won't talk about where &lt;i&gt;that&lt;/i&gt; particular yak shaving detour led), I could fairly easily print the objects in the debugger at the offending code, where I learned that &lt;span class="Apple-style-span"  &gt;PyInt_AsLong()&lt;/span&gt; was getting called with &lt;span class="Apple-style-span"  &gt;None&lt;/span&gt; as its argument.  And yeah, you can't turn &lt;span class="Apple-style-span"  &gt;None&lt;/span&gt; into an integer in Python!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But, how was this function getting called with &lt;span class="Apple-style-span"  &gt;None&lt;/span&gt;?  Popping up the call stack led me eventually to &lt;span class="Apple-style-span"  &gt;PyArg_Parse()&lt;/span&gt;, an older C API function that parses a Python tuple into a set of objects based on some format flags.  This is used when implementing Python functions in C, to parse an argument list.  Popping up the stack again led me into some python-apt code.   python-apt is a C++ library that exposes the APT system to Python programs.  It's fairly mature and robust, but I wasn't as familiar with all its dark corners as I was with Python.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, my first instinct is never that I've found a bug in Python. That's not to say they don't exist, but just that Python has been around so long, is so well tested, and used so extensively that I'm always suspicious in cases like this (i.e. strange, inexplicable bugs that make no sense) of extension modules and third party code.  And indeed, my sleuthing has led me to python-apt, exactly the kind of complex Python extension module that can have odd lurking bugs in it.  Still, the problem I was now faced with was this: the call stack led me into a code path that had nothing to do with iterating over a list, or copying that list.  So, what gives?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, it's useful to know how Python exceptions work at the C level.  In general terms, when some C code raises an exception, it basically sets some global state, and then returns error codes up the stack until either something catches it and deals with it, or it percolates up to Python's top eval loop.  The key thing here is that there are usually &lt;i&gt;two&lt;/i&gt; states that exist: the global exception value currently in effect, and an error code that gets returned up the C call stack.  Usually this return code is a zero or one, but it can also be &lt;span class="Apple-style-span"  &gt;NULL&lt;/span&gt; or -1 in certain cases.  The Python C API documentation is very good at describing these.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So now that I looked closely at the python-apt code, I could see what what going on and it all began to make sense!  The python-apt package was &lt;i&gt;pulsing&lt;/i&gt; a progress meter, set up as a callback by the client of the python-apt code.  Meaning, python-apt couldn't really control what this callback would return.  python-apt &lt;i&gt;expected&lt;/i&gt; the callback to return either Python's &lt;span class="Apple-style-span"  &gt;True&lt;/span&gt; or &lt;span class="Apple-style-span"  &gt;False&lt;/span&gt;, but it could return anything, including nothing!  In Python, &lt;span class="Apple-style-span"  &gt;True&lt;/span&gt; can be coerced into the integer 1 and &lt;span class="Apple-style-span"  &gt;False&lt;/span&gt; into the integer 0, and python-apt wanted an integer, so indeed the call stack lead right to a call to &lt;span class="Apple-style-span"  &gt;PyArg_Parse()&lt;/span&gt; to turn the callback's return object into an integer.  What happens if the callback didn't return something that could be turned into an integer, or worse, didn't return anything at all?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In Python, a function &lt;i&gt;always&lt;/i&gt; returns something, even if there is no explicit return statement. In those cases, &lt;span class="Apple-style-span"  &gt;None&lt;/span&gt; is implicitly returned.  Yes, you see it now.  And if not, there was this clue in the python-apt code: &lt;i&gt;"most of the time the user who subclasses the pulse() method forgot to add a return {True,False} so we just assume he wants a True."&lt;/i&gt;  Translated: Hey guy!  You forgot to add a "return True" or "return False" to your &lt;span class="Apple-style-span"  &gt;pulse()&lt;/span&gt; method, and it probably fell of the end, giving us &lt;span class="Apple-style-span"  &gt;None&lt;/span&gt;, which we dutifully passed to &lt;span class="Apple-style-span"  &gt;PyArg_Parse()&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  &gt;PyArg_Parse()&lt;/span&gt; did its thing when getting &lt;span class="Apple-style-span"  &gt;None&lt;/span&gt;, by correctly setting the global exception state to the &lt;span class="Apple-style-span"  &gt;TypeError&lt;/span&gt;, and returning a zero code to indicate an error occurred.  But looking at the python-apt code, it recognizes the error code, but &lt;b&gt;forgets that some global exception state was set&lt;/b&gt;!  Meaning, even though python-apt was ignoring the exception, Python still knew about it.  But because control wasn't being passed on up to the Python eval loop, the exception was just lurking there like a angry unshaven yak, waiting to be discovered.  And in fact, the next time Python itself checked the exception state was in, yep, the &lt;span class="Apple-style-span"  &gt;for&lt;/span&gt;-loop iterating over the perfectly fine list object.  Python hits the &lt;span class="Apple-style-span"  &gt;for&lt;/span&gt;-loop, finds this orphaned &lt;span class="Apple-style-span"  &gt;TypeError&lt;/span&gt; lurking there and raises it, in a place that has literally nothing to do with the original exception.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The fix is a one-liner.  In python-apt, where its ignoring any exception returned by &lt;span class="Apple-style-span"  &gt;PyArg_Parse()&lt;/span&gt;, it must both swallow the error code (which it was doing), &lt;i&gt;and&lt;/i&gt; clear the global exception state (which it was &lt;i&gt;not&lt;/i&gt;doing).  By adding a call to &lt;span class="Apple-style-span"  &gt;PyErr_Clear()&lt;/span&gt;, python-apt was keeping the interpreter's state consistent, and properly ignoring the argument parsing error, thus fixing the bug.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As I mentioned to my colleague Colin Watson, this did turn out to be a fun one to debug, though not as "fun" as &lt;a href="http://www.chiark.greenend.org.uk/ucgi/~cjwatson/blosxom"&gt;one he recently worked on&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Happy Yak Shaving.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-1370031589691296513?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/1370031589691296513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2011/03/charming-snakes-and-shaving-yaks.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/1370031589691296513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/1370031589691296513'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2011/03/charming-snakes-and-shaving-yaks.html' title='Charming Snakes and Shaving Yaks'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-5130308646721307506</id><published>2010-09-09T18:15:00.017-04:00</published><updated>2011-03-22T09:51:00.740-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='canonical'/><title type='text'>What We Do</title><content type='html'>My friends and &lt;a href="http://www.warsaw.us/"&gt;family&lt;/a&gt; often ask me what I do at &lt;a href="http://www.canonical.com/"&gt;my job&lt;/a&gt;.  It's easy to understand when my one brother says he's a &lt;a href="http://www.ey.com/"&gt;tax accountant&lt;/a&gt;, but not so easy to explain the complex world of &lt;a href="http://en.wikipedia.org/wiki/Open-source_software"&gt;open source&lt;/a&gt; software development I live in.  Sometimes I say something to the effect: well, you know what &lt;a href="http://image.blog.bitcomet.com/postpic/20080403/1635675_ydtvpx080403120240.gif"&gt;Windows&lt;/a&gt; is, and you know what &lt;a href="http://www.lockergnome.com/dannyminick/files/2010/01/34jan29-fanboy.jpg"&gt;the Mac&lt;/a&gt; is right?  We're building a third alternative called &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; that is free, &lt;a href="http://en.wikipedia.org/wiki/Linux"&gt;Linux&lt;/a&gt;-based and in most cases, much better.  Mention that you won't get viruses and it can easily breathe new life into that old slow PC you shudder to turn on, and people at least nod their heads enthusiastically, even if they don't fully get it.&lt;br /&gt;&lt;br /&gt;I've been incredibly fortunate in my professional career, to have been able to share the software I write with the world for almost 30 years.  I started working for a &lt;a href="http://www.nist.gov/index.html"&gt;very cool research lab&lt;/a&gt; with the US Federal government while still in high school.  We had a &lt;a href="http://en.wikipedia.org/wiki/Uucp"&gt;UUCP&lt;/a&gt; connection and were on the early &lt;a href="http://en.wikipedia.org/wiki/Arpanet"&gt;Arpanet&lt;/a&gt;, and because we were funded by the US taxpayer, our software was not subject to copyright.  This meant that we could share our code with other people on &lt;a href="http://en.wikipedia.org/wiki/Usenet"&gt;Usenet&lt;/a&gt; and elsewhere, collaborate with them, accept their suggestions and improvements, and hopefully make their lives a little better, just as others around the world did for us.  It was free and open source software before such terms were coined.  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've never had a "real job" in the sense of slaving away in a &lt;a href="http://blogs.e-rockford.com/movieman/files/2008/10/milton.jpg"&gt;windowless cube&lt;/a&gt; writing solely proprietary software that would never see the light of day.  Even the closed source shops I've worked have been invested somehow in &lt;a href="http://en.wikipedia.org/wiki/Free_software"&gt;free software&lt;/a&gt;, and with varying degrees of persuasion, have both benefited from and contributed to the free and open source ecosystem.  Thus, in many ways, my current position at Canonical feels like the perfect fit and ultimate destination for my background, skills, and passion.  &lt;a href="http://www.canonical.com/about-canonical/canonical-and-open-source"&gt;Canonical is open source to its core&lt;/a&gt;.  Its central mission, as articulated by our founder &lt;a href="http://www.markshuttleworth.com/"&gt;Mark Shuttleworth&lt;/a&gt; is "to bring free software to the widest possible audience, powered by services rather than licenses, in tune with a world that was moving to services as the core economic model of a digital world."  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To me, the free and open source ethos goes much deeper than just the software we write.  It's about collaboration, community, sharing, learning, teaching, and having a truly positive impact on the world.  It's about empowering individuals to realize their full potential, to give them the opportunity to build a merit based reputation, to carve out their own areas of interest and expertise, and relate that to the larger society, to know that they make a difference, and that their opinions and contributions matter.  Open source is about having the courage of your convictions, but embracing humility to admit when you're wrong and someone else has a better idea.  To encourage and actively seek out consensus, but also to cultivate a thoughtful and compassionate process for making the hard decisions when consensus can't be reached.  It's about spreading enthusiasm and rallying others to your side sometimes, and at other times humbly and joyfully embracing other points of view.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I could go on with all the mushy goodness, but let's look at a few areas where the work I do for Canonical directly contributes to the broader free and open source ecosystem.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Python&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've been a core &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; developer since about 1995, and have served several times as release manager for major new versions.  As part of my job on the &lt;a href="https://wiki.ubuntu.com/FoundationsTeam"&gt;Ubuntu Platform Foundations team&lt;/a&gt;, I'm keenly concerned with issues involving Python's deployment on Ubuntu and its upstream ancestor &lt;a href="http://www.debian.org/"&gt;Debian&lt;/a&gt;.  One of the distinction between Ubuntu/Debian and other Linux distributions is that Ubuntu/Debian often provides more than one Python version in a release.  For example, in &lt;a href="http://www.markshuttleworth.com/archives/478"&gt;Natty Narwhal&lt;/a&gt;, it's likely that Ubuntu will officially support Python &lt;a href="http://www.python.org/download/releases/2.6/"&gt;2.6&lt;/a&gt;, &lt;a href="http://www.python.org/download/releases/2.7/"&gt;2.7&lt;/a&gt;, &lt;a href="http://www.python.org/download/releases/3.1/"&gt;3.1&lt;/a&gt;, and &lt;a href="http://www.python.org/download/releases/3.2/"&gt;3.2&lt;/a&gt;.  The reason for this is that it does take some porting effort for applications to upgrade their version of Python, and this eases the transition for those applications.  But it's complicated by the fact that upstream Python doesn't really support multiple installed versions out of the box.  Recent work I've done on &lt;a href="http://www.python.org/dev/peps/pep-3147/"&gt;PEP 3147&lt;/a&gt; and &lt;a href="http://www.python.org/dev/peps/pep-3149/"&gt;PEP 3149&lt;/a&gt; improve this situation greatly, by allowing multiple versions of Python to more peacefully coexist.  As is typical, I try to push my changes needed for the Ubuntu platform as far upstream as possible, because that benefits the most users of the open source software.  In addition, a huge number of users get their Python interpreter from their operating system vendor (this is at least the case on all Linux variants as well as &lt;a href="http://www.apple.com/macosx/"&gt;Mac OS X&lt;/a&gt;), so work done to improve the Python experience on Ubuntu directly and positively impacts users on Debian and other Linux distributions, as well as the general Python community at large.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;GNU Mailman and Launchpad&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;/b&gt;I've been the lead developer for &lt;a href="http://www.list.org/"&gt;GNU Mailman&lt;/a&gt; since the late 90's, and I've been overwhelmed to see it become the predominant free software mailing list manager.  When I was working on the &lt;a href="http://launchpad.net/"&gt;Launchpad&lt;/a&gt; team at Canonical, my primary responsibility for the first few years was to integrate mailing lists with Launchpad, and of course Mailman was the obvious choice for underlying technology.  At first, Launchpad was closed source software, but the intent was always to release it as open source, and it was with much joy that we saw &lt;a href="http://blog.launchpad.net/general/launchpad-is-now-open-source"&gt;Launchpad released under a free software license&lt;/a&gt; in the summer of 2009. It was not a design goal of the original Mailman software to be easily integrated with external systems, so a good bit of the work I did on Launchpad at the time directly benefited upstream Mailman users by making it easier for ourselves, and others, to do this type of integration.  Now that I'm no longer on the Launchpad team, I work on &lt;a href="http://wiki.list.org/display/DEV/Mailman+3.0"&gt;Mailman 3&lt;/a&gt; exclusively in my spare time.  My experiences with that integration effort had a direct influence on the architecture of Mailman 3, and I have a goal of swapping the current Mailman 2.1 technology in Launchpad with Mailman 3.  All the relevant work to do this is fed back into the upstream project, to the benefit of the larger free software community, since many other people also want a better way to integrate mailing list functionality with their web sites.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My Mailman and Launchpad work also saw many spin-offs of helpful utilities and libraries which can be used by the much wider community of open source developers.  The &lt;a href="https://launchpad.net/lazr"&gt;lazr&lt;/a&gt; suite of Python libraries has applicability outside Launchpad and I use many of them in my extra-curricular projects, evangelizing them along the way.  Many GNU Mailman utilities have also been spun off into their own libraries, and these are now or will soon be available on the Debian and Ubuntu platforms, just as they are now available on the &lt;a href="http://pypi.python.org/pypi"&gt;Python Package Index&lt;/a&gt;.  The work I'm doing, along with my Canonical and Ubuntu colleagues to reduce the barriers to opportunistic participation in projects is key to this ecosystem.  We're making it much easier for others to find and participate in the projects that interest them, at whatever level they choose.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;UDD&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Along those lines, as part of my work on Ubuntu Platform Foundations, I've become quite enthusiastic about technology we're calling &lt;a href="https://wiki.ubuntu.com/DistributedDevelopment"&gt;Ubuntu Distributed Development&lt;/a&gt;.  When I moved to the Platform team, I knew next to nothing about the &lt;a href="https://wiki.ubuntu.com/PackagingGuide"&gt;art of packaging&lt;/a&gt;, which is how upstream projects are turned into installable and manageable chunks that people can put on their Ubuntu (and Debian) machines.  Packaging has a rich tradition, but it's pretty esoteric and to most people who don't package, it's a black art.  Even now that I know how to package software, I still think it's way too magical.  UDD is a set of tools and procedures that aim to bring packaging to the masses, by reducing the magic and exposing the important parts in much more familiar tools.  Every open source developer sooner or later (hopefully &lt;i&gt;much&lt;/i&gt; sooner!) learns how to use a &lt;a href="http://en.wikipedia.org/wiki/Revision_control"&gt;revision control system&lt;/a&gt;.  Such systems allow developers to manage their code in a principled and rigorous way, by keeping detailed records about the changes to their software over time.  Revision control systems are an absolutely fundamental and required tool in the open source developer's toolbox.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &lt;a href="http://bazaar.canonical.com/en/"&gt;Bazaar&lt;/a&gt; distributed revision control system was written by Canonical, but is now a community-driven free software project.  It's ease of use, superior quality, and high degree of flexibility and extensibility make it a very attractive choice for projects looking to use the next generation in revision control systems.  Bazaar also integrates very nicely with Launchpad.  UDD are a set of extensions to bring packaging to the Bazaar suite, so that the very tool that upstream software developers use dozens of times a day, are also the tools they will use to create packages for making their software available to the mass of Ubuntu users.  I've been using Bazaar for years now, and have written a few plugins and patches.  I'll soon be helping to lead an effort to improve the UDD workflows and more widely expose the benefits of UDD to more and more Ubuntu developers. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Platform&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;/b&gt;I love my work on Platform because it allows me to have a small hand in lots of different upstream free and open source projects.  After so many years of hacking on such projects of all different stripes, I'm fairly good at looking at and understanding good open source code, debugging and fixing problems, and interacting with the upstream communities to get those patches pushed higher up the stack.  Bug trackers, mailing lists, &lt;a href="http://en.wikipedia.org/wiki/IRC"&gt;IRC&lt;/a&gt;, and revision control systems are the core technologies needed for this work, and I'm comfortable interacting on all of them.  Part of our job as Platform developers is, in my opinion, to engage the upstream projects, so that the fixes and changes we need to make in order to provide the absolute best experience to Ubuntu users, are available even to those folks who don't get their software from Ubuntu.  This to me is the the true meaning of being a free and open source developer for a company whose mission is to make free and open source available to the mass of computer users.  Our aim is not just to make software that competes on price, or liberty, but also on quality and "sex appeal" - we want our users to flock to Ubuntu not just because it costs nothing, but because it's so compelling that you can't help but &lt;a href="http://shop.canonical.com/"&gt;love it&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-5130308646721307506?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/5130308646721307506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2010/09/what-we-do.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/5130308646721307506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/5130308646721307506'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2010/09/what-we-do.html' title='What We Do'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-2627057889852452770</id><published>2010-06-08T15:14:00.005-04:00</published><updated>2010-06-08T16:09:56.931-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>import this and The Zen of Python</title><content type='html'>&lt;a href="http://www.mechanicalcat.net/richard/log/Python"&gt;Richard Jones&lt;/a&gt; is working on a talk for &lt;a href="http://pycon-au.org/2010/about/"&gt;PyCon Australia&lt;/a&gt; and asked me about the history of the &lt;a href="http://www.python.org/dev/peps/pep-0020/"&gt;Zen of Python&lt;/a&gt;, Tim Peters' eternal words of wisdom, often quoted, on the essential truths of Python.  At first, I couldn't find a reference to the first publication of this list, but then I did a better search of my archives and found that it was originally sent to the &lt;a href="http://mail.python.org/mailman/listinfo/python-list"&gt;python-list&lt;/a&gt; mailing list on &lt;a href="http://mail.python.org/pipermail/python-list/1999-June/616160.html"&gt;June 4, 1999&lt;/a&gt;, under the subject &lt;i&gt;"The Python Way"&lt;/i&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Interestingly enough, because I couldn't find that first reference immediately, I went back into my archives and researched the "&lt;a href="http://svn.python.org/view/python/tags/r221/Lib/this.py?revision=25249&amp;amp;view=markup"&gt;this&lt;/a&gt;" module.  Did you know that if you type the following at a modern Python interpreter, you get the Zen of Python?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;% python&lt;/div&gt;&lt;div&gt;Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) &lt;/div&gt;&lt;div&gt;[GCC 4.4.3] on linux2&lt;/div&gt;&lt;div&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;/div&gt;&lt;div&gt;&gt;&gt;&gt; import this&lt;/div&gt;&lt;div&gt;The Zen of Python, by Tim Peters&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Beautiful is better than ugly.&lt;/div&gt;&lt;div&gt;Explicit is better than implicit.&lt;/div&gt;&lt;div&gt;Simple is better than complex.&lt;/div&gt;&lt;div&gt;Complex is better than complicated.&lt;/div&gt;&lt;div&gt;Flat is better than nested.&lt;/div&gt;&lt;div&gt;Sparse is better than dense.&lt;/div&gt;&lt;div&gt;Readability counts.&lt;/div&gt;&lt;div&gt;Special cases aren't special enough to break the rules.&lt;/div&gt;&lt;div&gt;Although practicality beats purity.&lt;/div&gt;&lt;div&gt;Errors should never pass silently.&lt;/div&gt;&lt;div&gt;Unless explicitly silenced.&lt;/div&gt;&lt;div&gt;In the face of ambiguity, refuse the temptation to guess.&lt;/div&gt;&lt;div&gt;There should be one-- and preferably only one --obvious way to do it.&lt;/div&gt;&lt;div&gt;Although that way may not be obvious at first unless you're Dutch.&lt;/div&gt;&lt;div&gt;Now is better than never.&lt;/div&gt;&lt;div&gt;Although never is often better than *right* now.&lt;/div&gt;&lt;div&gt;If the implementation is hard to explain, it's a bad idea.&lt;/div&gt;&lt;div&gt;If the implementation is easy to explain, it may be a good idea.&lt;/div&gt;&lt;div&gt;Namespaces are one honking great idea -- let's do more of those!&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The story behind &lt;i&gt;"import this"&lt;/i&gt; is kind of funny, and occurred totally behind the scenes, so I thought it might be interesting to relate how it happened.  Maybe something to add to &lt;a href="http://python-history.blogspot.com/"&gt;Guido's History of Python blog&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, back in fall 2001, &lt;a href="http://en.wikipedia.org/wiki/Foretec_Seminars"&gt;Foretec&lt;/a&gt; was organizing the &lt;a href="http://www.python.org/workshops/2002-02/spam1folks.jpg"&gt;International Python Conference #10&lt;/a&gt; (IPC 10, precursor to &lt;a href="http://www.pycon.org/"&gt;Pycon&lt;/a&gt;).  Foretec was a conference organizing company owned by &lt;a href="http://www.cnri.reston.va.us/"&gt;CNRI&lt;/a&gt;, which earlier had employed Guido, Fred, Jeremy and myself, and which by 2000 we had left to form &lt;a href="http://www.python.org/pythonlabs/"&gt;Pythonlabs&lt;/a&gt; at various friendly (and &lt;a href="http://en.wikipedia.org/wiki/History_of_Python#BeOpen"&gt;occasionally disfunctional&lt;/a&gt;) corporate homes.  By September 13, 2001 (yes, how weird!) we were working for our friends at &lt;a href="http://www.zope.com/"&gt;Zope Corporation&lt;/a&gt; (perhaps not yet rebranded from &lt;a href="http://en.wikipedia.org/wiki/Zope"&gt;Digitial Creations&lt;/a&gt;), but Foretec was still organizing the IPCs.  They wanted to have a slogan for the conference, which could be printed on a t-shirt, and wanted to gather submissions from the Python community.  Pythonlabs agreed to judge the entries and select a winner.  However, I think Guido's wife was due any day and he didn't have much time or energy to go through the entries.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We got something like 500 entries, almost all of them terrible.  Tim's exact words were &lt;i&gt;"Jeez Louise, I can't look at these for more than 5 minutes w/o my brain turning to mush"&lt;/i&gt; and yet he still managed to do an initial cut down to something like 130 entries.  While we had agreed to choose a winner, we procrastinated until the last minute and by then it was obvious that Tim and I were the only ones crazy enough to still care. Tim suggested that we trade the list back and forth between the two of us, each cutting the list in half until there was just one left.  Tim is much better at math than me, and I had forgotten &lt;wink&gt; about Python's &lt;a href="http://docs.python.org/reference/expressions.html#binary-arithmetic-operations"&gt;integer division&lt;/a&gt; so I was left to choose from between the last two entries: &lt;i&gt;"Bite off all you like - Chewing is optional"&lt;/i&gt; (yes, I said most were terrible ;), and &lt;i&gt;"import this"&lt;/i&gt;.  At the last minute, Tim resurrected a fun one that we had both noticed approvingly early on: &lt;i&gt;"Let's we study about Python program"&lt;/i&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While that last one had lots of appeal,  I liked the irreverent, almost sneering tone of &lt;i&gt;"import this"&lt;/i&gt;.  I saw the potential for a great, &lt;a href="http://www.studio8.net/wp-content/uploads/2009/06/michael-jackson-crotch.jpg"&gt;Michael Jackson-esque&lt;/a&gt; t-shirt.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As soon as we'd chosen &lt;i&gt;"import this"&lt;/i&gt; I realized we just had to implement it.  Python 2.2 was about to be released and I proposed that we turn off checkin notifications and sneak in a &lt;i&gt;"this.py"&lt;/i&gt; module which when imported just printed the Zen of Python.  Tim or Guido suggested further that we &lt;a href="http://en.wikipedia.org/wiki/Rot13"&gt;rot13&lt;/a&gt; the contents of the module just for a little extra obfuscation, and we told no one outside our little group. According to my intergoogles spelunking, as soon as IPC 10 was concluded, we commemorated the event by committing &lt;i&gt;this.py&lt;/i&gt; to what was to become Python 2.2.1, thus adding to the &lt;a href="http://docs.python.org/library/functions.html#bool"&gt;affront&lt;/a&gt; of new features in point releases. IIRC, it took a long time for someone to find our little easter egg.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That was all back in the day when the Python community had a &lt;a href="http://ivory.idyll.org/blog/feb-10/whats-with-the-goat.html"&gt;sense of humor&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-2627057889852452770?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/2627057889852452770/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2010/06/import-this-and-zen-of-python.html#comment-form' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2627057889852452770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2627057889852452770'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2010/06/import-this-and-zen-of-python.html' title='import this and The Zen of Python'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-4896668785904968561</id><published>2010-06-07T15:03:00.006-04:00</published><updated>2010-06-07T16:14:36.460-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='canonical'/><title type='text'>Experimental Virtual Machines</title><content type='html'>I'm doing &lt;a href="https://blueprints.edge.launchpad.net/ubuntu/+spec/foundations-m-python-versions"&gt;some work&lt;/a&gt; these days on trying to get &lt;a href="http://www.python.org/download/releases/2.7/"&gt;Python 2.7&lt;/a&gt; as the default Python in the next version of Ubuntu, &lt;a href="https://wiki.ubuntu.com/MaverickMeerkat"&gt;Maverick Meerkat (10.10)&lt;/a&gt;.  This work will occasionally require me to break my machine by installing experimental packages.  That's a good and useful thing because I want to test various potentially disruptive changes before I think about unleashing them on the world.  This is where &lt;a href="http://en.wikipedia.org/wiki/Virtual_machine"&gt;virtual machines&lt;/a&gt; really shine!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To be efficient, I need a really fast turnaround from known good state, to broken state, back to known good state.  In the past, I've used &lt;a href="http://www.vmware.com/products/fusion/"&gt;VMware Fusion&lt;/a&gt; on my Mac to create a VM, then take a live snapshot of the disk before making my changes.  It was really easy then to revert to the last known good snapshot, try something else and iterate.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But lately Fusion has sprouted a nasty habit of &lt;a href="http://communities.vmware.com/thread/269292?tstart=0"&gt;freezing the host OS&lt;/a&gt;, such that a hard reboot is necessary.  This will inevitably cause havoc on the host, by losing settings, trashing mail, corrupting VMs, etc.  VMware can't reproduce the problem but it happens every time to me, and it hurts, so I'm not doing that any more :).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Back to my &lt;a href="http://www.ubuntu.com/"&gt;Lucid&lt;/a&gt; host and &lt;a href="http://www.libvirt.org/"&gt;libvirt/kvm&lt;/a&gt; and the sanctuary of &lt;a href="http://en.wikipedia.org/wiki/FLOSS"&gt;FLOSS&lt;/a&gt;.  It's really easy to create new VMs, and there are several ways of doing it, from &lt;a href="http://virt-manager.et.redhat.com/"&gt;virt-manager&lt;/a&gt; to &lt;a href="https://launchpad.net/vmbuilder"&gt;vmbuilder&lt;/a&gt; to straight up &lt;a href="http://ubuntuforums.org/showthread.php?t=966739"&gt;kvm&lt;/a&gt; (thanks Colin for some recipes). The problem is that none of these are exactly &lt;i&gt;fast&lt;/i&gt; to go from bare metal to working Maverick VM with all the known good extras I need (like openssh-server and bzr, plus my comfortable development environment).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I didn't find a really good fit for vmbuilder or the kvm commands, and I'm not smart enough to use the libvirt command line tools, but I think I've figured out a hack using virt-manager that will work well enough.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1. Create a disk for the baseline VM (named '&lt;b&gt;scars&lt;/b&gt;' in my case :) manually&lt;/div&gt;&lt;div&gt;   % qemu-img create -f qcow2 scars.qcow2 20G&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2. Create the baseline VM using virt-manager&lt;/div&gt;&lt;div&gt;   * I use dhcp internally, so I give this thing a mac address, assign it 1GB&lt;/div&gt;&lt;div&gt;     of RAM and 1 processor.&lt;/div&gt;&lt;div&gt;   * For storage, I tell it to use the &lt;b&gt;scars.qcow2&lt;/b&gt; file I created above&lt;/div&gt;&lt;div&gt;   * Boot from the maverick ISO of your choice, install everything you want,&lt;/div&gt;&lt;div&gt;     and get your development environment in place&lt;/div&gt;&lt;div&gt;   * Shut this machine down&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3. Clone your baseline VM&lt;/div&gt;&lt;div&gt;   * In the virt-manager Manager window, right click on your baseline VM and&lt;/div&gt;&lt;div&gt;     select Clone&lt;/div&gt;&lt;div&gt;   * You will not be given an opportunity to select a disk or a mac address,&lt;/div&gt;&lt;div&gt;     so for now just go with the defaults.&lt;/div&gt;&lt;div&gt;   * Do not start your clone&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4. Create an 'overlay' disk that is a backed by your baseline disk.&lt;/div&gt;&lt;div&gt;   % qemu-img create -f qcow2 -b scars.qcow2 scars.ovl&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;5. Edit your clone&lt;/div&gt;&lt;div&gt;   * Delete the disk given to your clone by default&lt;/div&gt;&lt;div&gt;   * Create a new virtio storage that points to scars.ovl&lt;/div&gt;&lt;div&gt;   * Delete the nic given to your clone by default&lt;/div&gt;&lt;div&gt;   * Create a new virtio network device with the mac address of your&lt;/div&gt;&lt;div&gt;     baseline.  You'll get a warning about a mac address collision, but this&lt;/div&gt;&lt;div&gt;     can be ignored (see below).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;6. Boot your clone&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At this point you'll have a baseline which is your known good system, and a clone/overlay which you can break to your heart's content.  When it's time to iterate back to a known good state, shut down your clone, delete the overlay disk, and create a new one from the baseline qcow2 disk.  This is pretty fast, and your turn around time is not much more than the time it takes to shutdown one machine and boot another.  It actually feels a lot faster by the wall clock than Fusion ever was to snapshot and restore.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One downside is that you cannot run both VMs at the same time.  I think mostly this is because of the MAC address collision, but also because creating the overlay requires that both machines be powered off.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The other downside seems to be that if you want to update your known good baseline, say by installing more packages or apt-get update/upgrade, you will have to recreate your overlay disk for your next experiment.  Changes to the underlying disk do not seem to propagate to the overlay automatically. Maybe that's intentional; I can't find much documentation on it.  (Note too that the &lt;a href="http://linux.die.net/man/1/qemu-img"&gt;manpage for qemu-img&lt;/a&gt; does not describe the -b option.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I guess the last downside is that I spent way too much time trying to figure all this out.  The Googles were not a lot of help but did give me the qemu-img clue.  But at least now you don't have to! :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-4896668785904968561?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/4896668785904968561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2010/06/experimental-virtual-machines.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4896668785904968561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4896668785904968561'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2010/06/experimental-virtual-machines.html' title='Experimental Virtual Machines'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-6499578266916049920</id><published>2010-05-26T17:46:00.004-04:00</published><updated>2010-05-26T18:02:13.399-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mailman'/><title type='text'>We have a winner!</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_hGUIklm9gQQ/S_2Yu16ZWSI/AAAAAAAACSs/mH4-zFnkbd0/s1600/logo2010.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 256px;" src="http://4.bp.blogspot.com/_hGUIklm9gQQ/S_2Yu16ZWSI/AAAAAAAACSs/mH4-zFnkbd0/s320/logo2010.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5475700652465805602" /&gt;&lt;/a&gt;&lt;br /&gt;In the early part of 2010, we started a contest for a new &lt;a href="http://www.list.org/"&gt;GNU Mailman&lt;/a&gt; logo.  Our &lt;a href="http://www.list.org/otherstuff.html"&gt;old logo&lt;/a&gt;, donated by the Dragon de Monsyne had served us well for many years, but it felt like we needed a refresh.  Besides, we wanted a nice scalable graphic that we could use in many more situations.  So we &lt;a href="http://wiki.list.org/display/DEV/LogoSubmissions"&gt;solicited entries&lt;/a&gt; and then &lt;a href="http://www.cs.cornell.edu/w8/~andru/cgi-perl/civs/results.pl?id=E_17290602feb"&gt;conducted a poll&lt;/a&gt;.  Today I am very pleased to announce the winner!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By better than 2-to-1, this submission by &lt;a href="http://andrijaarsic.webs.com/"&gt;Andrija Arsic&lt;/a&gt; was voted as best logo by the Mailman community. Congratulations Andrija!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While we have yet to re-brand the website and software to include the new logo, we'll start using it immediately.  If you'd like to help with any redesign, please contact us at &lt;a href="mailto:mailman-developers@python.org"&gt;mailman-developers@python.org&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A little bit about Andrija: originally from Trstenik, Serbia and now studying IT technology in Belgrade, Andrija is a self-employed, part-time graphic designer, specialising in the fields of corporate identity (logo) design, web design, print design and branding with the majority of his time spent designing and implementing marketing promotions for businesses such as logos, websites, letterhead, business cards, packaging and more.  I'm glad that he also contributes to free software, as I think his winning logo is spectacular.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My thanks and appreciation to all the artists who contributed logos to the contest.  All the designs are very nice, and in their own way, capture the spirit of GNU Mailman.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-6499578266916049920?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/6499578266916049920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2010/05/we-have-winner.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6499578266916049920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6499578266916049920'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2010/05/we-have-winner.html' title='We have a winner!'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_hGUIklm9gQQ/S_2Yu16ZWSI/AAAAAAAACSs/mH4-zFnkbd0/s72-c/logo2010.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-3376719211775330670</id><published>2010-05-24T21:26:00.009-04:00</published><updated>2010-06-10T17:14:18.870-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='packaging'/><category scheme='http://www.blogger.com/atom/ns#' term='debian'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='canonical'/><title type='text'>From Python package to Ubuntu package in 3-ish easy steps</title><content type='html'>My friend Tim is working on a very cool &lt;a href="https://launchpad.net/wikkid"&gt;Bazaar-backed wiki project&lt;/a&gt; and he asked me to package it up for Ubuntu.  I'm getting &lt;a href="https://edge.launchpad.net/~barry/+archive/python/+packages"&gt;pretty good&lt;/a&gt; at packaging Python projects, but I always like the practice because each time it gets a little smoother.  This one I managed to package in about 10 minutes so I thought I'd outline the very easy process.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First of all, you want to have a good setup.py, and if you like to &lt;a href="http://en.wikipedia.org/wiki/Cargo_cult_programming"&gt;cargo cult&lt;/a&gt;, you can start with &lt;a href="http://bazaar.launchpad.net/~barry/flufl.enum/trunk/annotate/head:/setup.py"&gt;this one&lt;/a&gt;.  I highly recommend using &lt;a href="http://packages.python.org/distribute/"&gt;Distribute&lt;/a&gt; instead of &lt;a href="http://pypi.python.org/pypi/setuptools"&gt;setuptools&lt;/a&gt;, and in fact the former is what Ubuntu gives you by default.  I really like adding the &lt;b&gt;distribute_setup.py&lt;/b&gt; which gives you nice features like being able to do &lt;b&gt;python setup.py test&lt;/b&gt; and many other things.  See lines 18 and 19 in the above referenced &lt;b&gt;setup.py &lt;/b&gt;file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The next thing you'll want is Andrew Straw's fine &lt;a href="http://github.com/astraw/stdeb"&gt;stdeb&lt;/a&gt; package, which you can get on Ubuntu with &lt;b&gt;sudo apt-get install python-stdeb&lt;/b&gt;.  This package is going to bootstrap your &lt;b&gt;debian/&lt;/b&gt; directory from your &lt;b&gt;setup.py&lt;/b&gt; file.  It's not perfectly suited to the task (yet, Andrew assures me :), but we can make it work!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;These days, I host all of my packages in &lt;a href="http://bazaar.canonical.com/en/"&gt;Bazaar&lt;/a&gt; on &lt;a href="http://launchpad.net/"&gt;Launchpad&lt;/a&gt;, which is going to make some of the following steps really easy.  If you use a different hosting site or a different version control system, you will have to build your Ubuntu package using &lt;a href="https://help.ubuntu.com/6.10/ubuntu/packagingguide/C/index.html"&gt;more traditional means&lt;/a&gt;.  That's okay, once you have your &lt;b&gt;debian/&lt;/b&gt; directory, it'll be fairly easy (but not as easy as described here &lt;wink&gt;).  If you do use Bazaar, you'll just want to make sure you have the &lt;a href="https://wiki.ubuntu.com/DistributedDevelopment/Documentation"&gt;bzr-builddeb&lt;/a&gt;.  Just do &lt;b&gt;sudo apt-get install bzr-builddeb&lt;/b&gt; on Ubuntu and you should get everything you need.&lt;/wink&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Okay, so now you have the requisite packages, and a &lt;b&gt;setup.py&lt;/b&gt;, let's build us a deb and upload it to our &lt;a href="https://help.launchpad.net/Packaging/PPA"&gt;personal package archive&lt;/a&gt; so everyone on Debian and Ubuntu can easily try it out.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, let's create the &lt;b&gt;debian&lt;/b&gt; directory.  Here's the first little icky bit:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;% python setup.py --command-packages=stdeb.command sdist_dsc&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Notice that this leaves us with a &lt;b&gt;deb_dist/&lt;/b&gt; directory, not the &lt;b&gt;debian/&lt;/b&gt; directory we want.  The latter is in there, just buried a bit.  Let's dig it out:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;% mv deb_dist/wikkid-0.1/debian .&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;% rm -rf deb_dist&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;% bzr add debian&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;% bzr commit -m'Debianize'&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Note that "wikkid-0.1" will be replaced by the name of your package.  In order to build the .deb package, you need an "orig.tar.gz" file.  Packaging sort of assumes that you've got an original upstream tarball somewhere and you're just adding the necessary Debian goo to package the thing.  In this case, we don't have an upstream tarball, although we could easily create one, and upload it to the &lt;a href="http://pypi.python.org/pypi"&gt;Cheeseshop&lt;/a&gt; or Launchpad or wherever.  However, that just slows us down so let's skip that for now!  (Aside: if you do have an upstream tarball somewhere, you'll want to add a &lt;b&gt;debian/watch&lt;/b&gt; which points to it; that'll eliminate the need to do the next step, by downloading the tarball instead).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let's create the tarball right now and copy it to where the following step will expect it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;% python setup.py sdist&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;% mv dist/Wikkid-0.1.tar.gz ../wikkid_0.1.orig.tar.gz&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Here's the second icky bit.  Building a Debian source package imposes a very specific naming convention on the tarball. Wikkid's &lt;b&gt;setup.py&lt;/b&gt; happens to build a tarball with an incompatible name, while the &lt;b&gt;sdist&lt;/b&gt; command leaves it in a place where the next step can't find it.  The rename just gets everything into the proper place.  YMMV.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now we can build the Debian source package.  It's the source package that we'll upload to our Launchpad PPA.  Launchpad will then automatically (if we've done everything right) build the binary package from the uploaded source package, from which Ubuntu and Debian users can easily install.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oops!  Before we do this, please edit your &lt;b&gt;debian/changelog&lt;/b&gt; file and change &lt;i&gt;unstable&lt;/i&gt; to &lt;i&gt;lucid&lt;/i&gt;.  You should also change the version number by adding a &lt;i&gt;~ppa1&lt;/i&gt; to the end of it.  Yeah, more ickiness.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Alright&lt;i&gt; now&lt;/i&gt; we're ready to build our source package:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;% bzr bd -S&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Now let's upload it (assuming you've enabled a PPA):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;% cd ..&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;% dput ppa:barry/python wikkid_0.1-1~ppa1_source.changes&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;That's it!  If you've done everything successfully, you'll have the package in your PPA in 5 minutes or so. Then anybody who's added your PPA can just &lt;b&gt;apt-get install wikkid&lt;/b&gt; (or whatever your package is called). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I do hope to work with the appropriate developers to make some of the ickiness go away.  Please do contact me if you want to help!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Addendum (2010-06-10)&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Let's say you publish your tarball on the &lt;a href="http://pypi.python.org/pypi"&gt;Cheeseshop&lt;/a&gt; or &lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt;, and you don't want to have to build a different tarball locally in order to package it.  Here's what I think works:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Create a &lt;a href="http://wiki.debian.org/debian/watch/"&gt;debian/watch&lt;/a&gt; file that points to the download location you publish to.  If your package is not yet available in Debian or Ubuntu, then use this command to build your source package:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;bzr bd -S -- -sa&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;The bit at the end tells the Debian packaging primitives to include your tarball when your source package is uploaded.  The &lt;b&gt;debian/watch&lt;/b&gt; file is used to download your published tarball and automatically renamed to the required &lt;b&gt;.orig.tar.gz&lt;/b&gt; name.  When you &lt;b&gt;dput&lt;/b&gt; your package, your tarball will be uploaded too, and everything should build properly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Oh, and don't forget to look carefully at the &lt;a href="http://lintian.debian.org/"&gt;lintian&lt;/a&gt; output.  Try to make this as clean as possible.  The &lt;a href="http://www.debian.org/doc/maint-guide/"&gt;Debian&lt;/a&gt; and &lt;a href="https://wiki.ubuntu.com/PackagingGuide"&gt;Ubuntu&lt;/a&gt; packaging guides can help here.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Addendum 2 (2010-06-10)&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Andrew Straw has added a &lt;i&gt;debianize&lt;/i&gt; command to his &lt;a href="http://github.com/astraw/stdeb"&gt;stdeb&lt;/a&gt; package, which makes things &lt;i&gt;much&lt;/i&gt; nicer.  With this you can create the &lt;b&gt;debian&lt;/b&gt;/ directory right next to your setup.py.  AFAIK, this version of stdeb isn't released yet, so you need to install his git head in a virtualenv, and it has a few minor buglets, but it does seem like the best-of-breed solution.  I'll post another article with a more detailed follow up later. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-3376719211775330670?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/3376719211775330670/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2010/05/from-python-package-to-ubuntu-package.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/3376719211775330670'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/3376719211775330670'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2010/05/from-python-package-to-ubuntu-package.html' title='From Python package to Ubuntu package in 3-ish easy steps'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-3785743837071070350</id><published>2010-05-23T17:56:00.009-04:00</published><updated>2010-05-24T11:54:38.947-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><category scheme='http://www.blogger.com/atom/ns#' term='canonical'/><category scheme='http://www.blogger.com/atom/ns#' term='servers'/><title type='text'>Gentoo No More</title><content type='html'>Today I finally swapped my last &lt;a href="http://www.gentoo.org/"&gt;Gentoo&lt;/a&gt; server for an &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu 10.04 LTS&lt;/a&gt; server.  Gentoo has served me well over these many years, but with my emerge updates growing to several pages (meaning, I was &lt;i&gt;waaaay&lt;/i&gt; behind on updates with almost no hope of catching up) it was long past time to switch.  I'd moved my internal server over to Ubuntu during the Karmic cycle, but that was a much easier switch.  This one was tougher because I had several interdependent externally facing services: web, mail, sftp, and &lt;a href="http://www.list.org/"&gt;Mailman&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The real trick to making this go smoothly was to set up a &lt;a href="https://help.ubuntu.com/community/KVM"&gt;virtual machine&lt;/a&gt; in which to install, configure and progressively deploy the new services.  My primary desktop machine is a honkin' big i7-920 quad-core Dell with 12GB of RAM, so it's perfectly suited for running lots of VMs.  In fact, I have several Ubuntu, &lt;a href="http://www.debian.org/"&gt;Debian&lt;/a&gt; and even Windows VMs that I use during my normal development of Ubuntu and &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;.  However, once I had the new server ready to go, I wanted to be able to quickly swap it into the real hardware.  So I purchased a 160GB IDE drive (since the h/w it was going into was too old to support SATA, but still perfectly good for a simple Linux server!) and a USB drive enclosure.  I dropped the new disk into the enclosure, mounted it on the Ubuntu desktop and created a virtual machine using the USB drive as its virtio storage.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It was then a pretty simple matter of installing Ubuntu 10.04 on this USB drive-backed VM, giving the VM an IP address on my local network, and installing all the services I wanted.  I could even register the VM with &lt;a href="http://www.canonical.com/projects/landscape"&gt;Landscape&lt;/a&gt; to easily keep it up-to-date as I took my sweet time doing the conversion.  There were a few tricking things to keep in mind:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;I use a &lt;a href="http://en.wikipedia.org/wiki/Port_forwarding"&gt;port forwarding&lt;/a&gt; border router to forward packets from my static external IP address to the appropriate server on my internal network.  As I prepared to move each service, I first shut the service off on the old server, twiddled the port forwarding to point to a bogus IP, then tested the new service internally before pointing the real port forward to the new service.  This way for example, I had reasonably good confidence that my SMTP server was configured properly before loosing the fire hose of the intarwebs on it.&lt;/li&gt;&lt;li&gt;I host several domains on my server so of course my &lt;a href="http://httpd.apache.org/"&gt;Apache&lt;/a&gt; uses &lt;a href="http://httpd.apache.org/docs/2.2/mod/core.html#namevirtualhost"&gt;NameVirtualHost&lt;/a&gt;s.  The big downside here is that the physical IP address is used, so I had to edit all the configs over to the temporary IP address of the VM, then back again to the original IP of the server, once the switch was completed.&lt;/li&gt;&lt;li&gt;My old server used a fairly straightforward &lt;a href="https://help.ubuntu.com/community/IptablesHowTo"&gt;iptables&lt;/a&gt; configuration, but in Ubuntu, &lt;a href="https://help.ubuntu.com/community/UFW"&gt;UFW&lt;/a&gt; seems to be the norm.  Again, I use IP addresses in the configuration, so these had to be changed twice during the migration.&lt;/li&gt;&lt;li&gt;/etc/hosts and /etc/hostname both had to be tweaked after the move since while living in a VM, the host was called something different than when in its final destination.  Landscape also had to be reconfigured (see &lt;b&gt;landscape-config(8)&lt;/b&gt;).&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;You get the picture.  All in all, just tedious if not very difficult.  One oddness was that when the machine was a Gentoo box, the ethernet port was &lt;i&gt;eth0&lt;/i&gt; but after the conversion to Ubuntu, it became &lt;i&gt;eth1&lt;/i&gt;.  Once I figured that out, it was easy to fix networking.  There were a few other little things like updates to my internal DNS, pointing my backup server to the new locations of the web and Mailman data on the new server (Ubuntu is more &lt;a href="http://www.pathname.com/fhs/"&gt;FHS&lt;/a&gt;-compliant than my ancient Gentoo layout), and I'm sure a few other little things I forgot to take notes on.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Still, the big lesson here was that by bouncing the services to a USB-drive backed VM, I was able to fairly easy drop the new disk into the old server for a quick and seamless migration to an entirely new operating system.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-3785743837071070350?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/3785743837071070350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2010/05/gentoo-no-more.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/3785743837071070350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/3785743837071070350'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2010/05/gentoo-no-more.html' title='Gentoo No More'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-2612524786814658502</id><published>2010-01-25T12:18:00.004-05:00</published><updated>2010-06-07T15:03:41.220-04:00</updated><title type='text'></title><content type='html'>I read this somewhere:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;When we opened the door to this wonderful place, we were stunned!  Literally.  Uncle Fledge had to be led in by the hand and seated in front of the massive TV.  He'd never seen anything so big.  Grandma loved the "hot" tub and even with her massive girth, it came up to her chin so she could relax.  The little family of hamsters or weasels kept wanting to join her, so that's what the broomstick is for (in case you're wondering).&lt;br /&gt;&lt;br /&gt;Uncle Fledge is a &lt;&gt; &lt;&gt; skier but he loved the game room so much, he played for 36 hours straight until he got pokey finger.  The Aunt Weebus dragged him out to the slopes.  Good thing too because we were getting tired of White Lion on the jukebox.  Uncle Fledge and Jimmie's favorite band, how did you know?&lt;br /&gt;&lt;br /&gt;Martha was kind of obsessed with the telescope but billy brought his laptop and then it was family YouTube time.  The view is spectacular though.  Grandma loved watching the bears iceskate on the lake.  Never seen that before she said.  The twins wanted me to add that the bunk beds are fun, and the triplets loved having their own rooms.  Mom and Dad retired to the jacuzzi for 8 hours, and little Moby had to keep refreshing their champagne.  We loved the Bears Den and will definitely be back.&lt;br /&gt;&lt;br /&gt;- The Kimmels, the Conans, the Boxxees, the Fledge Jrs &amp;amp; Srs, Phil, Sarah, Monk, Billy, Jimmy, Sandy Candy &amp;amp; Mandy, Uncle F.  Aunt W, Grandma, Tina, Mallory, Frank, Stu, Mack T, Mack F, Tug, Willy and "Beans".&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-2612524786814658502?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/2612524786814658502/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2010/01/i-read-this-somewhere-when-we-opened.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2612524786814658502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2612524786814658502'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2010/01/i-read-this-somewhere-when-we-opened.html' title=''/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-550315881637735645</id><published>2009-12-09T18:47:00.005-05:00</published><updated>2009-12-11T18:02:30.795-05:00</updated><title type='text'>MBP</title><content type='html'>So I got my new &lt;a href="http://www.apple.com/macbookpro/"&gt;Mac Book Pro&lt;/a&gt;, named it "&lt;a href="http://en.wikipedia.org/wiki/Hemispheres_%28Rush_album%29"&gt;hemispheres&lt;/a&gt;" as mentioned in my previous post. I'm very happy with this machine, and here are my early impressions.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://en.wikipedia.org/wiki/Solid-state_drive"&gt;SSD&lt;/a&gt; is pure win. It's quiet, cool, and fast. The biggest immediate downside of course is the cost, but as a refurb, this option was made much more affordable.  It'll be interesting to see how it performs over time as there are known issues with the long-term use of the technology.&lt;br /&gt;&lt;br /&gt;My two biggest concerns were the screen and the keyboard. I absolutely love my previous generation MBP keyboard, as it's about the only laptop I can comfortably use for 8 hours a day. The unibody MBPs have a completely different keyboard, with a different feel, but I hadn't used one for a long hacking session so I was unsure how it would feel after a few hours under my hands. I'm very relieved to say that while it has a different feel, it's still incredibly comfortable to use. Apple seems to know what they're doing.&lt;br /&gt;&lt;br /&gt;I have had a few problems hitting the right keys, most notably not quite getting the shift-2 chord right to produce an @ sign. The reach is a little bit longer it seems so I often end up just typing a "2", somehow missing the shift combination. I have a few other common typing errors, but for the most part I'm getting used to it.&lt;br /&gt;&lt;br /&gt;The other big uncertainty was the antiglare screen. I absolutely love the matte screen on my old MBP and hate &lt;span style="font-weight: bold;"&gt;hate&lt;/span&gt; &lt;span style="font-style: italic;"&gt;HATE&lt;/span&gt; the glossy screens that seem to come on most laptops today. Honestly, if the MBP didn't offer a matte screen as an option, I probably wouldn't have bought it. Of course, now it's a $50 upcharge, but I think it's worth it. The antiglare screen has a different color temperature than the old MBP matte screen. It seems colder and I don't think there's any way to adjust it (well, maybe color calibration but my first and only attempt at that didn't do much). The screen also seems a bit more "washed out" than my old MBP, but it's also brighter because of the backlit-LED. I'm not fond of the dimming in the dark and brightening in the light (it seems backward to me), so I'm kind of riding the F1 and F2 keys, but after several days of use, I am getting used to it.&lt;br /&gt;&lt;br /&gt;The machine does seem to have a very long battery life.  For hacking in front of &lt;a href="http://www.redskins.com/gen/index.jsp"&gt;Sunday football&lt;/a&gt;, I'd estimate it's about a 5 hour run, and the battery indicator seems pretty accurate after its calibration.  That's with the high performance graphics card, btw (there are two in this machine).&lt;br /&gt;&lt;br /&gt;I'm getting used to the different arrangement of ports and media slots, and the sleep light seems much less obnoxious.  I do wish the machine had come with an &lt;a href="http://en.wikipedia.org/wiki/Serial_ATA#External_SATA"&gt;eSATA&lt;/a&gt; port, as I think &lt;a href="http://en.wikipedia.org/wiki/FireWire"&gt;FireWire&lt;/a&gt; at least for storage is becoming increasingly uncommon and/or expensive.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.apple.com/macosx/"&gt;Snow Leopard&lt;/a&gt; (OS X 10.6) seems pretty cool, although honestly I don't notice much of a difference. There are still some kinks though, as my cursor freeze up occasionally.  I'm sure Apple will fix this in subsequent patches.  They did seem to fix a few Mail.app bugs I'd reported, but sadly not everything.  And they broke GPGmail so currently I have no encryption in Mail.app (a  release for Mail.app 4 is reportedly forthcoming).&lt;br /&gt;&lt;br /&gt;I wanted this machine to run &lt;a href="http://www.ubuntu.com/products/whatisubuntu/910features"&gt;Ubuntu&lt;/a&gt; as well, so that I'd only have to take one laptop with me to conferences and such.  I struggled with the best way to install Ubuntu: should I dual boot, use a virtual machine, or both?  A colleague of mine had done the "both" route with &lt;a href="http://www.vmware.com/products/fusion/"&gt;VMware&lt;/a&gt; and bootcamp and I had enough disk space to consider this, but decided to see how the VMware-only approach worked first.  The main problems are that Xorg configuration and MAC-address (and thus DHCP assigned IP addresses) would be problematic in a "both" environment.&lt;br /&gt;&lt;br /&gt;Fortunately, Karmic Koala in a VMware 3 machine works absolutely great.  It's very fast, looks and feels great, and doesn't tax the machine much that I can tell.  The biggest problems are the lack of OpenGL/compiz for windowing, and a weird problem where Gnome-Do's summon chord of control-command-space has to be hit twice in order for it to work.  I don't know if this is a VMware thing (since it works fine on my native Karmic desktop) or because I need to install vmware-tools.  My last experience with vmware-tools was far from satisfying so I've mostly ignored it.  I may try it to see if it clears up this problem though.&lt;br /&gt;&lt;br /&gt;I should mention that I have an older version of Parallels, but ditched it because of some things that bug me about it, such as screen resolution during boot up, and more.  Parallels 5 reportedly supports OpenGL/compiz for guests, so I grabbed a try-and-buy and went through the installation of Karmic in it, but was never able to enable desktop effects, so ditched it again.&lt;br /&gt;&lt;br /&gt;In any event, I'm not going to try to set up a dual-boot until and unless I have to.&lt;br /&gt;&lt;br /&gt;I did have one big gotcha as I was getting the new MBP set up.  Apple has a very nice migration assistant that helps you move your stuff (including applications, settings, home directory, etc.) from your old machine to your new machine.  The first time I tried it was massive fail.  First, I did a wireless-to-wireless transfer and it never warned me that it was going to take 12+ hours to migrate, and once it started it was impossible to interrupt.  Second, 12 hours later when I tried to log into the new machine, I was completely prevented from doing so.  I actually could log in, but OS X was throwing up a cryptic error saying it couldn't open my FileVault.  My home drive on my old MBP is encrypted and of course I wanted the same on my new machine.  I figured since Migration Assistant happy proceeded it would Do The Right Thing.  Yeah, not so much.&lt;br /&gt;&lt;br /&gt;After being on the phone with Apple support for a few hours, I was finally told that this was not a supported migration option.  Thank you Migration Assistant for the warning.  Not.  The solution was to re-install the OS on the new machine (since I could in no way log in now), turn FileVault off on the old machine, effect the transfer, and then re-enable FV on both machines.  The problem with this is that you need enough disk space on the old machine to turn FV off, and this I did not have.  It took quite some effort to free up the 31GB of space on my old machine (1/3 of the total hard drive size), but by temporarily moving stuff off to a NAS, I finally managed it.&lt;br /&gt;&lt;br /&gt;This time, I did an ethernet-to-ethernet migration and it took way less than 12 hours.  Of course it was transferring a lot less data, but still, it only took an hour or so maybe.  I guess that's the advantage of gigabit ethernet over 802.11G :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-550315881637735645?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/550315881637735645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/12/mbp.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/550315881637735645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/550315881637735645'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/12/mbp.html' title='MBP'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-6108667319490043208</id><published>2009-12-04T13:06:00.004-05:00</published><updated>2009-12-04T13:47:12.700-05:00</updated><title type='text'>Hemispheres</title><content type='html'>The relationship between the bass player and the drummer is one of the most profound and important relationships in rock music.  I've been incredibly fortunate in my musical life to have played with a number of drummers with whom I've had a deep and usually immediate musical connection.  Almost all are still close personal friends.  For me, playing with a good drummer is probably one of the most important reasons to stick with a band long term (it's a necessary but not sufficient condition).&lt;br /&gt;&lt;br /&gt;I've been with the &lt;a href="http://www.uliners.com"&gt;U-Liners&lt;/a&gt; now for quite a few years and I've enjoyed every minute playing with our drummer &lt;a href="http://www.larryfergusondrums.com/Home.html"&gt;Larry&lt;/a&gt;.  He's in the &lt;a href="http://bands.army.mil/"&gt;Army band&lt;/a&gt;, so clearly he's talented, but it goes deeper than that.  His feel is impeccable, his timing is great, and he hears everything.  What I really love about him (and many of my other favorite drummers) is that he's solid but knows when to go for it.  It's the occasional waltzes on the edge that make for an exciting, emotional musical moment.  It can't be too often, but it has to be there.  An element of risk is involved, and I love more than anything else, those improvisational moments within musical structure of the song, because that's where the magic happens.&lt;br /&gt;&lt;br /&gt;This week has been extraordinary too because I've played with three of my favorite drummers of all time.  Larry of course (and we have&lt;a href="http://www.uliners.com/gigs/the-u-liners-concert-with-ruthie-the-wranglers/"&gt; a gig this coming Saturday night&lt;/a&gt;), but also too great drummers and long time friends.  Last night the U-Liners played a show that Larry couldn't make, so my friend &lt;a href="http://www.facebook.com/Gambeats"&gt;Torro&lt;/a&gt; sat in.  Torro and I go way back (he was best man at my wedding) and is an amazing musician.  And at a jam party last Saturday night, my friend Keith came up from Florida and we got to play together for a while.  &lt;a href="http://barry.warsaw.us/musicbio.html"&gt;Keith&lt;/a&gt; was actually the first drummer that I played with where I experienced that immediate mind meld, back when I was 16 or 17.  We knew from the first song that we had Something, and now even 30 years later, it's still there.&lt;br /&gt;&lt;br /&gt;Larry and I have been doing something very cool and fun for a while now that I don't think anybody (maybe not even our fellow band members) know is going on, but it cracks the hell out of us!  At the end of songs, there's usually a little closing fill, kind of a ba-dump roll that ends thing.  Larry and I have this little game going on where we hit those little closing rolls dead on.  I honestly don't know how we do it, nor do I really want to know!  We're not 100% together, but it's better than 9-out-of-10, and the rest are pretty darn close.  It's not because that closing is the same every time; in fact, he sometimes challenges me by throwing in subtle differences, or delaying the hit, or adding a little extra flourish.  The key to me seems to be to all mindfulness. I don't think.  I just open my ears and my eyes and let my fingers do the right thing.  If you see us laughing at the end of a song, it's because we've hit a particularly good one.&lt;br /&gt;&lt;br /&gt;The wild thing about this is that even with the hour or so I played with Keith and Torro this week, I've managed the same connection with them.  Keith and I played one song that was almost all improv, and it was one of those chord progressions where it always comes back around to the head, so you're never quite sure how you're going to get out of it.  Then, out of nowhere, there it was, a clean ending where we Just Knew it was ending, Keith and I hitting the last notes perfectly in unison, perfectly unplanned, but as tight as if we'd played together every day for those 30 years.  We looked up afterward and just had to laugh!  Torro and I had several such moments at last nights gig.&lt;br /&gt;&lt;br /&gt;It's moments like these that make me so thankful to be a bass player bless with good drummers, and really just great musicians in my life.  It's what makes being the bass half of this whole thing such an ongoing joy.&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;&lt;br /&gt;It looks like my new Mac laptop will be delivered today, so it's time to name it.  My naming theme has always been &lt;a href="http://en.wikipedia.org/wiki/Rush_%28band%29"&gt;Rush&lt;/a&gt; references, with a preference going toward one word &lt;a href="http://en.wikipedia.org/wiki/Rush_discography"&gt;song and album titles&lt;/a&gt;.  This laptop is going to dual-boot Mac OS X and Ubuntu, so it seems appropriate to call it "&lt;a href="http://en.wikipedia.org/wiki/Hemispheres_%28Rush_album%29"&gt;hemispheres&lt;/a&gt;" although I've yet to figure out which one is &lt;a href="http://en.wikipedia.org/wiki/Apollo"&gt;Apollo&lt;/a&gt; and which one is &lt;a href="http://en.wikipedia.org/wiki/Dionysus"&gt;Dionysus&lt;/a&gt;.  Maybe I should call the machine &lt;a href="http://en.wikipedia.org/wiki/Cygnus_X-1_duology"&gt;Cygnus&lt;/a&gt; instead...&lt;br /&gt;&lt;br /&gt;Hemispheres was also the first Rush album I heard, and I've been a rabid fan ever since.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-6108667319490043208?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/6108667319490043208/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/12/hemispheres.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6108667319490043208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6108667319490043208'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/12/hemispheres.html' title='Hemispheres'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-1188911722606095681</id><published>2009-12-02T08:30:00.003-05:00</published><updated>2009-12-02T09:01:00.209-05:00</updated><title type='text'>Laptops</title><content type='html'>I really need a new laptop.  While I love my 3.5 year old Mac Book Pro, it's by now showing its age and the abuse I've given it.  It runs &lt;a href="http://www.vmware.com/products/fusion/"&gt;Fusion&lt;/a&gt; to give me an Ubuntu desktop, but because the disk is almost full I have to run that from a USB drive, so it's slow.   I know I can upgrade the disk, but the machine is a Core Duo only, so that probably wouldn't help much.  I also have an old IBM Thinkpad X40 which has an excellent form factor, but a small screen, and the motherboard power jack has an annoying habit of screaming at a high pitch when plugged in, so it lives in its dock, making it heavier and much less portable.  And this thing is &lt;span style="font-style: italic;"&gt;really&lt;/span&gt; slow.&lt;br /&gt;&lt;br /&gt;What to do?  Well, I've been looking around and with &lt;a href="http://en.wikipedia.org/wiki/Cyber_Monday"&gt;Cyber Monday&lt;/a&gt; (do you hate that marketing term as much as I do?) I knew there'd be some great deals around.  One of the best, which if you're reading this the same day I post it, is on &lt;a href="http://www.lenovo.com/us/en/index.html"&gt;Lenovo&lt;/a&gt; computers (formerly IBM), including steep 35% discounts on Thinkpads.  I know, I should get one of those!&lt;br /&gt;&lt;br /&gt;I looked at the x200s and the x301, the former being closest to the X40 form factor, but with a WXGA+ 1400x900 screen (yay!), no trackpad (boo), and no built-in webcam (boo).  The latter has the same WXGA+ screen (yay), a trackpad (yay), a built-in webcam (yay) and default solid state drive (yay).  It's still under 3lbs (yay) and only .5lbs heavier than the x200s in its stock configuration.  But it's about $800 more before you start customizing it.  Still the discounts really bring both computers into the realm of possibility, especially for a work computer that I'll be using constantly.&lt;br /&gt;&lt;br /&gt;I came &lt;span style="font-style: italic;"&gt;this&lt;/span&gt; close to pulling the trigger, but ultimately decided not to.  Why?  Because the Thinkpads just don't &lt;span style="font-style: italic;"&gt;feel&lt;/span&gt; right under my hands.  I use a &lt;a href="http://www.microsoft.com/hardware/mouseandkeyboard/ProductDetails.aspx?pid=022"&gt;Microsoft Natural Keyboard&lt;/a&gt; on my desktop because I can type for hours with no pain.  It's about the only Microsoft product that I can highly recommend .  I think it's literally saved my career.  There's no straight keyboard in the world that I can use for more than 5 minutes without feeling pain... except the keyboard on my Mac Book Pro.  For some reason, that keyboard is also very comfortable and pain free.&lt;br /&gt;&lt;br /&gt;What's not comfortable and pain free is the keyboard on my X40.  So before I pulled the trigger on the Lenovo, I sat down and used the X40 for my most common tasks: reading email and coding.  Within about 5 minutes I remembered why I've given this machine to Max (my son, who is about as anti-Windows as I am, and loves his little &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; machine).   The thing just &lt;span style="font-weight: bold;"&gt;hurts&lt;/span&gt; to use.  I'm certainly not going to spend over $1000 on a machine that hurts, even if the discounts are insanely good.&lt;br /&gt;&lt;br /&gt;I've decided instead to save my pennies and get a new Mac Book Pro some time in the next 3 months or so.  The design of the &lt;a href="http://www.apple.com/macbookpro/"&gt;15" MBP&lt;/a&gt; has changed pretty significantly since I bought mine in summer of 2006.  They use an aluminum unibody now, a default glossy screen, and most importantly a completely different keyboard.  I honestly don't know if it will have the same comfortable feel as my current MBP.  (TBH, I don't know that the Thinkpad x200s will have the same painful feel as my x40, but I think it's a good bet.  Their designs haven't changed that much since then.)  The little I've played on a new MBP is encouraging though. &lt;br /&gt;&lt;br /&gt;And one thing's for sure, the Mac hardware is just better.  The aluminum bodies are solid and sturdy, and I think few laptops could have put up with the abuse I've given mine.  I know my old little Dell (now donated as an Ubuntu machine to a friend) failed me after about a year.  Yes, you pay for it upfront, but they are reliable workhorses, so IMO well worth the money.  Coming up with the money is a different matter.&lt;br /&gt;&lt;br /&gt;Of course, Apple won't actually build the machine I want: a Mac Book Air with a 1400x900 matte screen.  But the MBP, even with it's heavier weight, will have to do.&lt;br /&gt;&lt;br /&gt;In any case, I know that the Thinkpad isn't right for me, so for now, I will choose not to decide.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-1188911722606095681?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/1188911722606095681/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/12/laptops.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/1188911722606095681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/1188911722606095681'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/12/laptops.html' title='Laptops'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-6927101209795032452</id><published>2009-11-29T14:31:00.002-05:00</published><updated>2009-11-29T14:50:19.232-05:00</updated><title type='text'>Mailman and LMTP</title><content type='html'>So, I spent quite a bit of time this weekend making sure that Mailman 3 works with LMTP delivery from Postfix.  With some help from Patrick on the mailman-developers list, I've gotten this working pretty well.  I also took the opportunity to play with virt-manager on Karmic.  It was pretty darn easy to create a virtual machine, load it up with Ubuntu 9.10 server and test Mailman in a fairly pristine setting.  The one gotcha that I ran into was having to run virt-manager under sudo, otherwise it could not create the VM files under /var/lib/libvert/images&lt;br /&gt;&lt;br /&gt;I'm going to release Mailman 3.0.0a4 today.  It really took me much longer to get this out than it should have.  I removed the dependency on setuptools_bzr because it really sucked having to build bzr just to install Mailman.  The whole reason for the setup dependency on setuptools_bzr was to allow me to be lazy in creating the MANIFEST.in file.  I bit the bullet and created that file, but it took surprisingly many iterations to get it right.&lt;br /&gt;&lt;br /&gt;On another front, after my bout with the flu and trip to Dallas, I'd been pretty remiss in updating my two Gentoo servers.  They were way behind on patches, so I finally updated the public one, which was a royal pain in the butt.  Still, it was doable.  The internal server is running EVMS which is no longer supported by IBM or Gentoo.  I think this will be the final straw that forces me to install Ubuntu on that machine.   I'm dreading moving all the services and files off of it in preparation for that.  It's going to be a time consuming job.  Fortunately, I have a spare box that I can bounce the services to, and backups of all the files.  I'm probably going to postpone that until the long holiday break.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-6927101209795032452?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/6927101209795032452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/11/mailman-and-lmtp.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6927101209795032452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6927101209795032452'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/11/mailman-and-lmtp.html' title='Mailman and LMTP'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-3570996910156553905</id><published>2009-10-08T19:31:00.005-04:00</published><updated>2009-10-08T20:16:38.680-04:00</updated><title type='text'>House, Music, Hacking</title><content type='html'>Well, it's been a long time since I posted anything here, and a lot has happened.  I won't bore you with all the details, but suffice to say it's been an interesting ride.  The good news is we were able to move back into our house in August and life is good.  We're not completely done, but we're getting back on track and moving on with our lives.&lt;br /&gt;&lt;br /&gt;Max started middle school so I am officially a morning person now, and I've even caught the &lt;a href="http://www.facebook.com/barry.warsaw"&gt;Facebook&lt;/a&gt; bug.  We got a cat.&lt;br /&gt;&lt;br /&gt;I want to expand this blog to cover things technical and personal, and I'm going to spend a little time every week posting something here.  I was going to say "something interesting" but it probably won't be, so you're just wasting time reading this. :)&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.python.org/community/sigs/current/email-sig/"&gt;email-sig&lt;/a&gt; is very interesting lately.  Python comes with a package to parse, generate and manipulate email messages.  It's actually very functional in Python 2 but mostly because we cheat.  In Python 2 we can be lazy about what's a string and what's a byte and email exploits this profusely.  I know this because the email package is severely damaged in Python 3, where the distinction between strings (unicodes) and bytes is explicit.  The email-sig is tasked with maintaining and developing the email package and we're struggling with many tricky issues.  And y'all thought email was simple because 99% of it is spam.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.python.org/download/releases/2.6.3/"&gt;Python 2.6.3&lt;/a&gt; was released last Friday, but it was broken and no one should use it.  It's my fault as the release manager for wanting a shortened candidate cycle, but I'm still not convinced that a long cycle would have avoided the regressions.  2.6.3 broke the logging module and setuptools, so I released &lt;a href="http://www.python.org/download/releases/2.6.4/"&gt;Python 2.6.4rc1&lt;/a&gt; on Tuesday.  2.6.4 will have a nice long candidate release and a very conservative commit policy.  We'll just fix the regressions in 2.6.3 and hopefully have a solid 2.6.4 on October 18.&lt;br /&gt;&lt;br /&gt;On a personal note, I've been taking vocal lessons from &lt;a href="http://www.dedewyland.com/"&gt;Dede Wyland&lt;/a&gt; for about 6 weeks.  She taught Joe Uehlein (from the &lt;a href="http://www.uliners.com/"&gt;U-Liners&lt;/a&gt;) and she's fantastic.  I never really understood harmony theory, but her explanations were fantastic.  Tenor tends to sing a &lt;a href="http://en.wikipedia.org/wiki/Chord_%28music%29"&gt;chord tone&lt;/a&gt; above the melody and baritone tends to sing a chord tone below the melody.  So if the chord is G major and the melody is singing a B (the major 3rd), the tenor will sing a D (the 5th) and the baritone will sing a G (the root).  I was pleasantly surprised that I didn't totally suck when we sang together!  I'm really enjoying stepping up to the mic more often.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-3570996910156553905?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/3570996910156553905/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/10/house-music-hacking.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/3570996910156553905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/3570996910156553905'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/10/house-music-hacking.html' title='House, Music, Hacking'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-3327102554187224919</id><published>2009-03-06T19:09:00.002-05:00</published><updated>2009-03-06T19:15:50.603-05:00</updated><title type='text'>Roof</title><content type='html'>Okay, we have roof and insulation estimates.  There are basically three options.  The most expensive involves using this foam insulation between the attic rafters.  This would give us essentially a conditioned attic which would be usable in for living space in the future.  Given the price, and what we're going to use the attic for this seems overkill.&lt;br /&gt;&lt;br /&gt;The second option involves insulating between the joists in the second floor ceiling but there are problems with this approach because batt insulation to code won't fit in the old shorter joists.  So this option will include building up the joists to accept the R38 insulation.&lt;br /&gt;&lt;br /&gt;The final (and cheapest) option seems best to me.  This involves using 12" rafters in the new roof so that it can accept the 10.5" R38 batt insulation.  We're going to go this route and it'll cost us approximately $6500.  I have to hand it to the builder for really working with us to make this as palatable as possible.  It's definitely not something I expected to spend money on and it's definitely a painful hit, but in the long run I think it will work out by giving us much better insulation and usable attic space.  I also think it will be easier for the builder.&lt;br /&gt;&lt;br /&gt;Now we just need plans for the roof, and the county will probably have to approve it. (I wonder how much &lt;span style="font-style:italic;"&gt;that's&lt;/span&gt; going to cost?!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-3327102554187224919?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/3327102554187224919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/03/roof.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/3327102554187224919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/3327102554187224919'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/03/roof.html' title='Roof'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-1823802887919927913</id><published>2009-02-13T19:06:00.000-05:00</published><updated>2009-03-06T19:09:12.251-05:00</updated><title type='text'>Insulate?  Holy Moly!</title><content type='html'>We got quotes on the roof insulation.  Wow, it is not cheap and it makes the whole roof proposition an even harder hit.  It's going to add $2000-$3000 onto the total cost of the roof.  Tom will work up specific estimates and we'll go over these at our next production meeting.&lt;br /&gt;&lt;br /&gt;Nothing is happening at the house.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-1823802887919927913?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/1823802887919927913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/02/insulate-holy-moly.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/1823802887919927913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/1823802887919927913'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/02/insulate-holy-moly.html' title='Insulate?  Holy Moly!'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-5377450685213805024</id><published>2009-02-11T19:04:00.002-05:00</published><updated>2009-03-06T19:06:38.109-05:00</updated><title type='text'>Waiting</title><content type='html'>Not much is happening, as we're waiting to decide about the roof.  We need to get insulation numbers.  Tom really thinks rebuilding the roof is the best thing.  I tend to agree, but we need to make it fit the budget.&lt;br /&gt;&lt;br /&gt;We told Tom about the placement of the kiln, which we want to put in the unconditioned space.  This shouldn't be a problem, but we're still waiting to see the electrical bid.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-5377450685213805024?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/5377450685213805024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/02/waiting.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/5377450685213805024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/5377450685213805024'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/02/waiting.html' title='Waiting'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-4553106646623245283</id><published>2009-02-10T18:52:00.002-05:00</published><updated>2009-03-06T19:04:04.471-05:00</updated><title type='text'>A new roof?</title><content type='html'>The builder is recommending that we rip off the old roof entirely and rebuild it from scratch.  The cost came in at $4700 but that does not include insulation (or the 20% change order markup), so we'll need a complete price in order to decide if we should do it.  This is a big hit to the budget, but it seems like it's really going to be the best option.  We'll need architectural and structural plans for the new roof, which basically must look like the original roof in front (hip with dormer) and like the plans in the back (hip joint to match the front).&lt;br /&gt;&lt;br /&gt;We looked at the shingle colors - I think Jane would love to go dark dark, but that's not nearly as energy efficient as a lighter color.  I think we'll end up compromising on something like Forest Gray which is just a shade or two lighter.  Wouldn't it be great if we could just layer solar panels over the entire roof?  Maybe in Max's first house.&lt;br /&gt;&lt;br /&gt;We met the stucco contractor today, who dropped off some samples and a color palette.  Seemed like a nice guy and he offered to take us around to some of his jobs to see his work.  I'm sure Jane will take him up on that.  Sounds like he can basically match any paint color in the stucco; we also need to pick a finish.  Jane's leaning toward the coarse grain for the majority of the house, with a fine finish for the trim.  The really coarse finish just didn't do it for us.&lt;br /&gt;&lt;br /&gt;The cabinets are killing us!  We did a plan at HD for some fairly standard KM cabinets.  I'm not very psyched about them, and it's really difficult to get cabinets that don't look like they belong in an apartment.  The thing that sucks the most about the KMs is that they really don't give you the options you want.  For example, we'd like to get the Shaker Rail doors in a dark color, but you can't do that.  Not to mention that we're still at about $9000 for the quote, and even with the HD discount, we're still going to be a thousand or so over our allowance.  We'll see about ditching the glass fronts, but that brings the discount down along with the price.&lt;br /&gt;&lt;br /&gt;Really, we want to do something &lt;span style="font-style:italic;"&gt;different&lt;/span&gt; but that seems impossible on our budget.  Still looking.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-4553106646623245283?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/4553106646623245283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/02/new-roof.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4553106646623245283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4553106646623245283'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/02/new-roof.html' title='A new roof?'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-6499006740456463920</id><published>2009-02-04T18:43:00.003-05:00</published><updated>2009-03-06T18:54:06.846-05:00</updated><title type='text'>Little things</title><content type='html'>Lots of little things today, but not too much progress.  Tom came up with a great, simple idea for the stair posts, involving bearing the load on the existing steel beam in the basement, then pull that load across to the outer wall.  This means we won't need to break up the concrete and pour another footing, with the sleeve around the waste pipe.&lt;br /&gt;&lt;br /&gt;We don't want to overbuild the existing roof, nor do we really want huge trusses because both options will severely limit the amount of usable space in the attic.  We need to get options and costs on our alternatives.&lt;br /&gt;&lt;br /&gt;Jane is still thinking about the RTA cabinets.  Everyone's saying "Don't do it!" because of the amount of work involved and the low margin of error.  Still, to get close to the cabinet allowances, we may have to do it this way.  No decision on the cabinets are made yet.&lt;br /&gt;&lt;br /&gt;The bay window will be insulated after the close-in inspection, so there's plenty of time for that.&lt;br /&gt;&lt;br /&gt;Tom will get Jane square footage for tile, so that she can start looking into that.&lt;br /&gt;&lt;br /&gt;We're still waiting on the electrical proposals.&lt;br /&gt;&lt;br /&gt;We'll need to pick the shingle colors this week.  This is especially important because we need to match it to the stucco color, which we also have to start thinking about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-6499006740456463920?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/6499006740456463920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/02/little-things.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6499006740456463920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6499006740456463920'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/02/little-things.html' title='Little things'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-6509416336655169283</id><published>2009-01-31T23:26:00.000-05:00</published><updated>2009-02-10T23:28:46.795-05:00</updated><title type='text'>Nope</title><content type='html'>We got some cost estimates on the two alternatives we talked about previously.  As suspected, both the additional insulation in the exterior walls, and the beadboard in the porch are too expensive so we'll pass on those.&lt;br /&gt;&lt;br /&gt;The porch, with a wood flooring, is framed up to the headers.  We're still waiting for structural on the bathroom and roof, and we're still waiting for the partial lien wavers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-6509416336655169283?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/6509416336655169283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/nope.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6509416336655169283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6509416336655169283'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/nope.html' title='Nope'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-5331013252378868955</id><published>2009-01-30T23:06:00.003-05:00</published><updated>2009-02-10T23:26:23.523-05:00</updated><title type='text'>What's goin' on</title><content type='html'>The porch deck is being built now and the basement plumbing is done.&lt;br /&gt;&lt;br /&gt;We've talked more about the structural options for keeping the existing bathroom.  One option is to bring a footer down through the corner of the new basement bathroom.  The unfortunate thing is that this drops right onto the waste pipe, with a sleeve to protect against any future settling.  This would entail tearing out more of the original cast iron.&lt;br /&gt;&lt;br /&gt;We also learned that the basement slab falls 2" from front-to-back but nothing significant side-to-side, so this will probably be easy to level out in the new slab.&lt;br /&gt;&lt;br /&gt;There's a conflict in the roof drawings.  We noticed that the architectural drawings say to tear the back roof off, while structural says to build over the existing roof.  We'll have to think about options for resolving this and work out some numbers.&lt;br /&gt;&lt;br /&gt;One time sensitive decision coming up is the rough-in kits for the showers, and we'll need to research the water heater a bit.  We're also waiting on structural for the stair support options.  In the meantime, the porch will be framed out.&lt;br /&gt;&lt;br /&gt;I had a thought about some extra porch steps leading down from the small corner jog to the Louis side.  Steve said he'd think about this, but I get the sense he's not crazy about the idea.  I don't think Jane is either, so I'll probably be convinced to drop it. :)  Jane is also thinking about doing beadboard between the porch roof beams and the ceiling, but again, it probably won't be cost effective to do.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-5331013252378868955?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/5331013252378868955/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/whats-goin-on.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/5331013252378868955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/5331013252378868955'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/whats-goin-on.html' title='What&apos;s goin&apos; on'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-5900216019193918049</id><published>2009-01-28T23:03:00.002-05:00</published><updated>2009-02-10T23:06:15.288-05:00</updated><title type='text'>Snow!</title><content type='html'>Today's production meeting needs to be rescheduled due to the snow, but we did get the window list in an email and will review that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-5900216019193918049?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/5900216019193918049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/snow.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/5900216019193918049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/5900216019193918049'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/snow.html' title='Snow!'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-2043225038441333080</id><published>2009-01-27T22:58:00.002-05:00</published><updated>2009-02-10T23:03:04.474-05:00</updated><title type='text'>Return from vacation</title><content type='html'>We were on vacation for a few days, doing some much needed detox on the ski slopes.&lt;br /&gt;&lt;br /&gt;On our return, we saw that the whole addition is framed out, but not yet under roof.  The brick exterior on the back of the old house has been demoed but not yet cleared.  There's some kind of weird contraption on the roof.  I wonder what that's all about?!&lt;br /&gt;&lt;br /&gt;There's not much other activity at the house, probably due to the snow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-2043225038441333080?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/2043225038441333080/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/return-from-vacation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2043225038441333080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2043225038441333080'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/return-from-vacation.html' title='Return from vacation'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-6744271088715328031</id><published>2009-01-22T22:49:00.001-05:00</published><updated>2009-02-10T22:58:34.421-05:00</updated><title type='text'>More considerations</title><content type='html'>We thought about a couple of extras today:&lt;br /&gt;&lt;br /&gt;Since the front wall where the bay window is was torn out, we noticed that the existing house is basically uninsulated.  One of the things we're considering is tearing out the few outside walls we aren't touching, insulating, and re-drywalling them.  It's tricky though because we've got some weird 1930's pre-drywall covering on the studs.  There's only a few walls we're talking about, but it's still probably more work than we want to pay for.  We've asked for an estimate and will get it from the builder soon.&lt;br /&gt;&lt;br /&gt;There's another issue with the existing bathroom that we're not touching.  There's a question about how the support for the new stairs is going to tie into the perimeter wall.  This beam runs under the existing bathroom, but the plumbing is essentially in the way.  We've asked for an estimate to tear the bathroom out and rebuild it, but it will probably be cost prohibitive.  We're looking into other options, and are consulting the structural engineer to see if we can just drop a post down into the basement.&lt;br /&gt;&lt;br /&gt;I also walked the site with one of the electricians, looking at what we want (especially with some kind of X10 setup, the network cabling and the additional outlets in the office and computer closet.  We'll review his bid when it comes in and probably get a second bid as well.&lt;br /&gt;&lt;br /&gt;Good news!  The plumber's come in and verified that we will not need an ejector pump.  I'm really glad we won't have to worry about that gross little addition.&lt;br /&gt;&lt;br /&gt;The framing out of the ground floor is continuing apace.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-6744271088715328031?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/6744271088715328031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/more-considerations.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6744271088715328031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/6744271088715328031'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/more-considerations.html' title='More considerations'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-4504378322805067482</id><published>2009-01-21T22:25:00.005-05:00</published><updated>2009-01-21T23:12:53.086-05:00</updated><title type='text'>Thinking About Windows</title><content type='html'>We had our weekly production meeting this morning, Steve, Tom, Jane and I.  Tom brought the tentative window order by and we went through them.  Would you believe how hard it was to remember what was in the original house, at least until I pulled up the pictures from the web!  To save money, we're matching the new windows with the vinyl replacements that already exist.  Those are all 3x2 on top and no mullions on the bottom.  We can match all of those except for the casement windows we'll be using in the new bedrooms to conform to egress code.  The small 25" wide windows will be awnings, and everything else will be double hung windows.  The dormers will probably be fixed and we'll be getting half screens all around.  The only tempered windows will be the small ones in the basement, which are just above grade.&lt;br /&gt;&lt;br /&gt;We noticed that the bay window is fully framed in now, but the guys forgot to insulate the well underneath it, so Tom is going to get them to pull up that flooring and insulate there.  Supposedly the plumber was coming by today, but I never did hear the verdict on that.&lt;br /&gt;&lt;br /&gt;We talked at length about the stucco seams that are needed at all material joins, and runs over 144 square feet.  Since the Louis side marries the old brick construction with the frame construction of the new part, there will be a vertical seam right there.  We really need to match that well so that its as unnoticeable as possible, as it's going to be 1/2" wide the height of the house.  There will be some horizontal seams as well, and we may place them low on the house, and draw them all the way around, with a color offset for aesthetics.&lt;br /&gt;&lt;br /&gt;I read something on the 'net about stucco and the need for kickout flashing, which is installed at the transition between roof and vertical wall.  It's purpose is to "kick out" any water away from the wall, so it can't seem behind the stucco and cause problems.  I'll have to remember to ask about that when we get to that phase of the project.&lt;br /&gt;&lt;br /&gt;I took a &lt;a href="http://picasaweb.google.com/warsaw/TheFloor09#"&gt;few pictures&lt;/a&gt; of today's progress. You can see that they've put the deck on for the new part of the house.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-4504378322805067482?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/4504378322805067482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/thinking-about-windows.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4504378322805067482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4504378322805067482'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/thinking-about-windows.html' title='Thinking About Windows'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-7332258036184267341</id><published>2009-01-20T06:38:00.003-05:00</published><updated>2009-01-21T06:44:51.824-05:00</updated><title type='text'>BHO!</title><content type='html'>I just have to take a moment and say what an amazing day today was.  BHO is now our 44th president and there were millions of people on the mall to witness it.  Our neighbors biked down as we're only about 6 miles or so from the center of DC.  Me, it was too darn cold and I had to work, but I did take a long lunch break to watch.  I have nothing more profound to say than what everyone else has said, but it sure was cool.&lt;br /&gt;&lt;br /&gt;And what's that with Cheney?  Could he &lt;span style="font-style:italic;"&gt;be&lt;/span&gt; any more Mr. Potter than that?  George Bailey -&gt; Mr. Smith -&gt; Barack Obama anyone...?&lt;br /&gt;&lt;br /&gt;Anyway, back to (as my wife would say) my boring house blog.  Although we talked to Tom about the windows, there's no feedback on that yet, though we have a production meeting tomorrow morning.  I went over to the house and it looked like the bay was framing was complete, including the roof.  The one or two poor guys working out on that frigid day were putting a wood cap on the poured concrete walls of the conditioned area.  Now the bolts sticking up make perfect sense, as the wood planks are literally screwed onto them nice and solid.&lt;br /&gt;&lt;br /&gt;I didn't get into the house today, but will try to do so tomorrow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-7332258036184267341?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/7332258036184267341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/bho.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/7332258036184267341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/7332258036184267341'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/bho.html' title='BHO!'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-25218717677578005</id><published>2009-01-19T06:28:00.002-05:00</published><updated>2009-01-21T06:38:01.097-05:00</updated><title type='text'>Waterproofing</title><content type='html'>Looks like today was a fun day with gooey black tar.  This stuff is used to waterproof the foundation poured concrete walls that form the conditioned part of the house.  The walls forming the unconditioned parts apparently are not waterproofed, such as the area under the entranceway, the stairs leading down from what will be the back porch, and the unconditioned area under the porch.  I bet it wasn't fun to be slather that stuff all over the place in the cold we've been experiencing lately.  I also hope that the stuff still &lt;span style="font-style:italic;"&gt;works&lt;/span&gt; when it's slather on in that cold!&lt;br /&gt;&lt;br /&gt;The bay window was framed out today, or mostly so.  That's gonna be a really nice touch to the exterior view.&lt;br /&gt;&lt;br /&gt;No word yet on the ejector pump.  Tom dug down about 12" and did not see the top of the sewage line, but the plumber still needs to come in and take a look to give us the final word.  We discussed re-arranging the bathroom in the basement to make it fit if necessary.  We'll see...&lt;br /&gt;&lt;br /&gt;The framing of the new living space was delayed because Tom was waiting for word from the stucco guy, just to make sure tolerances were set for marrying the old and new part of the house.  The old part will of course be stuccoing over brick, while the new will be wood.  The wood needs to be 1/2" back from the brick so that it can accept the mesh that the stucco will be applied to.&lt;br /&gt;&lt;br /&gt;The one bummer is that there will have to be a seam between the old and new parts of the house.  This makes sense because the original house has been settling for 70 years.  We're concerned that the caulk seam will be too noticeable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-25218717677578005?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/25218717677578005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/waterproofing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/25218717677578005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/25218717677578005'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/waterproofing.html' title='Waterproofing'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-4962440160603401031</id><published>2009-01-18T11:13:00.002-05:00</published><updated>2009-01-19T11:30:42.613-05:00</updated><title type='text'>New picture site</title><content type='html'>Everybody needs a day off.  It's Sunday and there's no activity, but we did get a chance to show Jane's sister, brother-in-law, and their kids around the site.&lt;br /&gt;&lt;br /&gt;Because of limitations in Flickr and because there's some nicer integration with blogger, I've moved the canonical location of the construction pictures to &lt;a href="http://picasaweb.google.com/warsaw"&gt;Picasa&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-4962440160603401031?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/4962440160603401031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/new-picture-site.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4962440160603401031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4962440160603401031'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/new-picture-site.html' title='New picture site'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-4935122702314786137</id><published>2009-01-17T11:18:00.000-05:00</published><updated>2009-01-18T11:26:55.294-05:00</updated><title type='text'>A Down Day</title><content type='html'>Not too much happening today.  The guys were going to start framing, and though there's a big pile of wood out there, there's no sign of that happening.  They did start framing out the floor for the new bay window.&lt;br /&gt;&lt;br /&gt;Steve and I did get a chance to get inside and look around.  We were actually looking for a couple of stands for the dumpster drums I'm loaning his son Graham (a good friend of my son Max and a budding Neil Peart).  Well, we couldn't find the stands -- they're either in the pods or gone gone gone -- but it was good to walk around with Steve.  The basement step-up was jackhammered, but we haven't yet heard the gravitational verdict, and it looks like the temporary walls were built in the basement.  I suspect the basement stairs will be ripped out before we know it.&lt;br /&gt;&lt;br /&gt;We have &lt;span style="font-weight:bold;"&gt;got&lt;/span&gt; to wrap the sofa bench that we left in the house.  It's huge and difficult to move, but not only was it heavily dusted, we noticed that there was a McDonalds drink cup left on it by one of the workers.  I'll probably head to the hardware store and do that before we get too much farther.&lt;br /&gt;&lt;br /&gt;It was also really cool to walk around the new foundation, see the poured walls from the inside and get a sense of what the new space will be like.  We had a question about the window cut outs on the Louis side of the basement since there are supposed to be three windows there, but there are only two cut outs.  The third is in the interface between the old and new house, so we think they'll just carve out what they need once the back wall comes down.  We'll verify that with the builder.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-4935122702314786137?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/4935122702314786137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/down-day.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4935122702314786137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4935122702314786137'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/down-day.html' title='A Down Day'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-388849359008611050</id><published>2009-01-16T10:51:00.000-05:00</published><updated>2009-01-18T11:18:12.417-05:00</updated><title type='text'>Foundations</title><content type='html'>I had a chance to see the poured foundation walls today.  Originally, we were thinking to use block construction, but there's no arguing with the speed at which the poured concrete walls went up.  Our builder has a lot of experience with this construction method, and our architect is cool with it so it's the way we went.  Jane's not psyched about the formed brick impressions (she detests fake attempts when something tries to look like what it's not), but all that is going to get stuccoed anyway so you'll never see it.&lt;br /&gt;&lt;br /&gt;(Aside: Jane gives me grief because this is all boring and not funny.  I keep telling her that things are moving so fast, and there's so much information to get in that there isn't time to be funny.  Don't worry!  I'm sure there will be plenty to laugh about later.)&lt;br /&gt;&lt;br /&gt;One big question that we have is whether we're going to need an ejector pump in the basement or not.  The basement bathroom is above a step-up at the bottom of the basement stairs.  We don't really know what's under that step-up.  Ideally of course, the sewage line is below the grade of the new basement bathroom and we'll just let gravity do what it does best.  If not, we'll need an ejector pump to get the, er, goo up from the lower bathroom into the main sewage line.  If necessary, we'll hide the ejector pump under the stairs just as we're doing with the sump pump.  We think there's enough room there.  Tomorrow hopefully, we'll get that step-up jackhammered and take a look at what's there.&lt;br /&gt;&lt;br /&gt;The other issue is the gas meter, which is currently inside what &lt;span style="font-style:italic;"&gt;was&lt;/span&gt; the utility room, but what will be the family room if we finish the basement.  Of course, we'd rather not have the gas meter in that location, but it may not be feasible to move it.  There's no room outside that wall because of the new bay window, and it will probably be cost prohibitive to move the meter to the far side of the house where the new utility room is going.  The plumber indicates that even with the additional BTUs of Jane's New UberOven we apparently won't &lt;span style="font-style:italic;"&gt;need&lt;/span&gt; a new meter, so the gas company would be reluctant to pay for moving it.  It won't be that big of a deal if we keep it where it is; we'll just hide it behind a closet or some such.&lt;br /&gt;&lt;br /&gt;We're still thinking about finishing the basement.  It's an additional cost (not part of the base contract), but it sure would be nice.  We have some time to decide.  We also have a bit of time to decide about the new back porch and new front walkway.  Jane really wants to flagstone it, but that's also an extra cost.  The difference is in the finish and depth of the concrete we're pouring in those locations.  Obviously if we don't flagstone it, we'll have a nice smoother finish, but if we do cover it in flagstones, we'd want a more rough and thinner slab there.  Again, we have time to decide.&lt;br /&gt;&lt;br /&gt;As a cost saving measure we decided to keep the existing vinyl replacement windows in the old house and match the new windows as best we can.  The problem is that new windows have a different reveal (the border area) than replacement windows.  This won't matter on the front of the house because the only new windows are the bay and that will look different anyway.  On the back, it's all new windows and on the Scutt-side it won't matter too much because it's not really visible from the street.  On the Louis-side though there will be a mix of existing and new windows and Jane is concerned about the different looks.  We'll have a better feel for that when we see some window options.&lt;br /&gt;&lt;br /&gt;If the lumber arrives, we're told they may begin framing tomorrow.&lt;br /&gt;&lt;br /&gt;Um, how the hell are the pod guys going to get their pods back when they're done?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-388849359008611050?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/388849359008611050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/foundations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/388849359008611050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/388849359008611050'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/foundations.html' title='Foundations'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-4767551294000112514</id><published>2009-01-15T21:47:00.000-05:00</published><updated>2009-01-18T13:22:30.686-05:00</updated><title type='text'>Compromise, and progress</title><content type='html'>(Happy Birthday, Mom!)&lt;br /&gt;&lt;br /&gt;Today we had a production meeting at 7am with the builder, his project manager, and our architect.  We talked about a bunch of things, including the need to raise the windows behind the kitchen banquette (for the seat backs), the fact that the original slab isn't level (but only slightly, and we don't yet know what the impact on the new slab will be), and what we'll use to frame the floor of the porch.  Interestingly enough, one sheet of the plans calls for Trex while another leaves it unspecified, and our contract states Trex as an alternative.  Neither our architect nor we really care too much as long as it is structurally sound and has water and ice guards.  Later, our builder related that they preferred to wood frame it.&lt;br /&gt;&lt;br /&gt;There's an unconditioned space below the porch, but my eventual hope is that in a few years we'll close that off, bring in hvac and electrical and possibly be able to finish it.  It's a nice little space, but we really can't afford to finish it now, so it'll mostly be used to store lawnmowers, bikes and the lot.  Someday it might make a nice little area for Jane's pottery studio perhaps.&lt;br /&gt;&lt;br /&gt;Another interesting thing about that space: I wanted to put a concrete ramp in next to the stairs, so we've actually designed a 6' wide entrance.  Unfortunately, even though that ramp was approved by the county, it turns out that it's not up to code after all, so we're going to put stairs in across the entire 6 feet and then probably put in a wooden ramp or some such for the few times I need to haul gear up and down.  I'm disappointed, but we can work around it.&lt;br /&gt;&lt;br /&gt;As mentioned yesterday, we did discuss the drywells for stormwater runoff, but since the county is pretty strict about this, we're going to leave it as designed.&lt;br /&gt;&lt;br /&gt;I'm glad that we'll be waterproofing most of the outer foundation.  Almost the entire perimeter has been dug around: the entire back of course, the side because of the new entrance footers, and half the front for where the new bay window is going.  All that will be waterproofed.  The neighbor side and half the front will be left alone, but they're already dry and we'll make sure the new grading will keep it that way.&lt;br /&gt;&lt;br /&gt;There was also a question about whether code would require a sprinkler system, but we've learned that our plans will not require it.&lt;br /&gt;&lt;br /&gt;One of the things I really want to think about is wiring the house for smart home.  I mean, what would be cooler than being able to log into your house and turn off the lights when you're on vacation?  I'm not sure we'll be able to afford to put in all the fixtures, but I really want to at least prep the house so that we can do this if we want.  Of course, I'll also want to wire the house up for cat-6 so we can hardwire a few rooms to reach areas where wireless sucks.  I'm starting now to research all this, but if you have suggestions, please leave a comment with some suggestions!&lt;br /&gt;&lt;br /&gt;Oh, and the &lt;a href="http://picasaweb.google.com/warsaw"&gt;photo stream&lt;/a&gt; is up!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-4767551294000112514?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/4767551294000112514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/decisions-decisions.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4767551294000112514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/4767551294000112514'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/decisions-decisions.html' title='Compromise, and progress'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-7681841914643192747</id><published>2009-01-14T19:53:00.000-05:00</published><updated>2009-01-14T20:26:52.339-05:00</updated><title type='text'>A big ol' pile of dirt</title><content type='html'>It's amazing how quickly things have happened.  The project manager (Tom) is a great guy and he's explained that we'll see a lot of progress early on, but that once the addition is framed and under roof, things will appear to slow.  Plumbing, electrical and hvac all take a long time to complete.  That's okay, right now it's very exciting!&lt;br /&gt;&lt;br /&gt;Today the excavation was largely complete.  There is now a BIG hole in the backyard, stretching almost all the way back to the tree line.  This is sure going to eat up most of our backyard.  There's also a ditch along the side of the house (which, because we're on a corner lot faces the street we are not addressed on), and a hole near the front door where the bay window will go.  Footers were poured today for all of that.&lt;br /&gt;&lt;br /&gt;We hit our first snag, namely in where the sump pump is going to go.  The original plans were going to put this under the unconditioned space under the porch, but that's not allowed or recommended because it can freeze.  Since that space will (for now) be open, you just don't want the sump pump to be exposed to the elements.  We've decided to move the sump pump to under the basement stairs, which are barely usable as it is because it's such a small space.  We'll have access to the pump from a utility door and it'll still drain out of the side of the house.  The unconditioned area will still have a floor drain to handle any rain and such.&lt;br /&gt;&lt;br /&gt;We briefly toyed with the idea of enclosing the unconditioned area, running hvac and electrical to it, so that we could use it as an additional room, but because of the way the stairs and ramp lead out of the basement, it isn't feasible or cost effective.  We're talking more architectural and engineering fees, and most significantly, delays in schedule getting the changes approved by the county.  We'll leave this area unconditioned for now, though our architect has assured us that should we decide to enclose it a few years from now, it will be doable (with some accommodation for the lack of an exterior landing, which we just can't fit given the yard space).&lt;br /&gt;&lt;br /&gt;Another snag we hit was with the drainage plan, which was added at the last minute in order to gain county approval.  It turns out that this will leave two clean out access ports in the front yard, each about 8" in diameter.  This is unfortunate because they'll basically be front yard artifacts that will be somewhat unsightly.  Tom and Larry (the builder) have told us that once the yard is given its final grade, the drainage pipes will be shorn so that they'll be at or below grass level.  Hopefully they'll be easy to hide behind some gardening.  We're exploring the possibility of using a single drain, but we're doubtful that the county will either give its approval, or do so in a timely manner.  We really do not want to incur delays here.&lt;br /&gt;&lt;br /&gt;Tomorrow, we've got our first production meeting with Tom and Larry, along with Steve (our architect).  We've all met before, but I think it'll be good to talk about some of these outstanding issues, establish regular meetings, get a schedule, etc.  It's gonna be cold tomorrow, so we're doing it at the rental house.  Yay for 7am meetings!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-7681841914643192747?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/7681841914643192747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/big-ol-pile-of-dirt.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/7681841914643192747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/7681841914643192747'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/big-ol-pile-of-dirt.html' title='A big ol&apos; pile of dirt'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-2246921245684026208</id><published>2009-01-13T22:39:00.000-05:00</published><updated>2009-01-13T22:49:47.907-05:00</updated><title type='text'>Where'd my house go?</title><content type='html'>Well, we woke up this morning to find most of our house gone.  Actually, we'd sort of expected it since the county approved our plans on Friday.  We've been in our house in suburban Washington DC for more than 6 years and always planned on doing a renovation project.  It's taken this long for us to get off our butts and finish the plans, line up a builder, arrange financing, and so on.  Given the sorry state of the housing market, this is either the smartest thing we've done, or the dumbest.&lt;br /&gt;&lt;br /&gt;Anyway, we were expecting to break ground tomorrow, but Jane had to go up to the school this morning and saw the project manager on her way.  He asked her if she'd seen the house -- which she hadn't yet.  So we went over there and by noon, they had ripped off the crappy addition, taken off the awning and the concrete slab underneath, and nearly completely stripped the interior.  Kitchen?  Gone.  Basement? Gone.  Upstairs walls?  Gone.  Unbelievable.&lt;br /&gt;&lt;br /&gt;By the time school had let out, the concrete to the front door was gone as was the huge azalea bush that Max and his friends had used as a secret fort.  The bobcat and backhoe were hard at work digging out the big hole which will soon be the new part of our basement.&lt;br /&gt;&lt;br /&gt;It's only the first day, but it was a good, exciting, freakout kind of day.  I can say one thing though: I am so glad we decided to move out while the construction was under way!  We took lots of pictures, which I'll be posting to Flickr as soon as possible.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-2246921245684026208?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/2246921245684026208/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2009/01/whered-my-house-go.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2246921245684026208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2246921245684026208'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2009/01/whered-my-house-go.html' title='Where&apos;d my house go?'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-7372749166988517745</id><published>2003-04-21T22:44:00.000-04:00</published><updated>2009-01-15T23:13:49.216-05:00</updated><title type='text'>Pain</title><content type='html'>&lt;span style="font-style:italic;"&gt;This is a repost from my earlier blog.  I totally disavow everything my younger self said.  He doesn't know what he's talking about.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There's a &lt;a href="http://www.startrek.com/library/episodes_tos.asp"&gt;Star Trek (original series)&lt;/a&gt; episode that I dimly remember.  I think it's the one with the rotating stoner light on the ceiling in the &lt;a href="http://www.startrek.com/library/tos_episodes/episodes_tos_detail_68682.asp"&gt;penal colony&lt;/a&gt;, but I'm not sure.  I don't know what's sadder: that I used to be able to name each episode before the first commercial break, or that my memory is so far gone, that I no longer can.&lt;br /&gt;&lt;br /&gt;Anyway, I think while Kirk's in the chair transfixed by "the colors, dude!" a man in the next room utters the single word: Pain.  And Kirk feels the pain.&lt;br /&gt;&lt;br /&gt;I'm thinking of this because I'm doing a &lt;a href="http://www.cvshome.org/"&gt;CVS&lt;/a&gt; merge from the trunk of the &lt;a href="http://www.list.org/"&gt;Mailman&lt;/a&gt; tree into the 2.1 maintenance branch.  That perverse little guy who invented CVS has just uttered "Pain" as I stare transfixed at all the pretty colors in my &lt;a href="http://www.xemacs.org/"&gt;XEmacs&lt;/a&gt; buffer.   And it hurts like someone &lt;a href="http://www.woodcarvers.org/golfballs.htm"&gt;knifed open your balls&lt;/a&gt; (which has happened to me, but that's probably too much information, huh?).&lt;br /&gt;&lt;br /&gt;Why is this so painful?  Well, part of the reason is that there are CVS id strings in the files that really shouldn't be there.  They just cause conflicts for no good reason.  Yeah, I know about -kv, but I know it about the same way I know the Star Trek episode, so it doesn't help me much.&lt;br /&gt;&lt;br /&gt;The other reason is worse: there are tons of files that aren't in English and that I didn't write.  Because Mailman is internationalized, there are a raft of files containing text in everything from &lt;a href="http://www.cia.gov/cia/publications/factbook/geos/it.html"&gt;Italian&lt;/a&gt; to &lt;a href="http://www.cia.gov/cia/publications/factbook/geos/ja.html"&gt;Japanese&lt;/a&gt;, and now (tickling my ethnic pride nose hairs) &lt;a href="http://www.cia.gov/cia/publications/factbook/geos/pl.html"&gt;Polish&lt;/a&gt; too.  Now, for my own sanity, I'm trying to move to a place where the translation teams make their own updates in both the trunk and the maintenance branch, where there are essentially two copies of each file.  Many teams are handling this quite well.&lt;br /&gt;&lt;br /&gt;Me, like &lt;a href="http://victorian.fortunecity.com/russell/105/sven1sm.jpg"&gt;an idiot&lt;/a&gt;, did a blanket merge from the HEAD which caused all kinds of conflicts in files I can't read.  So resolving those conflicts -- which must be done manually -- is basically like playing "pet the kitty" with the one evil cat of ours that is laying on my shoulders.  It's all nice and fine while she's quiet, but at some point she'll expose some tendons and then the fun (and blood) will start.  At some point in the conflict resolution, I'll delete the wrong block and screw up the hard work of other dedicated volunteers.&lt;br /&gt;&lt;br /&gt;That sucks the most, because I know everyone's overworked, and my translators do a great job solely on a volunteer basis.  I just hate to screw them over as thanks for a hard job well done, y'know?&lt;br /&gt;&lt;br /&gt;I have some ideas on how to do this better, and plan on investigating &lt;a href="http://www.iro.umontreal.ca/contrib/po/HTML/"&gt;The Translation Project&lt;/a&gt; to make our lives easier.  I actually think &lt;a href="http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/TranslationServiceInterface"&gt;Zope could come to the rescue here&lt;/a&gt;,  but it now looks like I won't be working on that any time soon.  So, like Kirk, I mostly just sit in agony in this chair, with one tiny part of my brain quite happy to watch the lights and enjoy the writhing of the body that surrounds me, hoping that eventually someone will turn the dial down and stop the pain.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-7372749166988517745?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/7372749166988517745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2003/04/pain.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/7372749166988517745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/7372749166988517745'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2003/04/pain.html' title='Pain'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1388352290632479227.post-2657529739112140358</id><published>2003-04-04T23:11:00.000-05:00</published><updated>2009-01-15T23:13:26.435-05:00</updated><title type='text'>Young Again</title><content type='html'>&lt;span style="font-style:italic;"&gt;This is a repost from my earlier blog.  I totally disavow everything my younger self said.  He doesn't know what he's talking about.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So I'm blogging.  All the kids are doing it and it seems like a great way to rant and vent in a write-only forum.  I feel like I did the first time I recompiled my Linux kernel.  Once again I can put off my mid-life crisis without having to waste money on a fast car or have a divorce-inducing affair with the babysitter.  Blogging is much less likely to have an impact on anybody else in the world, and that's probably a good thing.&lt;br /&gt;&lt;br /&gt;Thanks to my colleague &lt;a href="http://www.python.org/~jeremy/weblog/index.html"&gt;Jeremy Hylton&lt;/a&gt; for finding a nice Elisp blogging tool which makes it really easy to write these things.  Expect a lot of content early on, followed by long periods of inactivity.  But no one's reading this anyway, so who cares?&lt;br /&gt;&lt;br /&gt;The main thing I've been doing lately is immersing myself in graphical &lt;a href="http://www.imap.org"&gt;IMAP&lt;/a&gt; based mail reading clients. I've been a &lt;a href="http://www.wonderworks.com/vm/"&gt;VM&lt;/a&gt; user for years, preferring of course the &lt;a href="http://www.xemacs.org/"&gt;One True&lt;/a&gt; of the One True Editors.  But lately I've been disappointed with VM, primarily because of its lack of true remote IMAP support.  I use at least 3 different desktop machines (Linux and MacOSX -- I'm Windows free!) regularly, as well as my laptop in various locations, and tunneling XEmacs over &lt;a href="http://www.openssh.org"&gt;SSH&lt;/a&gt; is just not cutting it.  VM has some support for IMAP but only by sucking all your mail over from the server to the local client, and that just defeats the whole purpose.  I might as well burn a DVD with my gig of 20 year old email so I have it with me at all times.&lt;br /&gt;&lt;br /&gt;I started out by using &lt;a href="http://www.apple.com/"&gt;Apple's&lt;/a&gt; &lt;a href="http://www.apple.com/macosx/jaguar/mail.html"&gt;Mail application for OSX&lt;/a&gt;.  I'm a huge OSX fan, so this felt like a good place to start.  On the plus side, Mail.app is nicely integrated with the OSX desktop, has very good drag-and-drop, and has a quite nice integrated spam detection system.  I've been aware of spam classifiers through my off-and-on dance with the &lt;a href="http://spambayes.sf.net"&gt;Spambayes&lt;/a&gt; project.&lt;br /&gt;&lt;br /&gt;However, Mail.app suffers from Bruised Skull Syndrome, caused by its many missing features and defects.  Chief among these are the lack of message threading and folder subscriptions, virtual foldering, and its really horrible performance at times.  It's unfortunately a lot like Apple's web browser &lt;a href="http://www.apple.com/safari/"&gt;Safari&lt;/a&gt;; really cool software that needs more baking.  I'll keep an eye on the oven and hope the cookies are moist when they come out.  Mmmhh, moist.&lt;br /&gt;&lt;br /&gt;Once again, Jeremy turned me on to a cool tool, &lt;a href="http://www.ximian.org/"&gt;Ximian's&lt;/a&gt; PIM tool called &lt;a href="http://www.ximian.org/products/evolution/"&gt;Evolution&lt;/a&gt;. Get it?  Ximian, simian, monkey icon, evolution?  Evo, as it's quaintly called by us insiders, is really excellent, even for someone like me who won't buy into the whole &lt;a href="http://www.gnome.org"&gt;Gnome&lt;/a&gt; desktop conspiracy.  For a graphical mail app, it's about my ideal.  Except for one huge, fatal flaw.  Its imap implementation is horrendous.  When it works, it's great, but it has a nasty and prolific tendency to drop its connection to the server all the time.  It helpfully reconnects automatically, after shoving annoying click-away windows which let you know it hiccuped.  I almost wouldn't care if it didn't display that annoying window.  But really, its imap implementation should be better.  As nice as Evo is, this one bug is getting to be too much so I may start looking around at other mates.&lt;br /&gt;&lt;br /&gt;The Ximian folks claim the problem is that I tunnel cleartext imap over ssh, but I don't believe it because even running Evo on my local network in the clear, I get constant drops.  And I've been tunneling XEmacs over ssh for years -- if XEmacs isn't a client sensitive to network glitches, I don't know what is (although they've gotten much better lately).  Nope, the underlying connection is solid.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.mozilla.org"&gt;Mozilla&lt;/a&gt;'s mail client, as well as its co-joined sister &lt;a href="http://www.netscape.com"&gt;Netscape&lt;/a&gt; are just too pitiful to be usable.  Enabling imap mail should be dead simple, with just a few configuration options necessary to get you started.  But no, both Moz and NS were just too hard to configure properly and I couldn't get them to talk with my imap server.  To give them a fair shot, I spent almost an hour trying to get the basic connections to work, but my impatient bastard side won out and I gave up.&lt;br /&gt;&lt;br /&gt;Ditto for &lt;a href="http://www.kde.org"&gt;KDE's&lt;/a&gt; KMail application. Admittedly though, they have newer versions that what comes with my &lt;a href="http://www.redhat.com"&gt;Redhat 7.3&lt;/a&gt; version of Linux, but I haven't spent the time to install KDE 3.1 RPMs.  I may come back to this though because Kmail had one extremely neat feature: I could use XEmacs as my external editor for composing email.  This is great because of the huge number of Emacs hacks I've got going.  I've been a heavy duty (as opposed to heavy doodie) Emacser for almost 20 years (yes, I'm a fuggin' old dinosaur) and a XEmacser/Lucid Emacser for maybe 12.  So I like that environment a lot.&lt;br /&gt;&lt;br /&gt;My netbud &lt;a href="http://tmda.sf.net"&gt;Jason Mastaler&lt;/a&gt; reminded me that &lt;a href="http://www.gnus.org"&gt;Gnus&lt;/a&gt; has an imap backend, but treating my mail like news was just a little too jarring for me. Jason also pointed me to &lt;a href="http://www.gohome.org/wl/"&gt;Wanderlust&lt;/a&gt; which I plan on taking a close look at.  I wouldn't call either of these graphical, but there's an appeal of keeping everything in XEmacs.&lt;br /&gt;&lt;br /&gt;I'm sure I've missed some, but if you know of any other decent clients for Linux or MacOSX, feel free to let me know.  But you're not reading this anyway, so I guess you won't.&lt;br /&gt;&lt;br /&gt;Okay, I've puked enough on this subject, so I'll wipe the chunks of lisp off my lips and see if I can clean myself up.  Of course, with a blog you can turn any crap into art...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1388352290632479227-2657529739112140358?l=www.wefearchange.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.wefearchange.org/feeds/2657529739112140358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.wefearchange.org/2003/04/young-again.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2657529739112140358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1388352290632479227/posts/default/2657529739112140358'/><link rel='alternate' type='text/html' href='http://www.wefearchange.org/2003/04/young-again.html' title='Young Again'/><author><name>Barry Warsaw</name><uri>http://www.blogger.com/profile/18101470219352563249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_hGUIklm9gQQ/SXNx18gZW7I/AAAAAAAAAsw/e4lwGQQAbH4/S220/birdhead134.png'/></author><thr:total>3</thr:total></entry></feed>
