<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<feed xmlns="http://www.w3.org/2005/Atom">

	<title>Planet Schooltool</title>
	<link rel="self" href="http://staging.schooltool.org/atom.xml"/>
	<link href="http://staging.schooltool.org/"/>
	<id>http://staging.schooltool.org/atom.xml</id>
	<updated>2012-02-23T04:19:04+00:00</updated>
	<generator uri="http://www.planetplanet.org/">Planet/2.0 +http://www.planetplanet.org</generator>

	<entry xml:lang="en">
		<title type="html">Converting a gnarly SVN repository to GIT: success!</title>
		<link href="http://mg.pov.lt/blog/eazysvn-git-migration-success.html"/>
		<id>http://mg.pov.lt/blog/eazysvn-git-migration-success.html</id>
		<updated>2012-02-20T20:17:00+00:00</updated>
		<content type="html">&lt;p&gt;I've received more feedback about my last night's post on &lt;a href=&quot;http://mg.pov.lt/blog/eazysvn-git-migration.html&quot;&gt;gnarly
svn to git migration&lt;/a&gt; than I've expected.  Thanks to that feedback
(and, mostly, Raffaele Salmaso for doing almost all the work and emailing the
result to me) &lt;a href=&quot;https://github.com/mgedmin/eazysvn&quot;&gt;eazysvn is now on
  GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The rest of this post will describe the conversion (and verification)
in detail, because if I ever need to do this again, I do not want to start
from scratch.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/blog/eazysvn-git-migration-success.rss&quot;&gt;Continue reading this post...&lt;/a&gt;&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Converting a gnarly SVN repository to GIT: FAIL.</title>
		<link href="http://mg.pov.lt/blog/eazysvn-git-migration.html"/>
		<id>http://mg.pov.lt/blog/eazysvn-git-migration.html</id>
		<updated>2012-02-19T21:13:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/eazysvn/&quot;&gt;eazysvn&lt;/a&gt; lives in a Subversion
repository.  I want to bring it (kicking and screaming) into the 21st century
and put it on Github.&lt;/p&gt;

&lt;p&gt;git-svn is unsuitable for the conversion, because in revision 50 I moved
/ to /trunk and added the traditional /tags and /branches.  With git-svn I
either get one third of the history that ignores everything before the layout
switch, or I get directories named 'trunk', 'tags' and 'branches'.&lt;/p&gt;

&lt;p&gt;Then I thought maybe hg would be smarter about the conversion, and then I
could use hg-fast-export to convert hg to git.  I enabled the hgsubversion
extension:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;sudo apt-get install hgsubversion&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;echo '[extensions'] &amp;gt;&amp;gt; ~/.hgrc&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;echo 'hgsubversion =' &amp;gt;&amp;gt; ~/.hgrc&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;(blog posts like this are a good reason why hg ought to steal the 'git
config --global foo.bar=baz' syntax from git).&lt;/p&gt;

&lt;p&gt;Then I converted the svn repository to Mercurial: &lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;hg clone svn+ssh://fridge/home/mg/svn/eazysvn eazysvn-hg&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;hg log -p &lt;del&gt;confirmed that hg handled the conversion nicely&lt;/del&gt; looked
right-ish at first glance, except the author information was nonsensical.  To
fix that:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;rm -rf eazysvn-hg&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;echo 'mg = Marius Gedminas &amp;lt;marius@gedmin.as&amp;gt;' &amp;gt; AUTHORS&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;hg clone svn+ssh://fridge/home/mg/svn/eazysvn eazysvn-hg -A AUTHORS&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Unfortunately, a closer look at hg log now shows that two thirds of the
history is lost: hg ignored everything before the layout restructuring, despite
printing the log messages of those revisions as it went about the conversion.
*sigh*.&lt;/p&gt;

&lt;p&gt;Dear lazyweb, surely svn layout reorganization can't be such a rare thing
that no tools in existence support it?  What should I try next?&lt;/p&gt;

&lt;p&gt;P.S. I also tried Bazaar, to see what it would do:&lt;/p&gt;
&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr branch svn+ssh://fridge/home/mg/svn/eazysvn eazysvn-bzr&lt;/span&gt;
Repository with UUID 4fc293c4-4eed-0310-a01a-b4ad72f90fad at svn+ssh://fridge/home/mg/svn/eazysvn contains fewer revisions than cache. This either means that this repository contains an out of date mirror of another repository (harmless), or that the UUID is being used for two different Subversion repositories (potential repository corruption).
bzr: ERROR: exceptions.KeyError: 'missing revision paths for 78'

Traceback (most recent call last):
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/commands.py&quot;, line 946, in exception_to_return_code
    return the_callable(*args, **kwargs)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/commands.py&quot;, line 1150, in run_bzr
    ret = run(*run_argv)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/commands.py&quot;, line 699, in run_argv_aliases
    return self.run(**all_cmd_args)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/commands.py&quot;, line 721, in run
    return self._operation.run_simple(*args, **kwargs)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/cleanup.py&quot;, line 135, in run_simple
    self.cleanups, self.func, *args, **kwargs)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/cleanup.py&quot;, line 165, in _do_with_cleanups
    result = func(*args, **kwargs)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/builtins.py&quot;, line 1263, in run
    from_location)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/bzrdir.py&quot;, line 919, in open_tree_or_branch
    return bzrdir._get_tree_branch()
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/controldir.py&quot;, line 410, in _get_tree_branch
    branch = self.open_branch(name=name)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/remote.py&quot;, line 420, in open_branch
    branch_path = self._determine_relpath(name)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/remote.py&quot;, line 369, in _determine_relpath
    layout = repos.get_layout()
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/repository.py&quot;, line 701, in get_layout
    return self.get_layout_source()[0]
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/repository.py&quot;, line 720, in get_layout_source
    self._find_guessed_layout(self.get_config())
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/repository.py&quot;, line 743, in _find_guessed_layout
    revnum, self._hinted_branch_path)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/layout/guess.py&quot;, line 143, in repository_guess_layout
    return logwalker_guess_layout(repository._log, revnum, branch_path=branch_path)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/layout/guess.py&quot;, line 149, in logwalker_guess_layout
    logwalker.iter_changes(None, revnum, max(0, revnum-GUESS_SAMPLE_SIZE)), revnum, branch_path)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/layout/guess.py&quot;, line 104, in guess_layout_from_history
    for (revpaths, revnum, revprops) in changed_paths:
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/logwalker.py&quot;, line 60, in iter_all_changes
    revpaths = get_revision_paths(revnum)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/logwalker.py&quot;, line 295, in get_revision_paths
    return self.cache.get_revision_paths(revnum)
  File &quot;/usr/lib/python2.7/dist-packages/bzrlib/plugins/svn/cache/tdbcache.py&quot;, line 187, in get_revision_paths
    raise KeyError(&quot;missing revision paths for %d&quot; % revnum)
KeyError: 'missing revision paths for 78'

You can report this problem to Bazaar's developers by running
    apport-bug /var/crash/bzr.1000.2012-02-19T22:12.crash
if a bug-reporting window does not automatically appear.

&lt;/pre&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">N9 Hackathon in Vienna</title>
		<link href="http://mg.pov.lt/blog/n9-hackathon.html"/>
		<id>http://mg.pov.lt/blog/n9-hackathon.html</id>
		<updated>2011-10-12T11:25:00+00:00</updated>
		<content type="html">&lt;p&gt;Last weekend I attended the &lt;a href=&quot;https://metalab.at/wiki/N9_Hackathon&quot;&gt;N9 Hackathon&lt;/a&gt; in Vienna.
Nokia kindly sponsored all food and accommodation costs and, at the very end,
surprised me with an entirely unexpected gift of a N9 phone.&lt;/p&gt;

&lt;p&gt;Vienna: great transportation system, delicious food (either that, or I was
always extremely hungry when I ate), huge portions, restaurants open until
midnight.  Shame I didn't have time to see the city itself.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://swipe.nokia.com/&quot;&gt;N9&lt;/a&gt; is a gorgeous phone; much more
so in real life than in pictures.&lt;/p&gt;

&lt;p&gt;After some hassle upgrading the &lt;a href=&quot;http://qt.nokia.com/downloads/&quot;&gt;Qt
SDK&lt;/a&gt; (the provided upgrade tool managed to somehow remove the Qt Creator
IDE while purporting to upgrade it; I had to reinstall the entire SDK) and
flashing &lt;a href=&quot;http://mg.pov.lt/blog/n950&quot;&gt;my N950&lt;/a&gt; with Beta 2 firmware
(Qt SDK 1.1.3 produces apps incompatible with the old Beta 1 firmware of the
N950) I started prototyping a time tracking application in &lt;a href=&quot;http://doc.trolltech.com/4.7-snapshot/qml-intro.html&quot;&gt;QML&lt;/a&gt;,
while learning QML and the &lt;a href=&quot;https://www.developer.nokia.com/swipe/ux/pages/building_blocks.html&quot;&gt;N9
design guidelines&lt;/a&gt; at the same time.&lt;/p&gt;

&lt;p&gt;Converting the pretty pictures into QML was harder than I expected, but at
the end of the second day I had &lt;a href=&quot;http://github.com/mgedmin/qml-time-tracker&quot;&gt;something&lt;/a&gt; that looked
like a native N9 application.&lt;/p&gt;

&lt;div&gt;
&lt;a href=&quot;http://mg.pov.lt/qml-timetracker-prototype.png&quot; title=&quot;click for full size image&quot;&gt;&lt;img src=&quot;http://mg.pov.lt/qml-timetracker-prototype.png&quot; alt=&quot;screenshot of the prototype&quot; width=&quot;306&quot; height=&quot;306&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Most useful reference pages were:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The &lt;a href=&quot;http://doc.trolltech.com/4.7-snapshot/qdeclarativeintroduction.html&quot;&gt;QML
    syntax introduction&lt;/a&gt; (which felt incomplete, but was almost adequate in the end).&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;http://harmattan-dev.nokia.com/docs/library/html/qt-components/qt-components-meego-componentlist.html?tab=1&quot;&gt;list of Harmattan-specific QML components&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;http://harmattan-dev.nokia.com/docs/library/html/qt4/qdeclarativeelements.html?tab=1&quot;&gt;list of standard QML components&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;https://www.developer.nokia.com/swipe/ux/pages/building_blocks.html&quot;&gt;UI
    building blocks pages&lt;/a&gt; mentioned above (pretty pictures! pretty colours! I &lt;em&gt;like&lt;/em&gt; shiny things!).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://harmattan-dev.nokia.com/docs/library/html/qt-components/qt-components-meego-interfaceguide.html&quot;&gt;Harmattan
    Qt Components User Interface Guidelines&lt;/a&gt;: pixel and font sizes of the
    standard UI elements.  (Ignore the &quot;import UIConstants.js&quot; red herrings;
    it's an internal thing &lt;em&gt;apparently&lt;/em&gt;, and you can't use it
    directly from your 3rd-party apps.  Unless you find and copy UIConstants.js
    into your project, after figuring out if the licence allows it, which
    seemed too much of a hassle for me to even start.  So I hardcoded all
    the numbers directly, like a bad programmer who doesn't know about
    constants.)&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;http://harmattan-dev.nokia.com/docs/library/html/qt-components/qt-components-meego-simpletutorial.html?tab=1&quot;&gt;TutorialApplication&lt;/a&gt;
      sample, finding the sources of which was unexpectedly &lt;em&gt;difficult&lt;/em&gt;
      -- a straight git clone of the &lt;a href=&quot;http://qt.gitorious.org/qt-components/qt-components&quot;&gt;qt-components
      repository&lt;/a&gt; gives you something too recent to run with the older
      qt-components version on the N9.  I ended up using apt-get source
      qt-components in Scratchbox to download the &lt;a href=&quot;http://harmattan-dev.nokia.com/pool/harmattan-beta/free/q/qt-components/qt-components_1.0~git20110525-1+0m6.tar.gz&quot;&gt;source
      tarball&lt;/a&gt; of version 1.0~git20110525-1+0m6.  Look in
      qt-components/examples/meego/.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, workflow.  QML is parsed at run time (application startup time,
unless you delay the loading), which means no recompilation ought to be
required to make changes, which means short development feedback cycles ought
to be possible.  So I was not happy about having to wait several seconds after
hitting Run in Qt Creator, while it built a .deb, copied it to the device over
wifi or USB networking, installed and ran it there.  Deploying to the Qt
Simulator is quicker, but not as much as I think it ought to be.  Plus, the
Qt Simulator apparently cannot simulate the landscape mode of the N9,
&lt;em&gt;and&lt;/em&gt; it lies about the default font size of QML Text elements (if you
do not specify a pixelSize, text elements will look all right in the simulator,
but ridiculously tiny on the N9).&lt;/p&gt;

&lt;p&gt;In the end I cobbled up a &lt;a href=&quot;https://github.com/mgedmin/qml-time-tracker/blob/master/quicktest&quot;&gt;shell
script&lt;/a&gt; that rsyncs my updated QML files to the device and runs a short
&lt;a href=&quot;https://github.com/mgedmin/qml-time-tracker/blob/master/quicktest.py&quot;&gt;Python
script&lt;/a&gt; (over ssh) to launch them.  You need rsync and PySide installed on
the device for this, obviously, as well as having
SSH set up for passwordless logins.  As a bonus, I can now do QML development
during lunch, directly on the device, with &lt;a href=&quot;http://mg.pov.lt/770/dists/harmattan/user/binary-armel/vim_7.3.260-1_armel.deb&quot;&gt;vim&lt;/a&gt;,
enjoying proper &lt;a href=&quot;http://gitorious.org/qt-qml-demo-playground/qt-qml-demo-playground/blobs/raw/master/qml.vim&quot;&gt;syntax
highlighting&lt;/a&gt;.
:)&lt;/p&gt;

&lt;p&gt;Oh, and my code is &lt;a href=&quot;http://github.com/mgedmin/qml-time-tracker/&quot;&gt;up
on Github&lt;/a&gt;.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Crackbook</title>
		<link href="http://blog.miliauskas.lt/2011/08/crackbook.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-5275117127671273593</id>
		<updated>2011-08-31T01:27:14+00:00</updated>
		<content type="html">&lt;div class=&quot;separator&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-drJ3dB4v4Xc/Tl1UvdKsYEI/AAAAAAAAATE/tD08be-ewW8/s1600/Screen%2Bshot%2B2011-08-30%2Bat%2B23.03.05.png&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;http://1.bp.blogspot.com/-drJ3dB4v4Xc/Tl1UvdKsYEI/AAAAAAAAATE/tD08be-ewW8/s400/Screen%2Bshot%2B2011-08-30%2Bat%2B23.03.05.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;
Shortly before starting my job at Google, I had invested a little time into writing a Chrome extension called &lt;a href=&quot;https://chrome.google.com/webstore/detail/nbgjmohekjolcgemlolblankocjlgalf&quot;&gt;Crackbook&lt;/a&gt;. It helps against wasting time on the web by delaying access to selected sites (see this &lt;a href=&quot;http://xkcd.com/862/&quot;&gt;XKCD cartoon&lt;/a&gt; for an illustration, and check out the hint too). Because access is just delayed rather than blocked, you are less likely to just disable the tool after a while, which is exactly what happened to the other tools I tried to use.&lt;/p&gt;

&lt;p&gt;
Having found a little free time in the evenings, I have just updated the extension. If you use Chrome, please &lt;a href=&quot;https://chrome.google.com/webstore/detail/nbgjmohekjolcgemlolblankocjlgalf&quot;&gt;try it&lt;/a&gt; and give feedback!&lt;/p&gt;

&lt;p&gt;
The extension also collects anonymous statistics on what domains people tend to mark as junk and how often the domains are hit. Some very basic results are available at &lt;a href=&quot;http://crackbook.info/&quot;&gt;crackbook.info&lt;/a&gt;. Now that a fair amount of data has been collected, a deeper statistical inspection is in the plans. Stay tuned.
&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-5275117127671273593?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Porting FBReader to Meego 1.2 Harmattan</title>
		<link href="http://mg.pov.lt/blog/harmattan-fbreader.html"/>
		<id>http://mg.pov.lt/blog/harmattan-fbreader.html</id>
		<updated>2011-07-29T00:16:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://wiki.meego.com/User:Fiferboy&quot;&gt;Andrew Olmsted&lt;/a&gt; built
the first &lt;a href=&quot;http://www.fbreader.org&quot;&gt;FBReader&lt;/a&gt; packages for Harmattan, after &lt;a href=&quot;http://mg.pov.lt/fiferboy-fbreader-harmattan.patch&quot;&gt;tweaking the build
system&lt;/a&gt; a bit.  The desktop version of FBReader already used Qt 4, and
ran almost unmodified, but with some bugs (&lt;a href=&quot;http://pastie.org/2238548&quot;&gt;segfault&lt;/a&gt; on task switch) and ugly
UI.&lt;/p&gt;

&lt;p&gt;I started with the Ubuntu packages for FBReader, since they used a more
sane build system for .debs (compared to upstream's &lt;a href=&quot;https://github.com/geometer/FBReader/blob/master/build_packages.sh&quot;&gt;funky
shell script&lt;/a&gt;).  Some tweaks were needed to make it build in Scratchbox:
since GTK+ and Hildon libraries aren't available on Harmattan, I had to disable
the building of -gtk and -maemo versions of libzlui.  I also got to learn
a new tool — &lt;a href=&quot;http://wiki.debian.org/UsingQuilt&quot;&gt;quilt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fixing the &lt;a href=&quot;http://pastie.org/2281152&quot;&gt;segfault&lt;/a&gt; took a couple of days of &lt;a href=&quot;http://pastie.org/2281247&quot;&gt;debugging&lt;/a&gt;, studying the &lt;a href=&quot;https://github.com/geometer/FBReader/blob/master/zlibrary/ui/src/qt4/view/ZLQtViewWidget.cpp#L97&quot;&gt;source&lt;/a&gt;
&lt;a href=&quot;https://github.com/geometer/FBReader/blob/master/zlibrary/ui/src/qt4/view/ZLQtPaintContext.cpp#L47&quot;&gt;code&lt;/a&gt;
of both FBReader and Qt itself, and asking for help on IRC.  Turns out
FBReader was holding an active QPainter instance for too long, and its backing
pixmap got destroyed (or, rather, converted from an OpenGL texture to a plain
X11 pixmap) during a task switch, causing the crash.  I'm probably describing
this wrong BTW, but, in any case, adding QPainter::begin() and QPainter::end()
calls in the paintEvent handler fixed the segfault.&lt;/p&gt;

&lt;p&gt;Next, a small tweak in the .desktop file to make FBReader a single-instance
application: change &lt;tt&gt;Exec=FBReader&lt;/tt&gt; to &lt;tt&gt;Exec=single-instance
  /usr/bin/FBReader&lt;/tt&gt; (I'm paraphrasing slightly).&lt;/p&gt;

&lt;p&gt;Then, a more ambitious goal: making FBReader intercept volume keys and
use them for scrolling.  Google gave me a &lt;a href=&quot;http://www.developer.nokia.com/Community/Discussion/showthread.php?226283-Grab-Volume-Keys-on-Harmattan&quot;&gt;pointer&lt;/a&gt;
to &lt;a href=&quot;http://apidocs.meego.com/1.2/qmsystem/classMeeGo_1_1QmKeys.html&quot;&gt;QmKeys&lt;/a&gt;, which was the
wrong API to use here, but gave me a lead to qmkeyd2, which appears to be an
&lt;a href=&quot;https://www.meego.gitorious.org/meego-middleware/qmsystem/blobs/5edeec3815de0a2cb81e305e504f072460efe30d/keyd/qmkeyd.cpp&quot;&gt;open
source&lt;/a&gt; daemon, which gave me a lead to sysuid, another &lt;a href=&quot;https://meego.gitorious.org/meegotouch/meegotouch-systemui/blobs/master/src/extensions/volume/volumebarlogic.cpp&quot;&gt;open
source&lt;/a&gt; daemon, which in turn gave me a lead to &lt;a href=&quot;http://harmattan-dev.nokia.com/unstable/beta/api_refs/showdoc.php?pkn=libresourceqt&amp;wb=daily-docs&amp;url=Li94bWwvZGFpbHktZG9jcy9saWJyZXNvdXJjZXF0&quot;&gt;libresourceqt&lt;/a&gt;,
and that was the right API at last.&lt;/p&gt;

&lt;p&gt;Volume keys generate regular key events for XF86AudioRaiseVolume and
XF86AudioLowerVolume, but they're also intercepted by qmkeyd2, which tells
all subscribers (and sysuid is one) about them.  Which subscriber gets to
react is determined by the resource policy framework.  So what I needed to do
in FBReader was acquire the ScaleButtonResource when FBReader starts up or gets
focus, and release it when FBReader quits or goes into background.  That
also required some IRC help until I discovered &lt;a href=&quot;http://doc.qt.nokia.com/latest/qobject.html#installEventFilter&quot;&gt;installEventFilter()&lt;/a&gt;
and the &lt;a href=&quot;http://doc.qt.nokia.com/latest/qevent.html#Type-enum&quot;&gt;ApplicationActivate/ApplicationDeactivate&lt;/a&gt;
events. And &lt;a href=&quot;http://doc.qt.nokia.com/latest/qcoreapplication.html#instance&quot;&gt;QApplication::instance()&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The various tools available in the developer firmware were invaluable:
openssh, gdb, valgrind, strace, xev, xprop, lsof, netstat.  Also, I would not
have achieved my second goal without being able to look at the sources of Meego
system components (qmkeyd, sysuid).  Yay open source!&lt;/p&gt;

&lt;p&gt;Here are &lt;a href=&quot;http://mg.pov.lt/fbreader-0.12.10dfsg-1ubuntu2mg9-harmattan.patch&quot;&gt;my
changes to the source code&lt;/a&gt;.  You can find my modified &lt;a href=&quot;http://mg.pov.lt/770/dists/harmattan/experimental/source/fbreader_0.12.10dfsg-1ubuntu2mg9.diff.gz&quot;&gt;Debian packaging
files&lt;/a&gt;, as well as &lt;strong&gt;prebuilt binary packages&lt;/strong&gt; (with full
debug info, for gdb goodness), in my &lt;a href=&quot;http://mg.pov.lt/770/&quot;&gt;experimental harmattan apt repository&lt;/a&gt;.
The UI is still ugly and non-native, but it doesn't matter much in fullscreen
mode &lt;tt&gt;:)&lt;/tt&gt; .&lt;/p&gt;

&lt;p&gt;Note to self: when next building fbreader, make sure the 2 megabyte
&lt;tt&gt;tags&lt;/tt&gt; file doesn't end up in the &lt;tt&gt;.diff.gz&lt;/tt&gt;.  And speaking of crud
in source packages, the &lt;a href=&quot;http://mg.pov.lt/770/dists/harmattan/user/binary-armel/vim_7.3.260-1_armel.deb&quot;&gt;vim
package&lt;/a&gt; I built for Harmattan the other day contains the entire 50 meg
&lt;tt&gt;.hg&lt;/tt&gt; in the &lt;tt&gt;.orig.tar.gz&lt;/tt&gt;.  I need to figure out how to
tell dh_make to omit it.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Nokia N950</title>
		<link href="http://mg.pov.lt/blog/n950.html"/>
		<id>http://mg.pov.lt/blog/n950.html</id>
		<updated>2011-07-19T12:44:00+00:00</updated>
		<content type="html">&lt;p&gt;Last Thursday I received a package containing something called the &lt;a href=&quot;http://wiki.maemo.org/N950&quot;&gt;Nokia N950&lt;/a&gt; development kit.  Sweet sweet
hardware, shame it's not going to be sold to end users.  The software is
visibly an unfinished pre-release version, but shows great potential.  There
are almost no 3rd-party apps, which is why Nokia is loaning these N950s to
random developers.&lt;/p&gt;

&lt;p&gt;I intend to port &lt;a href=&quot;http://mg.pov.lt/gtimelog/&quot;&gt;GTimeLog&lt;/a&gt; to it.
Although my more immediate need is to have &lt;a href=&quot;http://www.fbreader.org/&quot;&gt;FBReader&lt;/a&gt;, so that I can stop carrying both
this one and my N900 with me everywhere.  Also, &lt;a href=&quot;http://www.vim.org/&quot;&gt;vim&lt;/a&gt; would be nice.&lt;/p&gt;

&lt;p&gt;I've already &lt;a href=&quot;http://pastie.org/2218247&quot;&gt;hacked up&lt;/a&gt; Lithuanian
support to the virtual and hardware keyboards, thanks to the very nice design
of &lt;a href=&quot;http://wiki.meego.com/Maliit&quot;&gt;Maliit&lt;/a&gt;.  As a comparison, I've
had my N900 for a year and a half, and I still can't type Lithuanian on it.
XKB is not fun.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Amazon Kindle 3</title>
		<link href="http://blog.miliauskas.lt/2011/04/amazon-kindle-3.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-6883321890316002583</id>
		<updated>2011-04-02T21:13:02+00:00</updated>
		<content type="html">For the past couple years I had been reading very little, two or three books a year.&lt;br /&gt;
&lt;br /&gt;
For the past month my average has been two books per &lt;i&gt;week&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
The culprit is the &lt;a href=&quot;http://amazon.com/Kindle&quot;&gt;Amazon Kindle&lt;/a&gt;&amp;nbsp;3 I bought during my stay in the US. I just can not recommend it enough. For starters, it is quite affordable at $139. The image quality is wonderful, and reading in daylight or even in direct sunlight is pleasant. This is a welcome change from a backlit screen as the eyes get noticeably less strained. The format of the device is even more convenient than of a real book (the size is perfect for plain text, start thinking about the Kindle DX if and only if you intend to read PDFs). The Kindle is quite thin and convenient to hold (and you do not need to keep it from closing as with paperback bindings). Battery life is on the order of weeks. Extra functionality (e.g., web browsing) is available, but not convenient, but that is almost an advantage as distractions are kept at bay.&amp;nbsp;The Amazon store is great, I have already shelled out over $50 with little remorse (my time is much more expensive than the measly $9.99 a typical book costs). There are quite a few free books around too. And to top it off, the &quot;screensaver&quot; with pictures of writers is a very nice touch.&lt;br /&gt;
&lt;br /&gt;
The Kindle is also useful for going through longer articles you would normally be reading on your laptop. The Chrome extension&amp;nbsp;&lt;a href=&quot;https://chrome.google.com/webstore/detail/ipkfnchcgalnafehpglfbommidgmalan&quot;&gt;Send to Kindle&lt;/a&gt;&amp;nbsp;has worked well for me, do check it out.&lt;br /&gt;
&lt;br /&gt;
The most important drawback of the Kindle is that it is slow to turn pages, so it is not easy to browse a book. Turning a page takes a second or so. This is extremely annoying when reading in non-linearly, e.g. taking in study material, when you constantly need to go back to check up details of previous material. A PDF interpreter is available, but the screen is too small to show a full PDF page (a Kindle DX or an iPad would probably be better) and scrolling is painful because of the delays. Wireless seems to drain the battery noticeably, there have been a few cases where I forgot to turn it off and found a dead Kindle a few days later. I wish the WiFi connection would manage itself intelligently somehow.&lt;br /&gt;
&lt;br /&gt;
The Kindle drove the point home for me that &lt;b&gt;dead-tree books will be going the way of vinyl soon&lt;/b&gt;, much sooner than I had expected. And for good reasons. Go order now if you do not have an e-book reader yet (and do not forget to order a sleeve too, given the time you will be spending carrying the device it will come in very handy).&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-6883321890316002583?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Google Munich</title>
		<link href="http://blog.miliauskas.lt/2011/03/google-munich.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-5121693152361589566</id>
		<updated>2011-03-16T14:57:51+00:00</updated>
		<content type="html">It looks like I have made it through most of the hurdles of the Google hiring process, and I should be starting my new job at Google's Munich office soon. Now I just need to haul my stuff to Munich and get the paperwork done. It sure looks like this is going to be a very interesting year.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-5121693152361589566?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Trip to Bay Area coming to an end</title>
		<link href="http://blog.miliauskas.lt/2011/03/trip-to-san-francisco-coming-to-end.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-2763746172232389398</id>
		<updated>2011-03-06T04:37:46+00:00</updated>
		<content type="html">My trip to the Bay Area is coming to the end. It has been surprisingly productive. Here's some things I have done in the nearly two weeks I have been here:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;got acquainted with San Francisco&lt;/li&gt;
&lt;li&gt;interviewed for a job at a startup&lt;/li&gt;
&lt;li&gt;visited Stanford University &amp;amp; Berkeley University campuses&lt;/li&gt;
&lt;li&gt;visited Google Mountain View and San Francisco offices&lt;/li&gt;
&lt;li&gt;hanged out with folks from Google, from Twitter and from some very promising startups, also a Stanford professor, a researcher from Berkeley and a Berkeley undergrad student, among others&lt;/li&gt;
&lt;li&gt;hanged out with people from &lt;a href=&quot;http://singinst.org/&quot;&gt;The Singularity Institute for Artificial Intelligence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;spent a day biking in the Golden Gate National Recreation Area&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
While I am getting a little travel-weary, I know I will be sad leaving this place.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot;&gt;
&lt;a href=&quot;https://lh5.googleusercontent.com/-Al85QxVXogg/TXLxuMdCmOI/AAAAAAAAAQI/7_jFdtcrVl0/s1600/IMG_0027.JPG&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://lh5.googleusercontent.com/-Al85QxVXogg/TXLxuMdCmOI/AAAAAAAAAQI/7_jFdtcrVl0/s320/IMG_0027.JPG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ul&gt;&lt;/ul&gt;
&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-2763746172232389398?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Off to San Francisco!</title>
		<link href="http://blog.miliauskas.lt/2011/02/off-to-san-francisco.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-1361774250494296303</id>
		<updated>2011-02-23T04:01:05+00:00</updated>
		<content type="html">The interview at Munich seemed to go well. Well, at least, I had fun. We'll see how that turns out.&lt;br /&gt;
&lt;br /&gt;
For now, I'm off again for another job interview, this time to Palo Alto. This will be my first time to the West Coast, so I have postponed the return flight for two weeks to familiarize myself with the proverbial area. If anyone's from around the San Francisco Bay Area, I would be very happy to meet over lunch/dinner/beer!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-1361774250494296303?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Interviewing with Google</title>
		<link href="http://blog.miliauskas.lt/2011/02/interviewing-with-google.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-2207269488605548042</id>
		<updated>2011-02-16T08:24:09+00:00</updated>
		<content type="html">I somehow made it through Google's phone interviews in one piece, and&amp;nbsp;now they are flying me in for an on-site interview in Munich (Germany), which will take place tomorrow. Keep your fingers crossed for me!&lt;br /&gt;
&lt;br /&gt;
I will be landing in Munich in a few hours, and today I am free to look around the city. Anyone from here up for lunch or a beer?&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-2207269488605548042?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Lithuanian (AltGr) keyboard for Windows</title>
		<link href="http://blog.miliauskas.lt/2010/11/lithuanian-altgr-keyboard-for-windows.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-8892080239571135564</id>
		<updated>2010-12-19T22:59:43+00:00</updated>
		<content type="html">In GNU/Linux I usually use an AltGr-based keyboard layout for entering Lithuanian characters. That is, you can enter Lithuanian diacritics by holding down AltGr (right Alt)). I had lived with separate modes for entering English and Lithuanian until I found out that having a single layout was a &lt;b&gt;huge &lt;/b&gt;relief.&lt;br /&gt;
&lt;br /&gt;
Windows does ship with a Lithuanian layout where AltGr switches to English characters, but I use the English layout much more, so I need it the other way around. So, I grabbed Microsoft's Keyboard Layout Creator and made the layout I needed. The result is available on a GitHub&amp;nbsp;&lt;a href=&quot;http://github.com/gintas/LitAltGr&quot;&gt;repository&lt;/a&gt;. You may also &lt;a href=&quot;https://github.com/gintas/LitAltGr/raw/master/LitAltGr.zip&quot;&gt;download the installer directly&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
In Linux, keymaps, being plain text files, are more transparent, but to be fair, in this case the Windows way wins. Not only do you get a GUI tool to create the layout, but also an installer can be generated automatically for deployment of the layout.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-8892080239571135564?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Mobile App Camp</title>
		<link href="http://blog.miliauskas.lt/2010/12/mobile-app-camp.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-8579862428660225936</id>
		<updated>2010-12-19T19:13:00+00:00</updated>
		<content type="html">On the last weekend my team and I participated in the Mobile App Camp (&lt;a href=&quot;http://www.omnitel.lt/dirbtuves&quot;&gt;link in Lithuanian&lt;/a&gt;) organized by &lt;a href=&quot;http://www.omnitel.lt/&quot;&gt;Omnitel&lt;/a&gt;,&amp;nbsp;which is one of the dominant mobile operators in Lithuania.&amp;nbsp;The event seems to be part of Omnitel's push for increasing the share of smartphones in the Lithuanian market, which has been lagging behind the European trends.&lt;br /&gt;
&lt;br /&gt;
Our team consisted of Povilas Kytra, who is behind the &lt;a href=&quot;http://www.tv.lt/&quot;&gt;TV.LT&lt;/a&gt; project, Mantas Kanaporis from &lt;a href=&quot;http://www.again.lt/en&quot;&gt;A-Gain&lt;/a&gt;&amp;nbsp;and me. In the weekend we built an &lt;a href=&quot;http://m.tv.lt/&quot;&gt;app&lt;/a&gt; that shows the TV programme for the coming day for all the Lithuanian TV channels. (The app is not yet available on the Android Market, but we are working on it.)&lt;br /&gt;
&lt;br /&gt;
Here's a screenshot of the main screen of the application:&lt;br /&gt;
&lt;div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/_zn_T2bmMZn0/TQ1JdYXcxMI/AAAAAAAAAOs/tkVoO3nEIRE/s1600/tvltapp.png&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://1.bp.blogspot.com/_zn_T2bmMZn0/TQ1JdYXcxMI/AAAAAAAAAOs/tkVoO3nEIRE/s320/tvltapp.png&quot; width=&quot;212&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
The app was built using the standard Android Development Toolkit on Eclipse. The app gets the content from a &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;Rails&lt;/a&gt;-based server containing a simple database and couple JSON views.&lt;br /&gt;
&lt;br /&gt;
I had some experience of developing for Android before, but it was mostly about working with graphics on canvas, while in this app we used some standard GUI controls (with some nifty styling).&lt;br /&gt;
&lt;br /&gt;
For the source control, we used a private repository on &lt;a href=&quot;http://bitbucket.org/&quot;&gt;bitbucket.org&lt;/a&gt;. That one was a huge letdown: a 'hg push' or 'hg pull' would take ages (or at least that's how it seemed to me in comparison to &lt;a href=&quot;http://www.github.com/&quot;&gt;GitHub&lt;/a&gt;), and we had no end of trouble with merging, partly due to the number of commands needed to get the repositories in sync (hg pull; hg update; hg merge; hg commit; hg push). Even &lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;Subversion &lt;/a&gt;would probably have worked better.&lt;br /&gt;
&lt;br /&gt;
The event itself was great fun. It had been a while since I had last coded intensively for the entire weekend. There were quite a few decent ideas presented by the participants, and some of them were successfully implemented.&lt;br /&gt;
&lt;br /&gt;
The rating system was somewhat disappointing though. The event was supposed to be a contest, with four predefined criteria for winning apps (still available on the website): uniqueness in the Lithuanian market, magnitude of the target group, value provided to the user and creativity. In the end, however, the jury nominated apps for three different awards (best app built on an existing database, best app built anew, and the &quot;hope&quot; nomination) with one app awarded from each category. Our app scored second in the first nomination, so we did not get an award, even though we would probably have been in the global top three, were the original criteria upheld.&lt;br /&gt;
&lt;br /&gt;
To be fair, we did not stand much chance against the winner in our category, an app based on &lt;a href=&quot;http://vaistai.lt/&quot;&gt;vaistai.lt&lt;/a&gt;, which sported a database of pharmaceuticals with detailed usage instructions, information about drug stores in Lithuania with maps and inventory status, and even a barcode scanner. Hats off to them. Another winner was &lt;a href=&quot;http://www.appbrain.com/app/alaus-radaras/alaus.radaras&quot;&gt;&quot;Alaus radaras&quot;&lt;/a&gt; (&quot;Beer radar&quot;) with locations of local beer bars and inventory info. The third one was &quot;3 milijonai teisėjų&quot; (Three million judges&quot;), which, as far as I understood, was a conception for a basketball-throwing game (basketball is very big in Lithuania, it is a second national religion).&lt;br /&gt;
&lt;br /&gt;
To conclude, it was a fun event and I wish we will be having more of those in Vilnius, even though the Monday after the long weekend was &lt;i&gt;very &lt;/i&gt;unproductive.&lt;/div&gt;
&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-8579862428660225936?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Stuff I've been doing recently</title>
		<link href="http://mg.pov.lt/blog/december-updates-2010.html"/>
		<id>http://mg.pov.lt/blog/december-updates-2010.html</id>
		<updated>2010-12-18T23:35:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://pypi.python.org/pypi/objgraph&quot;&gt;objgraph&lt;/a&gt; got&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://mg.pov.lt/objgraph/&quot;&gt;shiny documentation&lt;/a&gt; built with
      &lt;a href=&quot;http://sphinx.pocoo.org/&quot;&gt;Sphinx&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Python 3.x support, thanks to Stefano Rivera.&lt;/li&gt;
  &lt;li&gt;Python 2.4 and 2.5 support, thanks to Daniel Blackburn.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://mg.pov.lt/objgraph/CHANGES.html&quot;&gt;assorted smaller improvements&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;http://pypi.python.org/pypi/zodbbrowser&quot;&gt;zodbbrowser&lt;/a&gt; got&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;support for all ZODB databases, not just those with a
      Zope 3/Bluebream-style root folder/local site.&lt;/li&gt;
  &lt;li&gt;the ability to cope better with broken objects (due to the way ZODB
      works, not having some of your modules on the Python pack can break
      unpickling; zodbbrowser now handles this kind of situation better).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://pypi.python.org/pypi/zodbbrowser#changes&quot;&gt;assorted smaller improvements&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;a slow but inevitable shift of focus from &quot;use it as a plugin for your
      Zope 3 app&quot; to &quot;it's a standalone tool for inspecting ZODB contents&quot;.
      (Both use cases are still supported, and will be for the foreseeable
      future.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;http://pypi.python.org/pypi/imgdiff&quot;&gt;imgdiff&lt;/a&gt; got&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;its first public release.&lt;/li&gt;
  &lt;li&gt;some experimental code to actually find and highlight the differing
      parts of the images:
      &lt;br /&gt;
      &lt;br /&gt;
      &lt;center&gt;
        &lt;img src=&quot;http://mg.pov.lt/imgdiff-highlighting.png&quot; width=&quot;739&quot; height=&quot;403&quot; alt=&quot;example of highlighted image differences&quot; /&gt;
      &lt;/center&gt;
      &lt;br /&gt;
      This works better when both images are the same size, although there's
      experimental (and somewhat buggy) code to try all possible alignments.
      I could use some help here; image processing is not something I'm
      familiar with, and &lt;a href=&quot;http://stackoverflow.com/search?q=difference+between+images&quot;&gt;searching
        StackOverflow&lt;/a&gt; didn't help beyond reminding me of the existence
      of PIL's ImageChops.difference(), which is for same-sized images only.
      Many of the results there are about comparing photos, where things like
      lighting levels matter.  What I need is a diff for computer-generated
      images, where some things may be shifted around a bit, by different
      amounts, but are essentially the same.  Are there any two-dimensional
      sequence diff algorithms?
    &lt;/li&gt;
  &lt;/ul&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Windows (III): Packaging &amp;amp; nitpicks</title>
		<link href="http://blog.miliauskas.lt/2010/12/windows-iii-packaging-nitpicks.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-5783503686715561321</id>
		<updated>2010-12-07T10:00:01+00:00</updated>
		<content type="html">(This is a part of a series of posts on my recent experience with Windows; see&amp;nbsp;&lt;a href=&quot;http://blog.miliauskas.lt/2010/11/windows-i.html&quot;&gt;Windows (I)&lt;/a&gt;&amp;nbsp;&amp;nbsp;and &lt;a href=&quot;http://blog.miliauskas.lt/2010/12/windows-ii-user-interface.html&quot;&gt;Windows (II): User Interface&lt;/a&gt;.)&lt;br /&gt;
&lt;br /&gt;
Every GNU/Linux desktop distribution hangs on a package management system as a foundation, and as a result the packaging systems are quite advanced, while Windows is stuck with those pesky installation wizards. There have been several stabs to implement a package system for Windows (see &lt;a href=&quot;http://www.logilab.org/blogentry/9861&quot;&gt;here&lt;/a&gt;), but none seem to have caught on.&lt;br /&gt;
&lt;br /&gt;
There are three main disadvantages on not having good package management: tedium of manual installation, no dependency resolution and no system-wide automatic updates. In practice they are less important than it might seem. Installation wizards are indeed tedious, but in terms of time I found them to be quick enough to get through. Moreover,&amp;nbsp;apps tend to be less specialized and more encompassing than Linux utilities, and as a result you do not need to install as many things as in Linux. For the same reason dependency resolution is not as important: there are few dependencies in general. As for automatic updates, most high-profile apps have integrated mechanisms to deal with that, however, I found that those mechanisms tended to result in nagging the user with messages. After a while I started ignoring the update notifications. I suspect that happens to many users.&lt;br /&gt;
&lt;br /&gt;
The one thing that Windows has going for it is simplicity. You download installation binaries and you run them, and that's it. Linux package systems tend to be very complicated, and if (when) they break, you will need serious sysadmin chops to deal with the problem. Also installing specific versions (either older ones, or newer ones not yet available in the distro) of specific apps/libraries can be unnecessarily complicated, and the dependency graph limits your actions. In my experience, Windows does well enough without all this complexity as long as you don't reinstall your system too often.&lt;br /&gt;
&lt;br /&gt;
As for the other complaints, I frequently run into the restriction of moving/editing files opened by another application. Coming from Linux, that one is stupidly annoying. Furthermore, it is frustrating not to be able to move inactive (or stuck) background windows. I really miss my unified filesystem namespace. Also there's quite a bit of nagging in general on Windows which I would rather do without. In the end, these are not dealbreakers though.&lt;br /&gt;
&lt;br /&gt;
In my next (and probably final) post I will discuss software development on Windows.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-5783503686715561321?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Windows (II): User Interface</title>
		<link href="http://blog.miliauskas.lt/2010/12/windows-ii-user-interface.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-5364377296666324083</id>
		<updated>2010-12-01T21:55:30+00:00</updated>
		<content type="html">(This is a part of a series of posts on my recent experience with Windows. See &lt;a href=&quot;http://blog.miliauskas.lt/2010/11/windows-i.html&quot;&gt;Windows (I)&lt;/a&gt; for the first post.)&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The Windows user interface is definitely acceptable. The charge that it is too colorful or toy-like is completely unfounded. Rather, perhaps geeks should spend less time looking at their gray Motif boxy controls. In terms of speed, the UI is generally more responsive than on Linux, though maybe less so than previous versions of Windows (that could be because my Intel video IGP is a slouch).&lt;br /&gt;
&lt;br /&gt;
An interesting observation is that apps are almost as heterogeneous in terms of interface as in GNU/Linux, even though the standard controls are ubiquitous. Even apps by Microsoft can be separated into different &quot;generations&quot; of UI (e.g., folder windows, Control Panel,&amp;nbsp;Microsoft Office). &amp;nbsp;Also it is clear that generally more attention is paid to UI and usability by app developers, although perhaps not as much as in Apple products.&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
The greatest asset and the worst offender at the same time, by far, is the overall GUI orientation of the system. Needless to say, it aids discoverability, but reduces scripting capabilities. Problem is, even if you do not need to write scripts per se, command-line actions are useful because they can be repeated and chained very easily, using shell history. In Windows, I occasionally find myself doing much repetitive clicking that would likely be an &quot;Alt-Tab Up Enter&quot; (or sometimes just one key) sequence in Linux. Moreover,&amp;nbsp;the lack of good standartized scripting is a huge pain during app deployments which tend be repetetive. I did not like Windows on servers before, and I do not like it now.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
To be fair, my complaints about scripting capabilities may be partly moot because I have only used vanilla Windows batch files, and have not looked at all into&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Windows_PowerShell&quot;&gt;Windows PowerShell&lt;/a&gt;, which is a new-generation scripting tool. The&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Windows_PowerShell#Examples&quot;&gt;examples&amp;nbsp;&lt;/a&gt;are fairly impressive. The language has a nice look and is clearly powerful, but also looks somewhat complicated which keeps me away until I find a good reason to learn it.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Initially I missed workspaces. The one app I found that was supposed to emulate workspaces would take several seconds to switch the workspace, so it was completely unusable. I learned to do without them rather quickly though. Actually I'm starting to think that using many workspaces is a sign that you are doing too many things at once and also they are an invitation to distraction (how many of you have a &quot;blog reader&quot; workspace right aside your &quot;work&quot; workspace, ready at your fingertips at a moment's notice?). Workspaces do have one killer feature: you can jump directly to a given workspace instead of cycling through windows. This is very useful when working with more than two apps, in which case without workspaces you are forced to think about the morphing Alt-Tab queue when switching windows.&lt;br /&gt;
&lt;br /&gt;
Speaking about UI generations, I much prefer the ribbon toolbars of the new Office. The still-prevalent toolbars with zillions of old-style 32x32 (or 16x16) toolbar icons are really ugly. Typically only a few of the toolbar buttons are actually useful, and they make the user interface unnecessarily cramped and busy. The move to fewer and larger toolbar buttons is definitely on the right track.&lt;br /&gt;
&lt;br /&gt;
The explorer context menus also tend to grow crazy long. Every app wants to get in there, and in the end you have a context menu that takes up half a screen vertically. Needless to say, most of those items are not used much. Sure, you can opt out during app installation, but at that time it is difficult to say how useful the context menu item will be, and there's no easy way&amp;nbsp;(i.e. easier than just ignoring the cruft)&amp;nbsp;to remove the entries afterwards.&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
In my coming posts I will cover package management and application development on Windows.&lt;/div&gt;
&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-5364377296666324083?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Windows (I)</title>
		<link href="http://blog.miliauskas.lt/2010/11/windows-i.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-4959454925153026474</id>
		<updated>2010-12-01T17:17:12+00:00</updated>
		<content type="html">I have been helping with an overdue web app project lately, and the project uses ASP.NET MVC, so I have had to use Windows for most of my day. Since I had been using GNU/Linux almost exclusively since 2003, this is quite an adventure (imagine trying out GNU/Linux after a seven year break). It is not nearly as bad as I thought it would be, even though I am using the not-so-well-liked Windows Vista which came pre-installed with my computer.&lt;br /&gt;
&lt;br /&gt;
The first thing that struck me is how much less important the OS is when compared to the situation a few years ago: a lot of the applications I depend on are web-based (GMail, Google Calendar, Google Docs, &lt;a href=&quot;http://springpadit.com/&quot;&gt;Springpad&lt;/a&gt;), and the ones that are not web-based are multiplatform and installable with a few clicks (&lt;a href=&quot;http://www.vim.org/&quot;&gt;GVim&lt;/a&gt; comes to mind). In fact, I do not think there is a single piece of software that I &lt;i&gt;really&amp;nbsp;&lt;/i&gt;missed in Windows. (An interesting corollary of this observation is that it should be equally easy to migrate to GNU/Linux nowadays.)&lt;br /&gt;
&lt;br /&gt;
The one thing where the operating system matters is hardware support, and I do not think I have to say much here. After years of whack-a-mole GNU/Linux upgrades which would fix support for one component but break another (for things as essential as video and sound), it was absolutely&amp;nbsp;&lt;i&gt;weird&lt;/i&gt;&amp;nbsp;having all hardware work properly at the same time (sound after suspend! no video glitches! high quality webcam picture!). There is no point recounting the reasons why hardware support in Linux is as it is, but now I am starting to think that Linux users do tend to suffer from a sort of Stockholm syndrome regarding hardware support; I know I did.&lt;br /&gt;
&lt;br /&gt;
The other important thing that operating systems do is resource management, and I did not have problems here either. In fact, I liked the virtual memory behaviour much better: when Windows ran out of memory (I had filled up the smallish Windows partition and there was no space left for the swap file to grow), it started rejecting malloc calls from applications, but the system was kept alive and responsive, and I could close apps and clean up the mess without much trouble. In Ubuntu, with the default settings, whenever a runaway process ate too much RAM, the system would start thrashing so hard that it would be very difficult to fix. My standard procedure (switch to text console, log in, find and kill app using command line tools) would take &lt;i&gt;minutes&lt;/i&gt; and was so annoying that I would sometimes just reset the computer instead. And in the end, even if I did not reset, an important app would possibly be killed anyway. I know there are kernel parameters for tweaking this behaviour (swappiness?), but I never got around to figuring them out as this situation does not arise that frequently, and testing is painful.&lt;br /&gt;
&lt;br /&gt;
I did not like the Windows FS security model. ACLs are much more complicated and thus less transparent that the Unix approach, even though they are more powerful. My main gripe with them is that I do not know a good way to display them easily (as with &lt;i&gt;ls -l&lt;/i&gt; in Unix). I have not had to deal with them much though.&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
I have had no stability issues. It seems that this argument should be put to rest.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Long blog posts are annoying, so I will leave the user interface, the developer experience and my complaints with the system for separate posts (edit: you can now read my &lt;a href=&quot;http://blog.miliauskas.lt/2010/12/windows-ii-user-interface.html&quot;&gt;next post&lt;/a&gt;&amp;nbsp;about the&amp;nbsp;UI).&lt;/div&gt;
&lt;ul&gt;
&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-4959454925153026474?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Verdi's Requiem</title>
		<link href="http://blog.miliauskas.lt/2010/11/verdis-requiem.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-8887693426622716260</id>
		<updated>2010-11-22T12:06:03+00:00</updated>
		<content type="html">The choir I sing in (&lt;a href=&quot;http://www.promusica.lt/&quot;&gt;Pro Musica&lt;/a&gt;) will be performing on January 22nd in Bremen, Germany. Together with two local choirs we will perform Verdi's &lt;i&gt;Requiem&lt;/i&gt;, which is absolutely fabulous. See for yourself:
&lt;br /&gt;








&lt;br /&gt;
(Also try &lt;a href=&quot;http://www.youtube.com/watch?v=pW1Uc-grcMs&quot;&gt;Solti's version&lt;/a&gt; for better sound quality, but no video.)&lt;br /&gt;
It's going to be a busy month preparing for the concert. Verdi's melodies are not complicated, but he's crazy with dynamics: I think it's the first time I've seen a quintuple pianissimo (&lt;i&gt;ppppp&lt;/i&gt;) or a quadruple fortissimo (&lt;i&gt;ffff&lt;/i&gt;) in sheet music.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-8887693426622716260?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Laptop trouble</title>
		<link href="http://blog.miliauskas.lt/2010/11/laptop-trouble.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-3110332634697172948</id>
		<updated>2010-11-21T16:48:30+00:00</updated>
		<content type="html">My trusty somewhat-old laptop has been under the weather lately. It will not boot when it's cold, and it's fairly picky. ~20 °C seems too cold already; so I have to heat it up at little.&lt;br /&gt;
&lt;div class=&quot;separator&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/_zn_T2bmMZn0/TOhUgdA-M5I/AAAAAAAAAOk/ddwB28XhNIw/s1600/IMG_0031.JPG&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://1.bp.blogspot.com/_zn_T2bmMZn0/TOhUgdA-M5I/AAAAAAAAAOk/ddwB28XhNIw/s320/IMG_0031.JPG&quot; width=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Now that winter is coming, this needs to be done almost every morning, and that is extremely annoying. Does anybody have an idea of what could be wrong? It seems that the problem is not just a loose connection, as the laptop goes up in stages:&lt;br /&gt;
&lt;br /&gt;
1) when the power button is pressed the power LED will blink for a split-second and nothing will happen,&lt;br /&gt;
2) the LED will light up for slightly longer, but the laptop still will not boot,&lt;br /&gt;
3) the laptop starts booting but shuts off spontaneously after while on the BIOS screen,&lt;br /&gt;
4) the laptop goes through the BIOS screen, but shuts down before showing the boot menu.&lt;br /&gt;
Past that, apparently the CPU generates enough heat for stable operation.&lt;br /&gt;
This is fairly complicated behaviour for a hardware problem. I wonder, maybe the power supply is at fault? Any ideas, anyone? This is a good excuse to buy a new laptop, but I would rather not splurge right before Christmas season.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-3110332634697172948?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Living a monastic life for 10 days</title>
		<link href="http://blog.miliauskas.lt/2010/09/living-monastic-life-for-10-days.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-6328269201313463577</id>
		<updated>2010-11-04T03:33:38+00:00</updated>
		<content type="html">&lt;p&gt;About a month ago, at the end of August, I finished a 10-day Vipassana meditation course. This was probably one of the more extreme activities I have ever participated in, and it's well worth a blog post.&lt;/p&gt;

&lt;p&gt;I found out about the course in a ridiculously trivial way, by following a link in a Reddit comment (I wonder if I could track down that comment...).  The &lt;a href=&quot;http://www.dhamma.org/&quot;&gt;website&lt;/a&gt; referenced by the comment contained (almost) no new-agey mumbo-jumbo and looked legit in general. I also appreciated the fact that this was a relatively serious and intensive course, which should be enough to form a reasonably founded opinion on meditation in general. When learning sporadically, in small bits, it is hard to say whether the material itself is no good, or you just do not understand it yet and need to study more; I was quite skeptical towards the practice, but wanted to give it fair trial. I was quite impressed that there was a course available in Lithuania, a few hours by train from where I live. Finally, the course was free (by tradition Vipassana is taught without monetary compensation). I went ahead and signed up for a standard introductory 10-day course.&lt;/p&gt;

&lt;p&gt;Vipassana (also called insight meditation) is a meditation technique allegedly coming back from Gautama Buddha himself (well, all the traditions like to claim that origin...). It has been experiencing a renaissance, partly due to an &lt;a href=&quot;http://blog.miliauskas.lt/atom.xml&quot;&gt;organization&lt;/a&gt; set up by a meditation teacher S. N. Goenka which has founded meditation centers all over the world. &lt;/p&gt;

&lt;p&gt;The essence of Vipassana is a method of teaching your mind to &lt;em&gt;act&lt;/em&gt; instead of merely &lt;em&gt;reacting&lt;/em&gt; to outside stimuli such as pain, anger of other people or hardships. The technique provided is to monitor your sensations, watch them with &lt;a href=&quot;http://en.wikipedia.org/wiki/Equanimity&quot;&gt;equanimity&lt;/a&gt; and suspend any reaction, and slowly it sinks in that all things are temporary and you can choose what to react to and how. That's the basic idea; I don't want to go deep into exposition of Vipassana as there is plenty of information about that (also at the same time the information is almost useless because you have to experience it to really understand it). Instead, I will sure some of the more personal remarks and experiences.&lt;/p&gt;

&lt;p&gt;The course took place in an cottage near Kretinga, housing around 50 people. The living conditions were absolutely great, and this would have been a true holiday if not for the regime and the rules. The day would start very early, at 4 AM (ending at around 9:30 PM), and we'd do about 12 hours of meditation in total inbetween, with occasional breaks, but the most gruesome part is that no communication at all was allowed with anyone except the manager of the camp (and the teacher during a specified time). That gets to you after a few days, but still, there are people around you, so it's bearable; on the other side, the senses (touch, smell) become very acute. The food was taken care of by volunteers (students who have finished the course), and I could say it was quite good actually. The goal, of course, was to keep the environment from interfering with meditation, and I think it was done very well.&lt;/p&gt;

&lt;p&gt;The presentation of the actual technique also did not disappoint.  Each day a new step would be introduced, with the whole day to practice before moving on. Looking back, the pacing worked well. Every day in the evening there were lectures on theory. They were somewhat informative, but also sometimes annoyingly primitive and verbose. The little mistakes, holes in logic and slight doses of mumbo-jumbo almost drove me nuts by the middle of the course, until I learned not to react to them. Despite the shortcomings of presentation, the simplicity and lucidity of the practice and lightness of theoretical baggage really appealed to me. The whole organisation in general gave the impression of complete transparency, with no strings attached, no financial interests in play and no agitation for further involvement.&lt;/p&gt;

&lt;p&gt;While there are many meditation techniques, I am happy that I've gone with Vipassana in particular for one reason: Vipassana meditation uses no artificial tools to help you concentrate, such as mantras, visualisations, counting, etc. Such methods make concentration &lt;em&gt;much&lt;/em&gt; easier, but they also create a dependence on the methods themselves. I appreciate the purity of Vipassana in this regard.&lt;/p&gt;

&lt;p&gt;Not everything in the practice is roses though. First, a particular worldview supported by Vipassana is presented as &quot;scientific&quot; and supposedly &quot;the right way to live&quot;, and if even if you don't agree, &quot;the truth&quot; of Vipassana will become obvious to you with time. This is a distinctive mark of ideologies. The thing that makes everything break is the reincarnation, which is generally assumed as true, even if it's not shoved down the student's throat. Every rationalization of a world view has a &quot;white lie&quot; (usually related to the concept of eternity somehow) at the core, and in this context reincarnation is it. Given what we know now about the relationship between the mind and the body, reincarnation is absolutely ridiculous and completely untenable, and that breaks all &quot;moral&quot; reasoning for practicing meditation as opposed to doing something else. I'm not the first to bring up this problem, there's plenty of material about it online.&lt;/p&gt;

&lt;p&gt;The second slippery idea is that the concept of &quot;negative happiness&quot; is central in Vipassana, that is: happiness is defined as lack of suffering. This point is not that unreasonable actually, from personal experience I could indeed call the state of non-suffering happiness, but there is definitely something missing when compared to the state of mind when I'm truly, positively happy. Whether you consider that something important or not, it's definitely there.&lt;/p&gt;

&lt;p&gt;Third, Vipassana suggests that it is only you who is at fault when your inner state is disturbed; the world affects you as much as you let it, and in order to find happiness you should learn to control the &quot;interface&quot; rather than the outside world, which will usually not behave as you want.  This may be correct, but sometimes it could just be easier to fix the world rather than change yourself, and I have the suspicion that it this is much more frequently the case in the modern world compared to the pre-modern environment. (This is one of the points which break when reincarnation is rejected, as with reincarnation you have the whole eternity to fix yourself.)&lt;/p&gt;

&lt;p&gt;While the complaints are serious, they do not mean complete rejection of Vipassana but rather integration among the various other techniques available. The actual meditation technique is still great for gaining and maintaining mental composure, reducing anxiety and improving well-being. Now, if I could only get used to meditating regularly...&lt;/p&gt;

&lt;p&gt;If you have the chance, I highly recommend you try out an introductory 10-day course. There is little to lose and a lot to gain. And if you do go ahead, I have two hints. First, do not even think about leaving the course before it's over. Any hardships are temporary and will be overcome quickly. Second, use the time with the teacher, those interactions were very helpful to me. Also, given the &quot;noble silence&quot;, talking to someone once in a while will not hurt.&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-6328269201313463577?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Riga marathon</title>
		<link href="http://blog.miliauskas.lt/2010/05/riga-marathon.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-1684209953518440826</id>
		<updated>2010-09-16T23:03:56+00:00</updated>
		<content type="html">&lt;p&gt;I participated in the &lt;a href=&quot;http://www.nordearigasmaratons.lv/&quot;&gt;Riga marathon&lt;/a&gt; and ran the full 42km! The time (4:39) isn't great at all, but I'm happy to have finished at all!&lt;/p&gt;

&lt;a href=&quot;http://2.bp.blogspot.com/_zn_T2bmMZn0/TJJpACVNN1I/AAAAAAAAAOM/lsrcT_8dVhU/s1600/b1274818344.jpg&quot;&gt;&lt;img src=&quot;http://2.bp.blogspot.com/_zn_T2bmMZn0/TJJpACVNN1I/AAAAAAAAAOM/lsrcT_8dVhU/s400/b1274818344.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5517587942829012818&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-1684209953518440826?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Profiling with Dozer</title>
		<link href="http://mg.pov.lt/blog/profiling-with-dozer.html"/>
		<id>http://mg.pov.lt/blog/profiling-with-dozer.html</id>
		<updated>2010-08-07T03:06:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://pypi.python.org/pypi/Dozer&quot;&gt;Dozer&lt;/a&gt; is mostly known for
its memory profiling capabilities, but the as-yet unreleased version has
more.  I've &lt;a href=&quot;http://mg.pov.lt/blog/capturing-logs-with-dozer.html&quot;&gt;talked
  about log capturing&lt;/a&gt;, now it's time for&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Profiling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This WSGI middleware profiles every request with the cProfile module.
To see the profiles, visit a hidden URL &lt;tt&gt;/_profiler/showall&lt;/tt&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/dozer-all-profiles.png&quot;&gt;&lt;img src=&quot;http://mg.pov.lt/dozer-all-profiles-small.png&quot; alt=&quot;List of profiles&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What you see here is heavily tweaked in &lt;a href=&quot;http://bitbucket.org/mgedmin/dozer&quot;&gt;my &lt;del&gt;fork&lt;/del&gt; &lt;ins&gt;branch&lt;/ins&gt;
  of Dozer&lt;/a&gt;; upstream version had no Cost column and
didn't vary the background of Time by age (that
last bit helps me see clumps of requests).&lt;/p&gt;

&lt;p&gt;Here's what an individual profile looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/dozer-one-profile.png&quot;&gt;&lt;img src=&quot;http://mg.pov.lt/dozer-one-profile-small.png&quot; alt=&quot;One profile&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The call tree nodes can be expanded and collapsed by clicking on the
function name.  There's a hardcoded limit of 20 nesting levels (upstream had a
limit of 15), sadly that appears not to be enough for practical purposes,
especially if you start profiling Zope 3 applications...&lt;/p&gt;

&lt;p&gt;You can also take a look at the WSGI environment:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/dozer-environ.png&quot;&gt;&lt;img src=&quot;http://mg.pov.lt/dozer-environ-small.png&quot; alt=&quot;WSGI environment expanded&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sadly, nothing about the response is captured by Dozer.  I'd've liked to
show the Content-Type and perhaps Content-Length in the profile list.&lt;/p&gt;

&lt;p&gt;The incantation in &lt;tt&gt;development.ini&lt;/tt&gt; is&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;
[filter-app:profile]
use = egg:Dozer#profile
profile_path = /tmp/profiles
next = main
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Create an empty directory /tmp/profiles and &lt;strong&gt;make sure other users
  cannot write to it&lt;/strong&gt;.  Dozer stores captured profiles as Python
pickles, which are &lt;a href=&quot;http://docs.python.org/library/pickle.html#relationship-to-other-python-modules&quot;&gt;insecure&lt;/a&gt;
and allow &lt;strong&gt;arbitrary
  command execution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To enable the profiler, run paster like this:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;paster serve development.ini -n profile&lt;/span&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Bonus feature: call graphs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dozer also writes a call graph in Graphviz &quot;dot&quot; format in the profile
directory.  Here's the graph corresponding to the profile you saw earlier,
as displayed by the excellent &lt;a href=&quot;http://code.google.com/p/jrfonseca/wiki/XDot&quot;&gt;XDot&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/dozer-graph.png&quot;&gt;&lt;img src=&quot;http://mg.pov.lt/dozer-graph-small.png&quot; alt=&quot;Call graph&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See the fork where the &quot;hot&quot; red path splits into two?&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/dozer-graph-zoom1.png&quot;&gt;&lt;img src=&quot;http://mg.pov.lt/dozer-graph-zoom1-small.png&quot; alt=&quot;Call graph, zoomed in&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the left we have Routes deciding to spend 120 ms (70% total time)
recompiling its route maps.  On the right we have the actual request dispatch.
The actual controller action is called a bit further down:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/dozer-graph-zoom2.png&quot;&gt;&lt;img src=&quot;http://mg.pov.lt/dozer-graph-zoom2-small.png&quot; alt=&quot;Call graph, zoomed in&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here it is, highlighted.  42 ms (24% total time), almost all of which is
spent in SQLAlchemy, loading the model object (a 2515 byte image stored as a
blob) from SQLite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A mystery: pickle errors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I first tried to play with the Dozer profiler, I was attacked by
innumerable exceptions.  Some of those were due to a lack of configuration
(profile_path) or invalid configuration (directory not existing), or not
knowing the right URL (going to &lt;tt&gt;/_profiler&lt;/tt&gt; raised TypeError).  I
tried to make Dozer's profiler more forgiving or at least produce clearer
error messages in &lt;a href=&quot;http://bitbucket.org/mgedmin/dozer&quot;&gt;my &lt;del&gt;fork&lt;/del&gt; &lt;ins&gt;branch&lt;/ins&gt;&lt;/a&gt;,
e.g. going to &lt;tt&gt;/_profiler&lt;/tt&gt; now displays the profile list.&lt;/p&gt;

&lt;p&gt;However some errors were very mysterious: some pickles, written by Dozer
itself, could not be unpickled.  I added a try/except that put those at the end
of the list, so you can see and delete them.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/dozer-errors.png&quot;&gt;&lt;img src=&quot;http://mg.pov.lt/dozer-errors-small.png&quot; alt=&quot;Pickle errors&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Does anybody have any clues as to why &lt;a href=&quot;http://bitbucket.org/mgedmin/dozer/src/6b6884445863/dozer/profile.py#cl-183&quot;&gt;profile.py&lt;/a&gt;
might be writing out broken pickles?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: as Ben says in the comments, my changes have
been accepted upstream.  Yay!&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Capturing logs with Dozer</title>
		<link href="http://mg.pov.lt/blog/capturing-logs-with-dozer.html"/>
		<id>http://mg.pov.lt/blog/capturing-logs-with-dozer.html</id>
		<updated>2010-08-07T02:27:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://pypi.python.org/pypi/Dozer&quot;&gt;Dozer&lt;/a&gt; is mostly known for
its memory profiling capabilities, but the as-yet unreleased version has
more:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Log capturing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This WSGI middleware intercepts logging calls for every request.  Here
we see a toy &lt;a href=&quot;http://pylonshq.com/&quot;&gt;Pylons&lt;/a&gt; application I've
been working on in my spare time. Dozer added an info bar at the top:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/dozer-logview-prompt.png&quot;&gt;&lt;img src=&quot;http://mg.pov.lt/dozer-logview-prompt-small.png&quot; alt=&quot;Dozer's infobar&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you click on it, you get to see all the log messages produced for this
request.  I've set SQLAlchemy's loglevel to INFO in my
&lt;tt&gt;development.ini&lt;/tt&gt;, which produces:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/dozer-logview.png&quot;&gt;&lt;img src=&quot;http://mg.pov.lt/dozer-logview-small.png&quot; alt=&quot;Dozer's log viewer&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Why on Earth does SQLAlchemy think I want to see the memory address of the
Engine object in my log files, I don't know.  The parentheses contain
argument values for parametrized queries, of which there are none on this
page.)&lt;/p&gt;

&lt;p&gt;Upstream version displays absolute timestamps (of the YYYY-MM-DD
HH:MM:SS.ssssss variety) in the first column; &lt;a href=&quot;http://bitbucket.org/mgedmin/dozer&quot;&gt;my fork&lt;/a&gt; shows deltas in
milliseconds.  The incantation in &lt;tt&gt;development.ini&lt;/tt&gt; is&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;
[filter-app:logview]
use = egg:Dozer#logview
next = main
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;which makes it disabled by default.  To enable, you run paster like this:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;paster serve development.ini -n logview&lt;/span&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;(Upstream version lacks the paste entry point for logview; it's in my
fork, for which I submitted a pull request weeks ago like a good open-source
citizen.  Incidentally, patches for stuff I maintain have been known to
languish for &lt;em&gt;years&lt;/em&gt; in &lt;em&gt;my&lt;/em&gt; inbox, so I'm not one to throw
stones.)&lt;/p&gt;

&lt;p&gt;Next: &lt;a href=&quot;http://mg.pov.lt/blog/profiling-with-dozer.html&quot;&gt;profiling with Dozer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Tom Longson &lt;a href=&quot;http://truefalsemaybe.com/2008/11/profiling-sql-in-pylons-with-dozer/&quot;&gt;blogged
  about this&lt;/a&gt; back in 2008!  And his CSS is prettier.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">irclog2html is now on PyPI</title>
		<link href="http://mg.pov.lt/blog/irclog2html-on-pypi.html"/>
		<id>http://mg.pov.lt/blog/irclog2html-on-pypi.html</id>
		<updated>2010-08-06T01:32:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/irclog2html/&quot;&gt;irclog2html&lt;/a&gt;, the IRC log to HTML
converter, is now (finally!) available from the &lt;a href=&quot;http://pypi.python.org/pypi/irclog2html&quot;&gt;Python Package Index&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In other news, logs2html now copies &lt;a href=&quot;http://mg.pov.lt/maemo-irclog/irclog.css&quot;&gt;irclog.css&lt;/a&gt; to the
destination directory (if it doesn't exist there already).  I've been noticing
logs produced with irclog2html on random places, and sometimes they were
unstyled; hopefully this will become rare now.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Python course projects</title>
		<link href="http://blog.miliauskas.lt/2010/07/python-course-projects.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-2967594896151762477</id>
		<updated>2010-07-29T11:43:43+00:00</updated>
		<content type="html">&lt;p&gt;
This spring I read a course on &lt;a href=&quot;http://www.python.org/&quot;&gt;Python&lt;/a&gt; in &lt;a href=&quot;http://www.vu.lt/&quot;&gt;Vilnius University&lt;/a&gt;, Department of Mathematics and informatics. The course was not mandatory, which I suspect is one of the reasons why my students were quite a bright and motivated bunch. I began the course with a brief introduction to the Python language and the standard library, then dedicated a few lectures to &lt;a href=&quot;http://www.djangoproject.com/&quot;&gt;Django&lt;/a&gt; and in the remainder I covered various libraries (GUI toolkits, Pygame) and techniques (testing, debugging, optimization).
&lt;/p&gt;

&lt;p&gt;One of the major tasks of the course (and the deciding factor in the final valuation) was to develop a project using Python. The students were given complete freedom over the topic of the project and the tools used, as long as Python was involved. The quality of the result varied, of course; had I given concrete tasks, the low bar would definitely have been higher. However, I am happy with how things turned out.
&lt;/p&gt;

&lt;p&gt;Probably the best-executed project was &lt;a href=&quot;http://www.1000-online.com/&quot;&gt;1000 Online&lt;/a&gt;, an online multiplayer card game (see &lt;a href=&quot;http://www.1000-online.com/rules&quot;&gt;rules&lt;/a&gt;). It was developed by Vytautas Karpavičius. Vytautas apparently had prior experience with Python and Django, nevertheless, the quality of the app (and the code behind it) is impressive. Among the other projects, &lt;a href=&quot;http://gegute.lt/&quot;&gt;Gegute.lt&lt;/a&gt;, a Lithuanian clone of &lt;a href=&quot;http://www.reddit.com/&quot;&gt;Reddit&lt;/a&gt; is still up and running. It's nothing too fancy, but looks quite clean for a university project. Other projects perhaps were not perfectly executed, but were very interesting conceptually. Jonas Keturka developed a bot (&lt;a href=&quot;http://bitbucket.org/kukmedis/pyproj&quot;&gt;BitBucket&lt;/a&gt;) for the online strategy game &lt;a href=&quot;http://travian.com/&quot;&gt;Travian&lt;/a&gt;. Marius Damarackas developed a web-based guess-the-song game. He used YouTube for the song material and Last.fm (IIRC) to make you guess among similar songs, so that it would not be too easy. Andrius Chamentauskas developed a Puyo Pop clone (&lt;a href=&quot;http://github.com/sinsiliux/Puyo&quot;&gt;GitHub&lt;/a&gt;) with PyGame, complete with multiplayer and an AI. Paulius Budzinskas worked towards his course paper by developing a bacteria movement modelling and visualisation app (&lt;a href=&quot;http://github.com/ePaulius/Bakt_modeliavimas&quot;&gt;GitHub&lt;/a&gt;; Lithuanian only). David Abdurachmanov developed a spell-checker bot for WikiAnswers.com, with a really baroque and sophisticated architecture. I believe he has applied to Google Summer of Code with that project; I wonder how that is working out.&lt;/p&gt;

&lt;p&gt;For reference, you can find links to all student repositories on GitHub/BitBucket in &lt;a href=&quot;http://python.gintas.net/wiki/StudentuSarasas&quot;&gt;this list&lt;/a&gt;. Beware: some of them may be documented/commented in Lithuanian.
&lt;/p&gt;

&lt;p&gt;Another interesting effect of the course was that people started using Python in other related courses, for example in Mathematical Modelling and Numeric Methods. I even heard that the lecturer was impressed and expressed interest in learning Python. Another lecturer, this time a statistician, was interested in teaching and using &lt;a href=&quot;http://www.sagemath.org/&quot;&gt;SAGE&lt;/a&gt; at lab practice. Feeling such 'ripples' going through the department sure felt nice.
&lt;/p&gt;

&lt;p&gt;By the way, the university also offers lectures on Ruby, read by Saulius Grigaitis. I took some inspiration from him for the course form and content.&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-2967594896151762477?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Serving ePub files to Android 1.6</title>
		<link href="http://mg.pov.lt/blog/android-fbreader-epub-problem.html"/>
		<id>http://mg.pov.lt/blog/android-fbreader-epub-problem.html</id>
		<updated>2010-07-22T23:23:00+00:00</updated>
		<content type="html">&lt;p&gt; If you click on an ePub download link in the Android browser and get back
an error saying &quot;Cannot download. The content type is not supported on the
device&quot;, then make sure the web server is setting the Content-Type header to
&quot;application/epub+zip&quot; and not &quot;application/octet-stream&quot;.  When you do this,
Android will launch FBReaderJ automatically (provided that you have it
installed, of course).&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">N900 connection sharing the hard way</title>
		<link href="http://mg.pov.lt/blog/n900-connection-sharing.html"/>
		<id>http://mg.pov.lt/blog/n900-connection-sharing.html</id>
		<updated>2010-07-20T22:41:00+00:00</updated>
		<content type="html">&lt;p&gt;My N900 has a SIM card with a flat-rate 3G data plan.  My laptop hasn't.
What do I do when I want to use the Internet on my laptop somewhere that
doesn't have WiFi?  Well, there are many options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1: N900 as a USB modem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the provided USB cable to connect the N900 to the laptop.  Choose &quot;PC
Suite&quot; mode on the N900 when you get the USB connection menu.  The laptop
now sees your N900 as a bog-standard USB 3G modem.  Use Network Manager to
connect to the internet.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pros: no extra setup required.  The N900 and the laptop can both access
  the Internet at the same time.&lt;/p&gt;

  &lt;p&gt;Cons: you have to use a USB cable (I hate cables).  You cannot ssh into your
  N900 (and ssh is my primary file transfer protocol between the laptop and the
  M900).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Option 2: N900 as a Bluetooth DUN modem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Install &lt;a href=&quot;http://maemo.org/downloads/product/Maemo5/bluetooth-dun/&quot;&gt;Bluetooth DUN
  support&lt;/a&gt; from Maemo Extras.  Then use it like you would any other phone
that has Bluetooth DUN.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pros: no cables.&lt;/p&gt;

  &lt;p&gt;Cons: Bluetooth is the worst technology &lt;em&gt;ever&lt;/em&gt;.  I never had it
  work reliably.  Plus, Network Manager in Ubuntu 10.04 doesn't support
  Bluetooth DUN (it supports only Bluetooth PAN, as far as I know).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Option 3: N900 as a WiFi access point with Joikuspot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I haven't tried this.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pros: simple (hopefully), no cables required.&lt;/p&gt;

  &lt;p&gt;Cons: Joikuspot is non-free.  I'm not an absolute zealot, but I will
  avoid closed-source stuff when open-source alternatives are available.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Option 4: N900 as a WiFi access point with &lt;a href=&quot;http://mobilehotspot.garage.maemo.org/&quot;&gt;Mobilehotspot&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I haven't tried this either.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pros: it's an open-source app available from Maemo Extras.  No cables
  required.&lt;/p&gt;

  &lt;p&gt;Cons: requires a non-standard kernel (or so I've heard).  Way outside my
  comfort level.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Option 5: N900 as a WiFi access point with shell scripts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the shell script I run on my N900: &lt;a href=&quot;http://mg.pov.lt/share-wifi&quot;&gt;share-wifi&lt;/a&gt;.  It sets up an ad-hoc WiFi
network, and starts a DHCP and DNS server (dnsmasq).  Sadly, it cannot set up
connection sharing (NAT), so I rely on OpenSSH as a SOCKS5 proxy.  The whole
setup is like this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You want the latest firmware (PR 1.2) to avoid &lt;a href=&quot;https://bugs.maemo.org/show_bug.cgi?id=5712&quot;&gt;this bug&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;You need to have &lt;a href=&quot;http://maemo.org/downloads/product/Maemo5/openssh/&quot;&gt;OpenSSH&lt;/a&gt; installed on
      the N900.  Also, setting up key-based authentication makes it more
      convenient.&lt;/li&gt;
  &lt;li&gt;The script assumes that you've set up sudo on the N900 so that you
      can run any command as root.&lt;/li&gt;
  &lt;li&gt;You need to have &lt;a href=&quot;http://maemo.org/packages/view/wireless-tools/&quot;&gt;wireless-tools&lt;/a&gt;
      installed.  It's in the main SSU repository so you should be able to sudo
      apt-get install it (if it's not preinstalled; I don't remember).&lt;/li&gt;
  &lt;li&gt;On the N900 run &lt;tt&gt;share-wifi&lt;/tt&gt; in a terminal (optionally passing a
      WiFi channel number from 1 to 11, in case you need to avoid interference with
      nearby networks).&lt;/li&gt;
  &lt;li&gt;On the laptop connect to the new n900 WLAN and run
      &lt;tt&gt;ssh -D 1080 user@n900&lt;/tt&gt;.  You will get a shell session; the SOCKS proxy
      will be active while it is open.&lt;/li&gt;
  &lt;li&gt;Reconfigure your laptop to use a SOCKS5 proxy on localhost:1080.
      For GNOME systems I've a couple of shell scripts: &lt;a href=&quot;http://mg.pov.lt/proxy-on&quot;&gt;proxy-on&lt;/a&gt; and &lt;a href=&quot;http://mg.pov.lt/proxy-off&quot;&gt;proxy-off&lt;/a&gt;.  For applications
      that do not use the GNOME proxy settings (such as Subversion access
      over SSH), use &lt;a href=&quot;http://mg.pov.lt/blog/escaping-hotel-firewall.html#tsocks&quot;&gt;tsocks&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;When done, hit Ctrl-C on the N900 to terminate the sharing script.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pros: no non-free software or custom kernel required.  No cables.&lt;/p&gt;

  &lt;p&gt;Cons: complicated to set up.  No WLAN power savings available for ad-hoc
     networks, so battery life is extremely poor (~2 hours).  But, hey, &lt;i&gt;no
     cables!&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">ImportError: No module named _md5</title>
		<link href="http://mg.pov.lt/blog/no-module-md5.html"/>
		<id>http://mg.pov.lt/blog/no-module-md5.html</id>
		<updated>2010-07-06T22:20:00+00:00</updated>
		<content type="html">&lt;p&gt;If you're using virtualenv, and after a system upgrade you get errors like&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;
...
  File &quot;...&quot;, line ...
    from hashlib import md5
  File &quot;/usr/lib/python2.6/hashlib.py&quot;, line 63, in __get_builtin_constructor
     import _md5
ImportError: No module named _md5
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;this means that the copy of the python executable in your virtualenv/bin
directory is outdated and you should update it:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; cp /usr/bin/python2.6 /path/to/venv/bin/python
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;or, better yet, recreate the virtualenv.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Booting ISO images from a USB drive</title>
		<link href="http://mg.pov.lt/blog/booting-iso-from-usb.html"/>
		<id>http://mg.pov.lt/blog/booting-iso-from-usb.html</id>
		<updated>2010-05-03T17:24:00+00:00</updated>
		<content type="html">&lt;p&gt;Dear lazyweb, I would like to download an arbitrary ISO image (say, a &lt;a href=&quot;http://www.ubuntu.com/getubuntu/download&quot;&gt;Ubuntu 10.04 Desktop CD&lt;/a&gt;)
into a directory of a USB flash drive, and then make that USB flash drive boot
that ISO image.  I do &lt;em&gt;not&lt;/em&gt; want to&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;re-partition or re-format the flash drive (this eliminates &lt;a href=&quot;https://launchpad.net/usb-creator&quot;&gt;usb-creator&lt;/a&gt;, AFAIU)&lt;/li&gt;
  &lt;li&gt;extract the contents of the ISO image into the root of the USB drive
      (this eliminates &lt;a href=&quot;http://sourceforge.net/apps/trac/unetbootin/wiki/howitworks&quot;&gt;unetbootin&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;skip the ISO's bootloader and directly boot the kernel+initramfs from
      the ISO (eliminates &lt;a href=&quot;https://lists.ubuntu.com/archives/ubuntu-users/2010-April/216901.html&quot;&gt;this
       recipe&lt;/a&gt;, and &lt;a href=&quot;https://lists.ubuntu.com/archives/ubuntu-users/2010-April/216426.html&quot;&gt;this&lt;/a&gt;&lt;a href=&quot;https://lists.ubuntu.com/archives/ubuntu-users/2010-April/216429.html&quot;&gt;
       recipe&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I just want a bootloader on the USB to read the VFAT filesystem, mount the ISO image as a loop device,
then chain-load the bootloader from that ISO.  Bonus points for having a menu letting me choose one of
several ISO images.  Running a script to edit a text file (say, grub's config)
to get that menu is fine.&lt;/p&gt;

&lt;p&gt;Is this even possible?  If not, can I at least have two out of three (no
partition/extraction, but skipping intrinsic bootloader is fine)?&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Re: Web frameworks considered useful.</title>
		<link href="http://mg.pov.lt/blog/web-frameworks-useful.html"/>
		<id>http://mg.pov.lt/blog/web-frameworks-useful.html</id>
		<updated>2010-04-18T01:57:00+00:00</updated>
		<content type="html">&lt;p&gt;Martijn Faassen &lt;a href=&quot;http://faassen.n--tree.net/blog/view/weblog/2010/04/15/0&quot;&gt;defends web
  frameworks&lt;/a&gt; in a rather longish post (you can tell it's 5 AM in the
morning and I've &lt;em&gt;nearly&lt;/em&gt; defeated the unread post queue in Google
Reader).  I'd like to propose a condensed
version.  Consider this slogan:

&lt;blockquote&gt;
  Simple things should be easy; complicated things should be possible.
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Frameworks&lt;/em&gt; make simple things easy.  &lt;em&gt;Good&lt;/em&gt; frameworks
keep the complicated thing possible; poorly-designed frameworks make the
complicated thing more difficult than necessary; bad frameworks make even
simple things complicated.&lt;/p&gt;

&lt;p&gt;Doing everything from scratch merely makes things possible, but rarely
easy.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Review: Grok 1.0 Web Development</title>
		<link href="http://mg.pov.lt/blog/grok-book-review.html"/>
		<id>http://mg.pov.lt/blog/grok-book-review.html</id>
		<updated>2010-04-04T19:30:00+00:00</updated>
		<content type="html">&lt;p&gt;Disclaimer: I received a free review copy of this book. The book links are
affiliate links; I get a small amount from any purchase you make through them.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://grok.zope.org/&quot;&gt;Grok&lt;/a&gt; is a Python web framework, built on
top of the Zope Toolkit, which is the core of what used to be called Zope 3 and
is now rebranded as BlueBream.  Confused yet?  Get used to it: the small
pluggable components are the heart and soul of ZTK, and the source of its
flexibility. It's not surprising that people take the same approach on a larger
scale: take Zope 3 apart into smaller packages and reassemble them into
different frameworks such as Grok, BlueBream or repoze.bfg.&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.packtpub.com/grok-1-0-web-development/book/mid/150310wgpfxa?utm_source=mg.pov.lt&amp;utm_medium=affiliate&amp;utm_content=blog&amp;utm_campaign=mdb_002715&quot;&gt;
  &lt;img src=&quot;http://mg.pov.lt/grok-book.jpg&quot; width=&quot;250&quot; height=&quot;309&quot; alt=&quot;Grok 1.0 Web Development by Carlos de la Guardia&quot; /&gt;
&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.packtpub.com/grok-1-0-web-development/book/mid/150310wgpfxa?utm_source=mg.pov.lt&amp;utm_medium=affiliate&amp;utm_content=blog&amp;utm_campaign=mdb_002715&quot;&gt;Grok
  book by Carlos de la Guardia&lt;/a&gt; introduces the framework by demonstrating
how to create a small but realistic To-do list manager.  I like this technique,
and it works pretty well.  The author covers many topics:&lt;/p&gt; 
&lt;ul&gt;
  &lt;li&gt; creation of a new project &lt;/li&gt;
  &lt;li&gt; simple views with Zope Page Templates &lt;/li&gt;
  &lt;li&gt; automatic form generation from schemas (with tweaks) &lt;/li&gt;
  &lt;li&gt; catalogs and indexes (my favourite chapter) &lt;/li&gt;
  &lt;li&gt; security: users, roles, permissions; authentication and authorization &lt;/li&gt;
  &lt;li&gt; extremely pluggable page layouts with viewlets and pagelets &lt;/li&gt;
  &lt;li&gt; basic ZODB, blobs, ZEO, database packing, backups with repozo &lt;/li&gt;
  &lt;li&gt; SQL databases, integration with SQLAlchemy (including a common
       transactional model) &lt;/li&gt;
  &lt;li&gt; component architecture: adapters and utilities &lt;/li&gt;
  &lt;li&gt; Martian: extending Grok by defining custom component directives &lt;/li&gt;
  &lt;li&gt; very short intro to testing (zope.testing, unit tests and doctests,
       functional tests with zope.testbrowsing) and debugging (pdb; AJAXy
       debugger, which looks exactly like the Pylons one with an uglier skin) &lt;/li&gt;
  &lt;li&gt; deployment (my second favourite chapter): paster, apache and mod_proxy,
       mod_wsgi, pound, squid, varnish, scalable deployments. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some important topics like internationalization, time zones, testing with
Selenium, and (especially) database migration (which is pretty specific for
ZODB) were not covered.&lt;/p&gt;

&lt;p&gt; &lt;strong&gt;If you want to learn about Grok, this book will be useful&lt;/strong&gt;,
but there's a caveat: there's the usual slew of typographical mistakes and
other errors I've come to expect from books published by Packt.  It's their
third book I've seen; all three had surprisingly high numbers of errors.  Some
had more, others had fewer.  The Grok book was on the high side and the first
one where I was tempted to record a &quot;&lt;a href=&quot;http://www.osnews.com/story/19266/WTFs_m&quot;&gt;WTFs per page&lt;/a&gt;&quot; metric.
The mistakes are easy to notice and correct, so they didn't impede my
understanding of the book's content.  Disclaimer: I've been working with
Zope 3 for the last six-or-so years, so I was pretty familiar with the
underlying technologies, just not the thin Grok convenience layer. &lt;strong&gt;If
  minor errors annoy you, stay away.&lt;/strong&gt;  I haven't noticed any major
factual errors, although there were what I would consider some pretty important
omissions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ZODB is not as transparent as people tell you.  There are many gotchas,
  especially if you want to refactor your code without throwing away old
  databases.&lt;/li&gt;
  &lt;li&gt;&lt;tt&gt;bin/buildout&lt;/tt&gt; is free to recursively remove anything under
  &lt;tt&gt;parts&lt;/tt&gt;.  Keeping your database there is fine only if you don't mind
  occasionally starting from scratch.&lt;/li&gt;
  &lt;li&gt;&lt;tt&gt;repozo&lt;/tt&gt; does not back up blobs.&lt;/li&gt;
  &lt;li&gt;The ZODB transaction conflict resolution depends on being able to
  repeat requests several times; this is important if your code has external
  side effects (e.g. sends emails, creates files, pings 3rd party websites over
  HTTP).  Packages like megrok.rdb or zope.sendmail take care of this; it'd be
  nice to be shown how to do that  for your own code before you discover this
  issue the hard way when your app starts charging people's credit cards three
  times every now and then. &lt;/li&gt;
  &lt;li&gt;You need to make sure you send out object events at appropriate times, or
  your catalog indexes won't be updated.&lt;/li&gt;
  &lt;li&gt;Permission and role grants are persistent: if you delete a user and then
  create a new one with the same username, the new user will have all the roles
  and permissions granted to the old one.  If you implement user deletion, you
  need to explicitly remove old grants.&lt;/li&gt;
  &lt;li&gt;The Zope security model expects every object to have a valid &lt;code&gt;__parent__&lt;/code&gt;
  attribute; permission/role grants will not work properly on objects without a
  &lt;code&gt;__parent__&lt;/code&gt;.  Most of the time this is taken care of
  automatically, but when it's not, you can get really confusing errors.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;applySkin&lt;/code&gt; should only be used for browser requests; blindly
  calling it from a traversal event handler can break WebDAV/XML-RPC.
  (Incidentally, I should file a bug about that; it should abort if you pass a
  non-browser request instead of silently converting it into a browser
  request.)&lt;/li&gt;
  &lt;li&gt;Allowing end-users to specify &lt;code&gt;++skin++&lt;/code&gt; in the URL can be a
  security hole.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, Grok is pretty nice, especially compared to vanilla Zope 3.
However, when compared to frameworks like Pylons or Django, Grok appears more
complex and seemingly requires you to do additional work for unclear gain.  For
example, chapter 8 has you writing three components for every new form you add:
one for the form itself, one for a pagelet wrapping the form, and one for a
page containing the pagelet.  Most of that code is very similar with only the
names being different.  I'm sure there are situations where this kind of
extreme componentization pays off (e.g. it lets you override particular bits on
particular pages to satisfy a particular client's requests, without affecting
any other clients), but the book doesn't convincingly demonstrate those
advantages.  Again, I may be biased here since I've been enjoying those
advantages for the past six years, without ever having felt the pain of doing
similar customizations with a less flexible framework.  (It's a gap in my
professional experience that I'm itching to fill.) &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&quot;http://lateral.netmanagers.com.ar/weblog/posts/BB885.html&quot;&gt;some&lt;/a&gt; &lt;a href=&quot;http://blog.pythonisito.com/2010/03/review-grok-10-web-development.html&quot;&gt;other&lt;/a&gt;
&lt;a href=&quot;http://www.jmcneil.net/2010/03/review-grok-1-0-web-development/&quot;&gt;reviews&lt;/a&gt;
on Planet Python.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 2:&lt;/strong&gt; &lt;a href=&quot;http://blog.lowkster.com/2010/04/review-of-grok-web-development-10-part.html&quot;&gt;Another
  review&lt;/a&gt; (well, part 1 of one, but I got tired waiting for part 2).
&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Review: Python Testing: Beginner's Guide</title>
		<link href="http://mg.pov.lt/blog/python-testing-review.html"/>
		<id>http://mg.pov.lt/blog/python-testing-review.html</id>
		<updated>2010-03-13T18:54:00+00:00</updated>
		<content type="html">&lt;p&gt;I've been testing (as well as writing) Python code for the last eight years,
so a book with the words &lt;em&gt;Begginer's Guide&lt;/em&gt; prominently displayed on
the cover isn't something I'd've decided to buy for myself.  Nevertheless
I jumped at the offer of receiving a free e-copy for reviewing it.&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.packtpub.com/python-testing-beginners-guide/book/mid/1503107sqs3w?utm_source=mg.pov.lt&amp;utm_medium=affiliate&amp;utm_content=blog&amp;utm_campaign=mdb_002714&quot;&gt;
  &lt;img src=&quot;http://mg.pov.lt/python-testing.jpg&quot; width=&quot;250&quot; height=&quot;309&quot; alt=&quot;Python Testing: Beginner's Guide by Danien Arbuckle&quot; /&gt;
&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short summary:&lt;/strong&gt; it's good book.  I learned a thing or two
from it.  I don't know well it would work as an introductionary text for
someone new to unit testing (or Python).  Some of the bits seemed
overcomplicated and underexplained, parts of the example code/tests seemed to
contain design decisions received from mysterious sources.&lt;/p&gt;

&lt;p&gt;Incidentally, &lt;a href=&quot;http://www.packtpub.com/&quot;&gt;Packt&lt;/a&gt; uses a simple yet
effective method for watermarking e-books: my name and street address are
displayed in the footer of every page.  What's funny is that the two non-ASCII
characters in the street name are replaced with question marks.  It's not a
data entry problem: the website that let me download those books shows my
address correctly, so it must be happening somewhere in the PDF production
process.  I didn't expect this kind of Unicode buggyness from a publisher.
Then again there were occasional strange little typographical errors in the
text, like not leaving a space in front of an opening parenthesis in an English
sentence, or using a never-seen-before &lt;tt&gt;+q=&lt;/tt&gt; operator in Python code.  I
was also left wondering how the following sentence (page 225) could slip past
the editing process:&lt;/p&gt;

&lt;blockquote&gt;
  doctest ignores everything between the &lt;tt&gt;Traceback (most recent last call)&lt;/tt&gt;.
&lt;/blockquote&gt;

&lt;p&gt;Thankfully those small mistakes did not detract from the overall message of
the book.&lt;/p&gt;

&lt;p&gt;I liked the author's technique of showing subtly incorrect code, letting the
reader look at it and miss all the bugs, and then showing how unit or
integration tests catch the bugs the reader missed.  I'm pretty sure there's at
least one remaining bug that the author missed in the example package (storing
a schedule doesn't erase old data), which could serve for a new chapter on
regression testing if there's a second edition.&lt;/p&gt;

&lt;p&gt;Summary of topics covered:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Terms: unit testing, integration testing, system testing.&lt;/li&gt;
  &lt;li&gt;Basics of doctest and unittest, their strengths and weaknesses.&lt;/li&gt;
  &lt;li&gt;Using mocks (with Mocker).&lt;/li&gt;
  &lt;li&gt;Using Nose.&lt;/li&gt;
  &lt;li&gt;Test-Driven Development with lots of example code.&lt;/li&gt;
  &lt;li&gt;Using Twill.&lt;/li&gt;
  &lt;li&gt;Integration testing with lots of example code.&lt;/li&gt;
  &lt;li&gt;Using coverage&lt;/li&gt;
  &lt;li&gt;Post-commit hooks to run tests with Bazaar, Mercurial, Git, Darcs,
      Subversion.&lt;/li&gt;
  &lt;li&gt;Continuous integration with Buildbot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found the TDD cycle a bit larger than I generally like, but I believe it's
a matter of taste, and perhaps a shorter cycle wouldn't work as well in a
written medium.&lt;/p&gt;

&lt;p&gt;I found it a bit jarring how the Twill chapter intrudes between the two
chapters showing unit testing and integration testing of the same sample
package.  I think it would've been better to swap the order of chapters 8 and
9.&lt;/p&gt;

&lt;p&gt;I liked the technique presented for picking subsets of the code for
integration tests, although I wonder how well it would work on a larger
project.&lt;/p&gt;

&lt;p&gt;Topics not covered:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Functional testing (which is very close but not exactly the same as
      system testing).&lt;/li&gt;
  &lt;li&gt;Regression testing (page 46 contains advice about this without mentioning
      the term &lt;em&gt;regression testing&lt;/em&gt;).&lt;/li&gt;
  &lt;li&gt;Continuous integration with Hudson (simpler to set up than buildbot,
      easily covers 80% of cases).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see these holes are all rather small.&lt;/p&gt;

&lt;p&gt;Probably the biggest weakness of the book is the complexity of some
things shown:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt; writing mocks for pure unit tests &lt;/li&gt;
  &lt;li&gt; mocking other instances of the same class under test &lt;/li&gt;
  &lt;li&gt; even occasionally mocking &lt;em&gt;self&lt;/em&gt;, which needs tricks like
       calling a method's &lt;tt&gt;im_func&lt;/tt&gt; directly &lt;/li&gt;
  &lt;li&gt; mocking &lt;tt&gt;__reduce_ex__&lt;/tt&gt; so you can pickle mocks in an
       &lt;em&gt;integration test&lt;/em&gt;, instead of using real classes or simple
       stubs. &lt;/li&gt;
  &lt;li&gt; testing the same code multiple times: unit tests, several sets of
       integration tests that test ever-increasing subsets of classes &lt;/li&gt;
  &lt;li&gt; &lt;a href=&quot;http://buildbot.net/&quot;&gt;Buildbot&lt;/a&gt; instead of
       &lt;a href=&quot;http://hudson-ci.org/&quot;&gt;Hudson&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; Seeing the repetitive and redundant mock code in the first few doctest
examples I started asking &lt;em&gt;what's the point?&lt;/em&gt;, but the book failed to
provide a compelling answer (the answer provided—it's easier to locate
bugs—works just as well for integration tests that focus on individual
classes).  And there are good answers for that question, like instant feedback
from your unit test suite.  Are they worth the additional development effort?
Maybe that depends on the developer.  I don't think they would help me, so I
tend to stick with low-level integration tests I call &quot;unit tests&quot; (as well as
system tests; it's always a mistake to keep all your tests in a single level).
I'm slightly worried that this book might give the wrong impression (testing is
hard) and turn away beginning Python programmers from writing tests
altogether.&lt;/p&gt;

&lt;p&gt;Overall I do not feel that I have wasted my time reading &lt;a&gt;&lt;a href=&quot;http://www.packtpub.com/python-testing-beginners-guide/book/mid/1503107sqs3w?utm_source=mg.pov.lt&amp;utm_medium=affiliate&amp;utm_content=blog&amp;utm_campaign=mdb_002714&quot;&gt;Python
  Testing&lt;/a&gt;.  I look forward to reading &lt;a href=&quot;http://python.genedrift.org/2010/03/03/python-testing-beginner’s-guide-review/&quot;&gt;the&lt;/a&gt;
&lt;a href=&quot;http://www.blog.pythonlibrary.org/2010/03/06/book-review-python-testing/&quot;&gt;other&lt;/a&gt;
&lt;a href=&quot;http://mcjeff.blogspot.com/2010/03/review-python-testing-beginners-guide.html&quot;&gt;reviews&lt;/a&gt;
that showed up on Planet Python.  I gathered that not all reviewers were happy
with the book, but avoided reading their reviews in order not to influence my
own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I especially liked &lt;a href=&quot;http://www.protocolostomy.com/2010/03/18/python-testing-beginners-guide-the-review/&quot;&gt;this
  review by Brian Jones&lt;/a&gt;.  The lack of awkward page breaks in code examples
is something that I only noticed after reading a different book, which is full
of such awkward breaks, &lt;em&gt;sigh&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 2:&lt;/strong&gt; The book links are now affiliate links; I get a small
amount from any purchase you make through them. &lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">You've got to love profiling</title>
		<link href="http://mg.pov.lt/blog/you-gotta-love-profiling.html"/>
		<id>http://mg.pov.lt/blog/you-gotta-love-profiling.html</id>
		<updated>2010-03-06T17:49:00+00:00</updated>
		<content type="html">&lt;p&gt;Yesterday I slashed 50% of run time from our applications functional test
suite by modifying a single function.  I had no idea that function was
responsible for 50% of the run time until I started profiling.&lt;/p&gt;

&lt;p&gt;Profiling a Python program is getting easier and easier:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;python -m cProfile -o prof.data bin/test -f&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;runs our test runner (which is a Python script) under the &lt;a href=&quot;http://docs.python.org/library/profile.html&quot;&gt;profiler&lt;/a&gt; and stores
the results in prof.data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;runsnake prof.data&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;launches the &lt;a href=&quot;http://www.vrplumber.com/programming/runsnakerun/&quot;&gt;RunSnakeRun&lt;/a&gt;
profile viewer, which displays the results visually:&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://mg.pov.lt/run-snake-run.png&quot;&gt;
&lt;img src=&quot;http://mg.pov.lt/run-snake-run-square-map.png&quot; alt=&quot;RunSnakeRun square map display&quot; width=&quot;505&quot; height=&quot;370&quot; /&gt;
&lt;/a&gt;
&lt;br /&gt;
The square map display of RunSnakeRun, with the 'render_restructured_text'
function highlighted.
&lt;/p&gt;

&lt;p&gt;Who knew that ReStructuredText rendering could be such a time waster?  A
short caching decorator and the test suite is twice as fast.  The whole
exercise took me less than an hour.  I should've done it sooner.&lt;/p&gt;

&lt;p&gt;Other neat tools:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.python.org/library/profile.html?highlight=pstats#pstats.Stats&quot;&gt;pstats&lt;/a&gt;
  from the standard library lets you load and display profiler results from the
  command line (try &lt;tt&gt;python -m pstats prof.data&lt;/tt&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://pypi.python.org/pypi/pyprof2calltree&quot;&gt;pyprof2calltree&lt;/a&gt;
  converts Python profiler data files to a format that the popular profiler
  visualization tool &lt;a href=&quot;http://kcachegrind.sourceforge.net/html/Home.html&quot;&gt;kcachegrind&lt;/a&gt;
  can understand.  It's somewhat less useful now that RunSnakeRun exists.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://pypi.python.org/pypi/profilehooks&quot;&gt;profilehooks&lt;/a&gt; by
  yours truly has decorators for easily profiling individual functions instead
  of entire scripts.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://pypi.python.org/pypi/keas.profile&quot;&gt;keas.profile&lt;/a&gt; and &lt;a href=&quot;http://pypi.python.org/pypi/repoze.profile&quot;&gt;repoze.profile&lt;/a&gt; hook
  up the profiler as WSGI middleware for easy profiling of web apps.&lt;/li&gt;
&lt;/ul&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Bye, bye, free time!</title>
		<link href="http://mg.pov.lt/blog/volunteeritis.html"/>
		<id>http://mg.pov.lt/blog/volunteeritis.html</id>
		<updated>2010-03-05T20:02:00+00:00</updated>
		<content type="html">&lt;p&gt;Things I've taken up to do in the nearest future:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    Read and review &lt;a href=&quot;http://www.packtpub.com/python-testing-beginners-guide/book?utm_source=mg.pov.lt&amp;utm_medium=bookrev&amp;utm_content=blog&amp;utm_campaign=mdb_002640&quot;&gt;Python
      Testing: Beginner's Guide&lt;/a&gt; and &lt;a href=&quot;http://www.packtpub.com/grok-1-0-web-development/book?utm_source=mg.pov.lt&amp;utm_medium=bookrev&amp;utm_content=blog&amp;utm_campaign=mdb_002639&quot;&gt;Grok
      1.0 Web Development&lt;/a&gt; for Packt.  (The links are trackable to my blog,
    but I'm not getting anything out of it.  Other than free copies of the
    e-books, which I already received, in exchange for a promise to review them
    on this blog.)
  &lt;/li&gt;
  &lt;li&gt;
    Help &lt;a href=&quot;http://www.reportlab.com/software/opensource/&quot;&gt;Reportlab&lt;/a&gt;
    folks set up continuous integration (most likely &lt;a href=&quot;http://hudson-ci.org/&quot;&gt;Hudson&lt;/a&gt;, since &lt;a href=&quot;http://buildbot.net/&quot;&gt;Buildbot&lt;/a&gt;, while powerful, has a steep
    learning curve).
  &lt;/li&gt;
  &lt;li&gt;
    Think about becoming the buildbotmaster for Zope.  Originally I intended
    to volunteer to set up a few buildbots for various Zopeish projects
    (ZTK, BlueBream, Grok, Zope 2) since half of the &lt;a href=&quot;http://docs.zope.org/zopetoolkit/process/buildbots.html&quot;&gt;existing
      ones&lt;/a&gt; were down or broken.  Then various people fixed some of the
    broken ones and other people chimed in mentioning existing buildbots that
    nobody else knew about.  There is a need for somebody to coordinate all
    this activity: make sure we have up-to-date test results for all kinds of
    projects, aggregate them in one place, chase up build slaves for exotic
    OSes (i.e. Windows)...  I don't think I'm well suited for this kind of
    organisational activity.
  &lt;/li&gt;
  &lt;li&gt;
    Push along the various scratch-my-itch open source projects (&lt;a href=&quot;http://mg.pov.lt/gtimelog/&quot;&gt;GTimeLog&lt;/a&gt;, &lt;a href=&quot;http://mg.pov.lt/irclog2html/&quot;&gt;irclog2html&lt;/a&gt;,
      &lt;a href=&quot;https://launchpad.net/zodbbrowser&quot;&gt;zodbbrowser&lt;/a&gt;).
  &lt;/li&gt;
  &lt;li&gt;
    No idea what, but I've been wanting to do something for &lt;a href=&quot;http://maemo.org/&quot;&gt;Maemo&lt;/a&gt;.  Something small, given the copious
    amounts of free time I have.
  &lt;/li&gt;
  &lt;li&gt;
    Then there's the paying work.  On the plus side, there are opportunities
    for fun there (today I slashed functional test run time by a half, by
    adding a small caching decorator in front of a single function.
    &lt;a href=&quot;http://www.vrplumber.com/programming/runsnakerun/&quot;&gt;RunSnakeRun&lt;/a&gt;
    and &lt;a href=&quot;http://docs.python.org/library/profile.html&quot;&gt;cProfile&lt;/a&gt;
    rule!)
  &lt;/li&gt;
  &lt;li&gt;
    You know what, scratch the Zope buildbotmaster idea.  Maybe I can do
    something technical there, e.g. a cron script to ping the various buildbot,
    scrape HTML/parse emails and aggregate build results.  Maybe.
  &lt;/li&gt;
  &lt;li&gt;
    I hope I don't get &lt;a href=&quot;http://en.wikipedia.org/wiki/Burnout_(psychology)&quot;&gt;burnout&lt;/a&gt;
    again.  Because that would suck.  Again.  Been there, done that, didn't
    even get a T-shirt.
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I really ought to read Getting Things Done.  Reading it has been on my
todo-list for &lt;em&gt;years&lt;/em&gt;.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Oopsie</title>
		<link href="http://mg.pov.lt/blog/maemo-flood.html"/>
		<id>http://mg.pov.lt/blog/maemo-flood.html</id>
		<updated>2010-03-03T16:45:00+00:00</updated>
		<content type="html">&lt;p&gt;Sorry for flooding Planet Maemo -- it was a side effect of changing this
feed's URL to only include posts tagged &quot;maemo&quot;.  I'm not sure if the fault
is PyBlosxom's or the aggregator's&lt;/p&gt;

&lt;p&gt;As a penance, here's a Terminal trick for you:&lt;/p&gt;

&lt;pre&gt;
LABELS='[Tab,Esc,Enter,PgUp,PgDn,F2,VKB]'
KEYS='[Tab,Escape,KP_Enter,Page_Up,Page_Down,F2,Return]'
gconftool -s /apps/osso/xterm/key_labels --type list --list-type string &quot;$LABELS&quot;
gconftool -s /apps/osso/xterm/keys --type list --list-type string &quot;$KEYS&quot;
&lt;/pre&gt;

&lt;p&gt;This changes the toolbar to have three extra keys (Enter, F2, and a key that
acts like Enter when the hardware keyboard is open, and opens the virtual
keyboard if the hardware keyboard is closed).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; added screenshot:&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://mg.pov.lt/n900-xterm-toolbar.png&quot;&gt;
&lt;img src=&quot;http://mg.pov.lt/n900-xterm-toolbar.png&quot; alt=&quot;N900 Terminal with new toolbar buttons&quot; width=&quot;400&quot; height=&quot;240&quot; /&gt;
&lt;/a&gt;
&lt;br /&gt;
Nokia N900 Terminal app with new toolbar buttons
&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Weekly Zope developer IRC meetings</title>
		<link href="http://mg.pov.lt/blog/weekly-zope-irc-meeting.html"/>
		<id>http://mg.pov.lt/blog/weekly-zope-irc-meeting.html</id>
		<updated>2010-03-03T10:09:00+00:00</updated>
		<content type="html">&lt;p&gt;On Tuesday we started what will hopefully become a tradition: weekly IRC
meetings for Zope developers.  Topics covered include buildbot organization and
maintenance, open issues with the ZTK development process, and the fate of Zope
3.5 (= BlueBream 1.0).&lt;/p&gt;

&lt;p&gt;There are &lt;a href=&quot;http://zope3.pov.lt/irclogs-zope/%23zope.2010-03-02.log.html#t2010-02-02T16:59:56&quot;&gt;IRC logs&lt;/a&gt; of the meeting, and Christian Theune posted a &lt;a href=&quot;https://mail.zope.org/pipermail/zope-dev/2010-March/039642.html&quot;&gt;summary&lt;/a&gt;
  to the mailing list.&lt;/p&gt;

&lt;p&gt;My take on this can be summed up as: Zope ain't dead yet!  The project has
fragmented a bit (Zope 2, Zope Toolkit, Grok, BlueBream, Repoze), but we all
share a set of core packages and we want to keep them healthy.&lt;/p&gt;

&lt;p&gt;Next meeting is also happening on a Tuesday, at 15:00 UTC on #zope in
FreeNode.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Latin-1 or Windows-1252?</title>
		<link href="http://mg.pov.lt/blog/latin1-or-cp1252.html"/>
		<id>http://mg.pov.lt/blog/latin1-or-cp1252.html</id>
		<updated>2010-01-07T20:29:00+00:00</updated>
		<content type="html">&lt;p&gt;Michael Foord wrote about &lt;a href=&quot;http://www.voidspace.org.uk/python/weblog/arch_d7_2010_01_02.shtml#e1147&quot;&gt;some
  Latin-1 control character fun&lt;/a&gt; in a blog that's hard to read (the RSS feed
syndicated on Planet Python is truncated, grr!) and hard to reply (&lt;del&gt;no comments
  on the blog!&lt;/del&gt; my Chromium's AdBlock+ hid the comment link so I couldn't
find it), but never mind that.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;q&gt;Unfortunately the data from the customers included some \x85 characters,
    which were breaking the CSV parsing.&lt;/q&gt;
&lt;/blockquote&gt;

&lt;p&gt;0x85 is a control character (NEXT LINE or NEL) in Latin-1, but it's a
printable character (HORIZONTAL ELLIPSIS) in Microsoft's code page 1252, which
is often mistaken for Latin-1.  I would venture a suggestion that the encoding
of the customer data was not latin-1 but rather cp1252.&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;'&lt;span class=&quot;escape&quot;&gt;\x85&lt;/span&gt;'&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;decode&lt;/span&gt;(&lt;span class=&quot;string&quot;&gt;'cp1252'&lt;/span&gt;)
&lt;span class=&quot;string&quot;&gt;u'&lt;span class=&quot;escape&quot;&gt;\u2026&lt;/span&gt;'&lt;/span&gt;
&lt;/pre&gt;&lt;/blockquote&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">GTimeLog: not dead yet!</title>
		<link href="http://mg.pov.lt/blog/gtimelog-not-dead-yet.html"/>
		<id>http://mg.pov.lt/blog/gtimelog-not-dead-yet.html</id>
		<updated>2009-12-17T22:22:00+00:00</updated>
		<content type="html">&lt;p&gt;Back in 2004 I wrote a small Gtk+ app to help me keep track of my time, and
called it &lt;a href=&quot;http://mg.pov.lt/gtimelog/&quot;&gt;GTimeLog&lt;/a&gt;.  I shared it with
my coworkers, put it on the web (on the general &quot;release early, release often&quot;
principles), and it got sort-of popular before I found the time to polish it
into a state where I wouldn't be ashamed to show it to other people.&lt;/p&gt;

&lt;p&gt;Fast-forward to 2008: there are actual users out there (much to my
surprise), I still haven't added the originally-envisioned spit and polish,
haven't done anything to foster a development community, am wracked by guilt of
not doing my maintainerly duties properly, which leads to depression and
burnout.  So I do the only thing I can think of: run away from the project and
basically ignore its existence for a year.  Unreviewed patches accumulate in my
inbox.&lt;/p&gt;

&lt;p&gt;It seems that the sabbatical helped: yesterday, triggered by a &lt;a href=&quot;http://bugs.debian.org/560981&quot;&gt;new Debian bug report&lt;/a&gt;, I sat down,
fixed the &lt;a href=&quot;http://mg.pov.lt/blog//?flav=rss&quot;&gt;bug&lt;/a&gt;, implemented a &lt;a href=&quot;https://bugs.launchpad.net/gtimelog/+bug/308750&quot;&gt;feature&lt;/a&gt;, applied a
&lt;a href=&quot;https://bugs.launchpad.net/gtimelog/+bug/328118&quot;&gt;couple&lt;/a&gt; of &lt;a href=&quot;https://bugs.launchpad.net/gtimelog/+bug/255618&quot;&gt;patches&lt;/a&gt;
languishing in the bug tracker, and &lt;a href=&quot;http://pypi.python.org/pypi/gtimelog&quot;&gt;released version 0.3&lt;/a&gt; (which
was totally broken thanks to setuptools magic that suddenly stopped
working; so released 0.3.1 just now).  Then went through my old unread email,
created &lt;a href=&quot;https://bugs.launchpad.net/gtimelog&quot;&gt;bugs in Launchpad&lt;/a&gt; and sent
replies to everyone.  Except &lt;a href=&quot;http://blog.pierlux.com/en/&quot;&gt;Pierre-Luc
  Beaudoin&lt;/a&gt;, since his @collabora.co.uk email address bounced.  If anyone
knows how to contact him, I'd appreciate a note.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://mg.pov.lt/gtimelog-about-dialog.png&quot; alt=&quot;version is now shown in the about dialog&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There are also some older changes that I made before I emerged out of the
funk and so hadn't widely announced:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    There's a &lt;a href=&quot;http://groups.google.com/group/gtimelog&quot;&gt;mailing
      list&lt;/a&gt; for user and developer discussions (if there still are any ;).
  &lt;/li&gt;
  &lt;li&gt;
    GTimeLog's &lt;a href=&quot;https://code.launchpad.net/gtimelog&quot;&gt;source code&lt;/a&gt;
    now lives on Launchpad (actually, I &lt;a href=&quot;http://mg.pov.lt/blog/happenings.html&quot;&gt;mentioned&lt;/a&gt; this on my
    blog once).
  &lt;/li&gt;
&lt;/ul&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Android apps</title>
		<link href="http://blog.miliauskas.lt/2009/12/android-apps.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-5484551814550469122</id>
		<updated>2009-12-16T22:56:17+00:00</updated>
		<content type="html">&lt;p&gt;I've recently gotten myself an &lt;a href=&quot;http://www.android.com&quot;&gt;Android&lt;/a&gt; phone. The Android app market is not as mature as iPhone's App Store, but there is a lot of applications, and plenty of chaff to separate the wheat from. I found most of the apps I use by browsing &quot;top Android apps&quot; lists on the web, so I am putting up a similar list here in case someone finds it useful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Everyday apps&lt;/strong&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Astrid Task/Todo List&lt;/em&gt; - a great To-Do list app that integrates with &lt;a href=&quot;http://www.rememberthemilk.com&quot;&gt;Remember The Milk&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;Quick Calendar - an &quot;upcoming events&quot; widget&lt;/li&gt;
  &lt;li&gt;CardioTrainer - nice jogging app, records routes using GPS, integrates with music player&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Language tools&lt;/strong&gt;
&lt;ul&gt;
  &lt;li&gt;Thesaurus Free - a thesaurus&lt;/li&gt;
  &lt;li&gt;Free Dictionary Org - reference dictionary&lt;/li&gt;
  &lt;li&gt;QuickDic German Dictionary - an English-German-English dictionary&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Media content&lt;/strong&gt;
&lt;ul&gt;
  &lt;li&gt;Listen - an app to find audio content online&lt;/li&gt;
  &lt;li&gt;Mother TED - search and view TED talks&lt;/li&gt;
  &lt;li&gt;TuneWiki - music, song lyrics&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Games&lt;/strong&gt;
&lt;ul&gt;
  &lt;li&gt;Lumbricidae - guide a worm using your accelerometer&lt;/li&gt;
  &lt;li&gt;Flying High - plane flying (also accelerometer-based)&lt;/li&gt;
  &lt;li&gt;miniMatcher - memory game&lt;/li&gt;
  &lt;li&gt;Iconic Memory - another memory game&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;


&lt;li&gt;&lt;strong&gt;Cool apps&lt;/strong&gt;
&lt;ul&gt;
  &lt;li&gt;Phonalyzr - pretty phone call (and SMS) stats&lt;/li&gt;
  &lt;li&gt;Shazam - identify a song by recording a short snippet; possibly one of the coolest apps available&lt;/li&gt;
  &lt;li&gt;SnapTell - look up product information by scanning a barcode (or even by snapping a photo!)&lt;/li&gt;
  &lt;li&gt;Backgrounds - background images&lt;/li&gt;
  &lt;li&gt;Google Sky Map - shows constellations&lt;/li&gt;
  &lt;li&gt;Layar Reality Browser 3.0 - a fancy-looking Augmented Reality app&lt;/li&gt;
&lt;/ul&gt;


&lt;li&gt;&lt;strong&gt;Music&lt;/strong&gt;
&lt;ul&gt;
  &lt;li&gt;Sonorox - tune composition for everyone (the pentatonic scale is great, isn't it?)&lt;/li&gt;
  &lt;li&gt;Loops! Lite - another music composition app&lt;/li&gt;
  &lt;li&gt;Tuner - gStrings - a guitar tuner&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;


&lt;li&gt;&lt;strong&gt;Miscellaneous&lt;/strong&gt;
&lt;ul&gt;
  &lt;li&gt;Task Manager - a process monitor utility, useful for checking up on app resource usage&lt;/li&gt;
  &lt;li&gt;Currency - a currency converter&lt;/li&gt;
  &lt;li&gt;Sleep Logger - a very simple, but useful app for tracking your sleep habits&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-5484551814550469122?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Unix is an IDE, or my Vim plugins</title>
		<link href="http://mg.pov.lt/blog/unix-is-an-ide.html"/>
		<id>http://mg.pov.lt/blog/unix-is-an-ide.html</id>
		<updated>2009-12-08T22:23:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://c2.com/cgi/wiki?UnixIsAnIde&quot;&gt;Unix is an IDE&lt;/a&gt;.  I do my
development (Python web apps mostly) with &lt;a href=&quot;http://www.vim.org/&quot;&gt;Vim&lt;/a&gt;
with a &lt;a href=&quot;http://mg.pov.lt/vim/&quot;&gt;bunch of custom plugins&lt;/a&gt;, shell
(in GNOME Terminal: tabs rule!), GNU make, ctags, find + grep,
svn/bzr/hg/git.&lt;/p&gt;

&lt;p&gt;The current working directory is my project configuration/state.  I run
tests here (bin/test), I search for code here (vim -t TagName, find + grep), I
run applications here (make run or bin/&lt;em&gt;appname&lt;/em&gt;).  I can multitask
freely, for example, if I'm in the middle of typing an SVN commit message, I
can hit Ctrl+Shit+T, get a new terminal tab in the same working directory, and
look something up.  No aliases/environment variables/symlinks/&lt;a href=&quot;http://blog.doughellmann.com/2009/12/switching-development-contexts-with.html&quot;&gt;scripts
  making changes to config files&lt;/a&gt;.  I can work on multiple projects at the
same time.  I can work remotely (over ssh).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vimeo.com/user1043515&quot;&gt;Gary Bernhardt's screencasts on
  Vimeo&lt;/a&gt; show how productive you can get if you learn Vim and tailor it
to your needs.  I have Vim scripts that let me&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    See the name of the class and function that I'm editing in the statusbar,
    even if the class/function definition is offscreen:
    &lt;a href=&quot;http://mg.pov.lt/vim/plugin/pythonhelper.vim&quot;&gt;pythonhelper.vim&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li&gt;
    See all pyflakes warnings and errors in a list as soon as I press F2 to
    save the file: &lt;a href=&quot;http://mg.pov.lt/vim/plugin/python_check_syntax.vim&quot;&gt;python_check_syntax.vim&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li&gt;
    Add a &quot;from foo.bar import Something&quot; line at the top of the file if I
    press F5 when my cursor is on Something, looking up the package and module
    from ctags: &lt;a href=&quot;http://mg.pov.lt/vim/plugin/python-imports.vim&quot;&gt;python-imports.vim&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li&gt;
    Switch between production code and unit tests with a single key if the
    project uses one of several conventions for tests (e.g. ./foo.py
    &lt;tt&gt;&amp;lt;-&amp;gt;&lt;/tt&gt; ./tests/test_foo.py):
    &lt;a href=&quot;http://mg.pov.lt/vim/plugin/py-test-switcher.vim&quot;&gt;py-test-switcher.vim&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li&gt;
    Generate a command line for running one particular unit test (the one
    my cursor is inside) and copy it into the system clipboard, so I can
    run that test by Alt-Tabbing into my terminal window and pasting.
    &lt;a href=&quot;http://mg.pov.lt/vim/plugin/py-test-runner.vim&quot;&gt;py-test-runner.vim&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li&gt;
    Open the right file and move the cursor to the right line if I
    triple-click a line of traceback in a shell (or an email) then press F7 in
    my gvim window:
    &lt;a href=&quot;http://mg.pov.lt/vim/plugin/py-test-locator.vim&quot;&gt;py-test-locator.vim&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li&gt;
    Compare my version of the code with the pristine version in source control
    in an interactive side-by-side diff that lets me revert bits I no longer
    want:
    &lt;a href=&quot;http://mg.pov.lt/vim/plugin/vcscommand.vim&quot;&gt;vcscommand.vim&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li&gt;
    Highlight which lines of the source are covered by my tests, if I have
    coverage information in trace.py format:
    &lt;a href=&quot;http://mg.pov.lt/vim/plugin/py-coverage-highlight.vim&quot;&gt;py-coverage-highlight.vim&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li&gt;
    Show the signature of a function/class's __init__ when I type the name
    of that class/function and an open parenthesis (looked up from tags):
    &lt;a href=&quot;http://mg.pov.lt/vim/plugin/py-function-signature.vim&quot;&gt;py-function-signature.vim&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li&gt;
    Fold code into an outline so I only see names of methods or classes
    instead of their full bodies:
    &lt;a href=&quot;http://mg.pov.lt/vim/vimrc&quot;&gt;vimrc&lt;/a&gt;, function PythonFoldLevel.
  &lt;/li&gt;
  &lt;li&gt;
    Fold diff files so I can see whole hunks/files and can delete those with
    a single key (well, two keys -- dd).  Useful for reviewing &lt;em&gt;large&lt;/em&gt;
    diffs (tens of thousands of lines):
    &lt;a href=&quot;http://mg.pov.lt/vim/vimrc&quot;&gt;vimrc&lt;/a&gt;, function DiffFoldLevel.
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of these come from &lt;a href=&quot;http://www.vim.org&quot;&gt;www.vim.org&lt;/a&gt;, some
I've written myself, some I've taken and modified a little bit to avoid an
irritating quirk or add a missing feature.  Some things I don't have (and envy
Emacs or IDE users for having -- like an integrated debugger for Python apps,
and, generally, integration with other tools, running in the background).&lt;/p&gt;

&lt;p&gt;It's been my plan for a long time to polish my plugins, release them
somewhere (github?  bitbucket? launchpad?) and upload to vim.org, but as it
doesn't seem to be happening, I thought I'd at least put an &lt;a href=&quot;http://mg.pov.lt/vim&quot;&gt;svn
  export of my ~/.vim&lt;/a&gt; on the web.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Displaying multiline text in Zope 3</title>
		<link href="http://mg.pov.lt/blog/zope3-displaying-multiline-text.html"/>
		<id>http://mg.pov.lt/blog/zope3-displaying-multiline-text.html</id>
		<updated>2009-12-01T17:52:00+00:00</updated>
		<content type="html">&lt;p&gt;zope.schema has Text and TextLine.  The former is for multiline text, the
latter is for a single line, as the name suggests.  Zope 3 forms will use a
text area for Text fields and an input box for TextLine fields.  Display
widgets, however, apply no special formatting (other than HTML-quoting of
characters like &amp;lt;, &amp;gt; and &amp;amp;), and since newlines are treated the same
way as spaces in HTML, your multiline text gets collapsed into a single
paragraph.&lt;/p&gt;

&lt;p&gt;Here's a pattern I've been using in Zope 3 to display multiline user-entered
text as several paragraphs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;cgi&lt;/span&gt;

&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;zope&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;component&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;adapts&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;zope&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;publisher&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;browser&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;BrowserView&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;zope&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;publisher&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;interfaces&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;IRequest&lt;/span&gt;


&lt;span class=&quot;def&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;SplitToParagraphsView&lt;/span&gt;(&lt;span class=&quot;name&quot;&gt;BrowserView&lt;/span&gt;):
    &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;Splits a string into paragraphs via newlines.&quot;&quot;&quot;&lt;/span&gt;

    &lt;span class=&quot;name&quot;&gt;adapts&lt;/span&gt;(&lt;span class=&quot;name&quot;&gt;None&lt;/span&gt;, &lt;span class=&quot;name&quot;&gt;IRequest&lt;/span&gt;)

    &lt;span class=&quot;def&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;paragraphs&lt;/span&gt;(&lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;):
        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;None&lt;/span&gt;:
            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; []
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;filter&lt;/span&gt;(&lt;span class=&quot;name&quot;&gt;None&lt;/span&gt;, [&lt;span class=&quot;name&quot;&gt;s&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;strip&lt;/span&gt;() &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;context&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;splitlines&lt;/span&gt;()])

    &lt;span class=&quot;def&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;__call__&lt;/span&gt;(&lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;):
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;&quot;&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;join&lt;/span&gt;(&lt;span class=&quot;string&quot;&gt;'&amp;lt;p&amp;gt;%s&amp;lt;/p&amp;gt;&lt;span class=&quot;escape&quot;&gt;\n&lt;/span&gt;'&lt;/span&gt; % &lt;span class=&quot;name&quot;&gt;cgi&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;escape&lt;/span&gt;(&lt;span class=&quot;name&quot;&gt;p&lt;/span&gt;)
                        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;paragraphs&lt;/span&gt;())
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;View registration&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
&amp;lt;&lt;span class=&quot;def&quot;&gt;configure&lt;/span&gt;
    xmlns=&quot;http://namespaces.zope.org/zope&quot;&amp;gt;

  &amp;lt;&lt;span class=&quot;def&quot;&gt;view&lt;/span&gt;
      &lt;span class=&quot;name&quot;&gt;for&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;*&quot;&lt;/span&gt;
      &lt;span class=&quot;name&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;paragraphs&quot;&lt;/span&gt;
      &lt;span class=&quot;name&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;zope.publisher.interfaces.browser.IBrowserRequest&quot;&lt;/span&gt;
      &lt;span class=&quot;name&quot;&gt;factory&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;.views.SplitToParagraphsView&quot;&lt;/span&gt;
      &lt;span class=&quot;name&quot;&gt;permission&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;zope.Public&quot;&lt;/span&gt;
      /&amp;gt;

&amp;lt;/&lt;span class=&quot;def&quot;&gt;configure&lt;/span&gt;&amp;gt;
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;and usage&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
&amp;lt;&lt;span class=&quot;def&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;tal&lt;/span&gt;:&lt;span class=&quot;name&quot;&gt;replace&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;structure object/attribute/@@paragraphs&quot;&lt;/span&gt; /&amp;gt;
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt;  The view really ought to be registered twice: once
for basestring and once for NoneType.  I was too lazy to figure out the dotted
names for those (or check if zope.interface has external interface declarations
for them), so I registered it for &quot;*&quot;.  You should know that this makes the
view available for arbitrary objects (but won't work for most of them, since
they don't have a splitlines method), and that it is, sadly, accessible to
users who may try to hack your system by typing things like @@paragraphs in the
browser's address bar.  Ignas Mikalajūnas offers an &lt;a href=&quot;http://blog.pow.lt/2009/12/02/formatting-and-processing-text-in-tal-templates/&quot;&gt;alternative
  solution using TALES path adapters&lt;/a&gt;.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Maemo Summit 2009</title>
		<link href="http://mg.pov.lt/blog/maemo-summit-2009.html"/>
		<id>http://mg.pov.lt/blog/maemo-summit-2009.html</id>
		<updated>2009-10-11T22:22:00+00:00</updated>
		<content type="html">&lt;p&gt;The second &lt;a href=&quot;http://wiki.maemo.org/Maemo_Summit_2009&quot;&gt;Maemo Summit&lt;/a&gt; is over.&lt;/p&gt;

&lt;p&gt;Nokia surprised everyone on the first day by handing out 300 pre-release &lt;a href=&quot;http://maemo.nokia.com/n900/&quot;&gt;N900&lt;/a&gt;s to the participants.  I'm so
happy now that after a long period of wavering I finally decided to come to the
summit!  The device is much better than I expected/feared (and I haven't even
put a SIM card in yet).  We're supposed to provide feedback and will have to
send the devices back to Nokia in 6 months.
(Nokia insisted on loan contracts &lt;span&gt;signed in blood&lt;/span&gt;, kidding, but
there are contracts.)&lt;/p&gt;

&lt;p&gt;The tiny pixels are beautiful.  It's what, 266 pixels per inch?  Even older
225 dpi devices spoiled me: both the first generation iPhone and the first
generation Kindle displays seemed very coarse and pixellated.&lt;/p&gt;

&lt;p&gt;The user interface is very smooth.  Having a composition manager improves
apparent responsiveness: even if the app is swapped out and not ready to
redraw, switching between windows appears to be instant since the picture is
cached.  And there's no flicker while the apps are redrawing.  (Flickering
during redraw is one of the main reasons I did not buy a S60 phone and stayed
with good old S40.)  Speaking of swapping, it's barely noticeable.  You can run
more apps than fit in RAM without having to suffer.  The flash memory is
noticeably faster than in a N810.  And there's more of it (32 gigs: 28 gig
partition for user data, the rest for the system: swap, applications, config
files, etc.)&lt;/p&gt;

&lt;p&gt;The design and usability of the user interface have improved a lot since the
N810.  The UI is pretty.  Many of the apps are now convenient to use.
Pervasive kinetic scrolling is sweet (except when you have really long lists or
web pages, then it takes &lt;em&gt;forever&lt;/em&gt; to reach the end).&lt;/p&gt;

&lt;p&gt;Finally there are PIM-y things people missed in older Maemo releases:
calendaring, contacts that can record all kinds of information (such as phone
numbers).&lt;/p&gt;

&lt;p&gt;All right, enough gushing.  There were some irritating things too.  For
example, Bluetooth support is buggy/incomplete in the pre-release firmware, so
it's hard to transfer files.  Calendar/contacts sync with S40 phones does not
work either.  GPS is utterly useless when you're offline (no maps, or at least
I haven't found a way to pre-download and cache them; also very long fix times
without network assistance).  Since I have no desire to pay extortionist
roaming charges of my provider (2.5 EUR per megabyte), and haven't had a chance
to go look for a prepaid SIM card, I usually have either WiFi or GPS coverage,
but not both.&lt;/p&gt;

&lt;p&gt;As you can guess, playing the device diverted a part of my attention from
the presentations somewhat.  I tried to compensate for that by reporting
on the talks on IRC (using xchat on the device).  I think the strategy
backfired; IRC is rather disruptive and the channel is quite busy lately.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Escaping hotel firewalls with ssh over port 80</title>
		<link href="http://mg.pov.lt/blog/escaping-hotel-firewall.html"/>
		<id>http://mg.pov.lt/blog/escaping-hotel-firewall.html</id>
		<updated>2009-10-11T20:09:00+00:00</updated>
		<content type="html">&lt;p&gt;I booked a stay at a particular hotel because the web page said &quot;Free WiFi&quot;.
It didn't say &quot;all outgoing ports firewalled except for port 80 and a few
other (useless) ones&quot;.  Not having SSH access is most painful.  Luckily,
there's a solution.&lt;/p&gt;

&lt;p&gt;You need a web server running Apache and SSH.  Enable mod_proxy and
mod_proxy_connect and add this to the &lt;em&gt;first&lt;/em&gt; (i.e. default) virtual
host configuration:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;
&amp;lt;VirtualHost &lt;em&gt;whatever&lt;/em&gt;:80&amp;gt;
...

  # allow ssh to localhost over http proxy
  ProxyRequests on
  AllowCONNECT 22
  &amp;lt;Proxy localhost&amp;gt;
    Order allow,deny
    Allow from all
  &amp;lt;/Proxy&amp;gt;

&amp;lt;/VirtualHost&amp;gt;
&lt;/pre&gt;&lt;/blockquote&gt;
Reload Apache configuration.  The setup is done.  (Instructions based on &lt;a href=&quot;http://dag.wieers.com/howto/ssh-http-tunneling/&quot;&gt;Tunneling SSH over
  HTTP(S)&lt;/a&gt; by Dag Wieers.)&lt;/p&gt;

&lt;p&gt;On the client side you need &lt;a href=&quot;http://proxytunnel.sourceforge.net/&quot;&gt;proxytunnel&lt;/a&gt;.  Sadly, it's not
packaged for Ubuntu yet, but compiling from sources is trivial.  Edit ~/.ssh/config
and add an entry for your proxied ssh connection:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
Host p&lt;em&gt;myservername&lt;/em&gt;
ProxyCommand proxytunnel -q -p &lt;em&gt;myserver.mydomain.com&lt;/em&gt;:80 -d localhost:22
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;That's it.  Now you can &lt;tt&gt;ssh p&lt;em&gt;myservername&lt;/em&gt;&lt;/tt&gt;.  (The p prefix
is a reminder that I'm using a proxied connection: ssh fridge versus ssh
pfridge.  Also it reminds me of Terry Pratchett's &lt;a href=&quot;http://www.amazon.com/Pyramids-Terry-Pratchett/dp/0061020656&quot;&gt;Pyramids&lt;/a&gt;.).

&lt;p&gt;For extra fun (e.g. IRC) use ssh's built-in SOCKS5 proxy: &lt;tt&gt;ssh -D 1080
  p&lt;em&gt;myservername&lt;/em&gt;&lt;/tt&gt;.  Then tell the apps to use a SOCKS5 proxy on
localhost.  Since telling each app to use a proxy (and then, later, telling it
to stop using it) is a big *pain*, and some apps (e.g. ssh) don't support
proxies directly, a wrapper like &lt;a href=&quot;http://tsocks.sourceforge.net/&quot;&gt;tsocks&lt;/a&gt; is handy.  Edit
/etc/tsocks.conf and set the default socks server to 127.0.0.1, then use
it to run apps:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;tsocks xchat-gnome&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;tsocks bzr push lp:&lt;em&gt;myprojectname&lt;/em&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;tsocks is packaged for Ubuntu.&lt;/p&gt;

&lt;p&gt;If your hotel doesn't have free WiFi, a prepaid SIM card with 3G access
could be cheaper than roaming charges.  Apparently you can get one with a
virtually unlimited (for a short stay, anyway) data plan for 27 EUR in
Amsterdam.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Piano improv #2</title>
		<link href="http://blog.miliauskas.lt/2009/09/piano-improv-2.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-7741142431868328975</id>
		<updated>2009-09-28T02:47:10+00:00</updated>
		<content type="html">Here's a recording of a recent improvisation.  It's very simple, but I'm quite happy with it.

&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-7741142431868328975?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Pylons and SQL schema migration</title>
		<link href="http://mg.pov.lt/blog/pylons-and-sql-migration.html"/>
		<id>http://mg.pov.lt/blog/pylons-and-sql-migration.html</id>
		<updated>2009-09-21T16:44:00+00:00</updated>
		<content type="html">&lt;p&gt;I'm at the point in my hobby project where I'd like to be able to change my models
without losing all my test data.  And I'm too lazy to do manual dumps and edit
the SQL in place before reimporting it.&lt;/p&gt;

&lt;p&gt;I want a system&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;that is &lt;em&gt;transparent&lt;/em&gt; to the user: if my database is at schema
      version 1, and my code is at version 3, I want it to be automatically
      upgraded to version 3 on server startup.&lt;/li&gt;
  &lt;li&gt;that is &lt;em&gt;not too hard&lt;/em&gt; on the programmer: dropping a numbered Python or SQL
      script in a directory ought to be sufficient to define a transition from
      schema version X to schema version X+1.&lt;/li&gt;
  &lt;li&gt;that &lt;em&gt;handles errors gracefully&lt;/em&gt;: makes a backup of the database
      with the old schema version; runs my script in a transaction and aborts
      that transaction if the conversion fails (while showing me enough
      information to debug the problem).&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;allows prototyping&lt;/em&gt; without having to increment the schema number for every
      little change I make to the models; I should be the one who decides that a new
      schema is ready to go out to the world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've been glancing at &lt;a href=&quot;http://code.google.com/p/sqlalchemy-migrate/&quot;&gt;SQLAlchemy-Migrate&lt;/a&gt;, since I've
been brought up to believe &lt;abbr title=&quot;Not Invented Here&quot;&gt;NIH&lt;/abbr&gt;ing is
Bad.  But Migrate is &lt;em&gt;scary&lt;/em&gt;.  I have to admit that the longer I stare
at its documentation, the less I can describe &lt;em&gt;why&lt;/em&gt; I think so.  All
those shell commands—but there's an API for invoking them from Python, so maybe I can
achieve my goals.  I'll have to try and see.
&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Pylons with zc.buildout, continued</title>
		<link href="http://mg.pov.lt/blog/pylons-with-buildout-2.html"/>
		<id>http://mg.pov.lt/blog/pylons-with-buildout-2.html</id>
		<updated>2009-09-15T20:31:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://mg.pov.lt/blog/pylons-with-buildout.html&quot;&gt;Last time&lt;/a&gt; I
mentioned that running bin/buildout with the -N flag makes it run faster
(since it skips looking for newer versions to upgrade).  You can tell
buildout to do this by default by putting 'newest = false' into the [buildout]
section of buildout.cfg. We'll be running bin/buildout a lot now, since we'll
be making changes to the project environment, so this will save wear and tear
on the '-', 'N' and Shift keys.  (And, by the way, I'm not trying to soak up
Google juice by repeating the word 'buildout' a lot, honest!)&lt;/p&gt;

&lt;p&gt;I will omit bzr commits from this narrative as it's getting long; you can
assume that every self-contained change was committed separately.&lt;/p&gt;

&lt;h4&gt;tests&lt;/h4&gt;

&lt;p&gt;  First, I want a bin/test script to run the test
suite.  Pylons uses nose, so we need to tell buildout to install the nosetests
script (under a different name, since I'm used to typing bin/test no matter
what test runner a project happens to use):&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr diff&lt;/span&gt;
=== modified file 'buildout.cfg'
--- buildout.cfg	2009-09-15 19:49:11 +0000
+++ buildout.cfg	2009-09-15 19:49:18 +0000
@@ -8,5 +8,8 @@
 recipe = zc.recipe.egg
 eggs = Pylons
        PasteScript
+       nose
        asharing
 interpreter = python
+scripts = paster
+          nosetests=test

&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bin/buildout&lt;/span&gt;
...
Generated script '/tmp/AlliterationSharing/bin/paster'.
Generated script '/tmp/AlliterationSharing/bin/test'.
...
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bin/test&lt;/span&gt;

----------------------------------------------------------------------
Ran 0 tests in 0.276s

OK
&lt;/pre&gt;

&lt;h4&gt;ctags&lt;/h4&gt;

&lt;p&gt;Documentation is good, but sometimes you want to look at the source code of
the framework.  There's a tool called &lt;a href=&quot;http://ctags.sourceforge.net/&quot;&gt;ctags&lt;/a&gt; that builds a database of
identifiers.  The popular text editors &lt;a href=&quot;http://www.vim.org/&quot;&gt;Vim&lt;/a&gt;
and &lt;a href=&quot;http://www.gnu.org/software/emacs/&quot;&gt;Emacs&lt;/a&gt; can then use the
tags database to jump to a definition of any name with a single keystroke
(Ctrl-] in vim, M-. in emacs).&lt;/p&gt;

&lt;p&gt;Building the tags database is complicated by each Python package being
installed into a separate directory.  There's a buildout recipe called
z3c.recipe.tag that finds those directories and lets you build a unified tags
file.  We'll also ask buildout to make sure it &lt;em&gt;unzips&lt;/em&gt; any packages
distributed as .egg files, since ctags doesn't process those:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr diff&lt;/span&gt;
@@ -1,8 +1,9 @@
 [buildout]
 develop = .
-parts = pylons
+parts = pylons ctags
 
 newest = false
+unzip = true
 
 [pylons]
 recipe = zc.recipe.egg
@@ -13,3 +14,7 @@
 interpreter = python
 scripts = paster
           nosetests=test
+
+[ctags]
+recipe = z3c.recipe.tag:tags
+eggs = ${pylons:eggs}

&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bin/buildout&lt;/span&gt;
...
Generated script '/tmp/AlliterationSharing/bin/ctags'.
...
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bin/ctags&lt;/span&gt;
&lt;/pre&gt;

&lt;h4&gt;omelette&lt;/h4&gt;

&lt;p&gt;ctags lets you find classes and functions by name; it doesn't let you find
packages or modules.  There's another recipe, collective.recipe.omelette that
creates a tree of symlinks mirroring the Python package structure (here
'unzip = true' also comes in handy):&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr diff&lt;/span&gt;
=== modified file 'buildout.cfg'
--- buildout.cfg	2009-09-15 20:04:42 +0000
+++ buildout.cfg	2009-09-15 20:05:30 +0000
@@ -1,6 +1,6 @@
 [buildout]
 develop = .
-parts = pylons ctags
+parts = pylons ctags omelette
 
 newest = false
 unzip = true
@@ -18,3 +18,7 @@
 [ctags]
 recipe = z3c.recipe.tag:tags
 eggs = ${pylons:eggs}
+
+[omelette]
+recipe = collective.recipe.omelette
+eggs = ${pylons:eggs}

&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bin/buildout &lt;/span&gt;
...
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;ls -l parts/omelette&lt;/span&gt;
...
&lt;/pre&gt;

&lt;p&gt;The symlink tree is created under parts/omelette/.  For example, if you want
to see what webhelper tags were available, you can open
parts/omelette/webhelper/html/builder.py in your editor and see.

&lt;h4&gt;Makefile&lt;/h4&gt;

&lt;p&gt;This is getting long (and not everyone may be interested&lt;sup class=&quot;footnote&quot;&gt;1&lt;/sup&gt;), but one long post is easier to skip than five
medium ones in a row, so I'll continue.&lt;/p&gt;

&lt;blockquote class=&quot;footnotes&quot;&gt;
  &lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; Sorry, &lt;a href=&quot;http://maemo.org/news/planet-maemo/&quot;&gt;Planet
    Maemo&lt;/a&gt;!  There's an &lt;a href=&quot;http://mg.pov.lt/blog/tag/maemo/index.rss&quot;&gt;RSS feed of posts tagged
    'maemo'&lt;/a&gt;, if you can figure out the URL, which is very well hidden by
    PyBlosxom, *sigh*.
  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wouldn't it be nice if new developers could check out your project and start
it up with just a couple of commands?  Make is a time-tested tool that works
well for this:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;cat Makefile&lt;/span&gt;
# Just remember that you need to use real tabs, not spaces, in a Makefile

PYTHON = python

.PHONY: all
all: bin/paster

.PHONY: run
run: bin/paster
        bin/paster serve development.ini --reload

.PHONY: test check
test check: bin/test
        bin/test

.PHONY: tags
tags: bin/ctags
        bin/ctags

bin/paster bin/test bin/python bin/ctags: bin/buildout
        bin/buildout

bin/buildout: bootstrap.py
        $(PYTHON) bootstrap.py
&lt;/pre&gt;

&lt;p&gt;Now all you need to do after checking out is run 'make' to set up a working
development environment.  'make run' or 'make test' will also do that, if
necessary, so this one-liner is sufficient to get a working Hello World
application on port 5000:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr branch lp:~mgedmin/+junk/AlliterationSharing &amp;amp;&amp;amp; cd AlliterationSharing &amp;amp;&amp;amp; make run&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Try it!  You'll get a Bazaar branch with all the history of this little
blog project.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Starting a Pylons project with zc.buildout</title>
		<link href="http://mg.pov.lt/blog/pylons-with-buildout.html"/>
		<id>http://mg.pov.lt/blog/pylons-with-buildout.html</id>
		<updated>2009-09-13T13:13:00+00:00</updated>
		<content type="html">&lt;p&gt;For software development I prefer &lt;a href=&quot;http://www.buildout.org&quot;&gt;buildout&lt;/a&gt; to &lt;a href=&quot;http://pypi.python.org/pypi/virtualenv&quot;&gt;virtualenv&lt;/a&gt;.  This is
because buildout has a text file describing the state of your working
environent, which can be versioned and used later to recreate it, as well
as during development to modify the environment slightly.&lt;/p&gt;

&lt;p&gt;To start a new Pylons project, first create an empty directory.  Let's
call our new project AlliterationSharing&lt;sup class=&quot;footnote&quot;&gt;1&lt;/sup&gt;, because everybody is sick of 'foo'
and 'bar'.&lt;/p&gt;

&lt;blockquote class=&quot;footnotes&quot;&gt;
&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; Generated by randomly picking two words from
/usr/share/dict/words, then chosen over among 120 other variants that weren't
as good.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;mkdir -p ~/src/AlliterationSharing&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;cd ~/src/AlliterationSharing&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Now create a file called buildout.cfg with the following content:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;cat buildout.cfg&lt;/span&gt;
[buildout]
parts = pylons

[pylons]
recipe = zc.recipe.egg
eggs = Pylons
       PasteScript
interpreter = python
&lt;/pre&gt;

&lt;p&gt;Download &lt;a href=&quot;http://svn.zope.org/zc.buildout/trunk/bootstrap/&quot;&gt;bootstrap.py&lt;/a&gt; to
it and run it to get bin/buildout.  Note: you can chose which Python version you
want to use by running bootstrap.py with it.  All other scripts under bin/
will be generated by buildout and will use the same Python interpreter.&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;wget http://svn.zope.org/*checkout*/zc.buildout/trunk/bootstrap/bootstrap.py&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;python bootstrap.py&lt;/span&gt;
Creating directory '.../AlliterationSharing/bin'.
Creating directory '.../AlliterationSharing/parts'.
Creating directory '.../AlliterationSharing/eggs'.
Creating directory '.../AlliterationSharing/develop-eggs'.
Generated script '.../AlliterationSharing/bin/buildout'.
&lt;/pre&gt;

&lt;p&gt;Run bin/buildout to install Pylons into your sandbox.&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bin/buildout&lt;/span&gt;
Installing pylons.
Generated script '.../AlliterationSharing/bin/paster'.
Generated interpreter '.../AlliterationSharing/bin/python'.
&lt;/pre&gt;

&lt;p&gt;Aside: buildout has this very nice feature where it can share Python
packages between projects.  This will save you enormous amounts of time that
would otherwise be spent downloading and unpacking eggs.  To make use of this
facility, create a file ~/.buildout/default.cfg with&lt;/p&gt;
&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;cat ~/.buildout/default.cfg &lt;/span&gt;
[buildout]
eggs-directory = /home/mg/tmp/buildout-eggs
# XXX replace /home/mg with the full path of *your* home directory
# it would be much nicer if buildout let me use ~ or $HOME
# see &lt;a href=&quot;https://bugs.launchpad.net/zc.buildout/+bug/190260&quot;&gt;https://bugs.launchpad.net/zc.buildout/+bug/190260&lt;/a&gt;
&lt;/pre&gt;

&lt;p&gt;Another useful trick is to pass the -N flag to bin/buildout, which will tell
it not to bother looking for newer versions of packages on the Internet when
there's already an existing version installed in your eggs directory.&lt;/p&gt;

&lt;p&gt;Back to business: now you've got two new scripts: bin/python and bin/paster.
You can use the first one to play with the interactive Python console where you
can now import pylons and all the dependencies; it has no other value.&lt;/p&gt;

&lt;p&gt;Now is a good point to add the files you've created into a version control
system.  I'll arbitrarily use Bazaar.&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr init .&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr add bootstrap.py buildout.cfg&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr ignore bin parts eggs develop-eggs .installed.cfg&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr commit -m &quot;Create AlliterationSharing project&quot;&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Run bin/paster create -t pylons to create a skeleton project.&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bin/paster create -t pylons asharing&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr ignore *.egg-info&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr add asharing&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr commit -m &quot;Generated project files with paster create&quot;&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Now paster creates a directory structure that I don't like:&lt;/p&gt;

&lt;pre&gt;
AlliterationSharing/
  buildout.cfg
  bin/
  asharing/
    setup.py
    README.txt
    MANIFEST.in
    asharing/
      __init__.py
      config/
      controllers/
      templates/
      public/
&lt;/pre&gt;

&lt;p&gt;I'd like the README and setup.py to be in the top level, and I dislike
repeating 'asharing' twice in directory names.  I'll move some files around&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;cd asharing/&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr mv development.ini docs MANIFEST.in README.txt setup.* test.ini ../&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr rm ez_setup.*&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;cd ..&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr mv asharing src&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr ci -m &quot;Moved some files around&quot;&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Now the tree looks like this:&lt;/p&gt;

&lt;pre&gt;
AlliterationSharing/
  buildout.cfg
  setup.py
  README.txt
  MANIFEST.in
  bin/
  src/
    asharing/
      __init__.py
      config/
      controllers/
      templates/
      public/
&lt;/pre&gt;

&lt;p&gt;We have to tell setup.py where to find the source tree&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr diff&lt;/span&gt;
=== modified file 'MANIFEST.in'
--- MANIFEST.in	2009-09-13 13:04:00 +0000
+++ MANIFEST.in	2009-09-13 13:05:59 +0000
@@ -1,3 +1,3 @@
-include asharing/config/deployment.ini_tmpl
-recursive-include asharing/public *
-recursive-include asharing/templates *
+include src/asharing/config/deployment.ini_tmpl
+recursive-include src/asharing/public *
+recursive-include src/asharing/templates *

=== modified file 'setup.py'
--- setup.py	2009-09-13 13:04:00 +0000
+++ setup.py	2009-09-13 13:04:40 +0000
@@ -17,7 +17,8 @@
         &quot;SQLAlchemy&amp;gt;=0.5&quot;,
     ],
     setup_requires=[&quot;PasteScript&amp;gt;=1.6.3&quot;],
-    packages=find_packages(exclude=['ez_setup']),
+    packages=find_packages('src', exclude=['ez_setup']),
+    package_dir={'': 'src'},
     include_package_data=True,
     test_suite='nose.collector',
     package_data={'asharing': ['i18n/*/LC_MESSAGES/*.mo']},
&lt;/pre&gt;

&lt;p&gt;(I'm not sure if you also need to change package_data and/or setup.cfg; it's
possible that I left i18n in a broken state.  Can somebody comment on
this?)&lt;/p&gt;

&lt;p&gt;And we have to tell buildout that we've got a new Python package to enable
in the project environment&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr diff buildout.cfg &lt;/span&gt;
=== modified file 'buildout.cfg'
--- buildout.cfg	2009-09-13 12:57:21 +0000
+++ buildout.cfg	2009-09-13 13:08:05 +0000
@@ -1,8 +1,10 @@
 [buildout]
+develop = .
 parts = pylons
 
 [pylons]
 recipe = zc.recipe.egg
 eggs = Pylons
        PasteScript
+       asharing
 interpreter = python
&lt;/pre&gt;

&lt;p&gt;Now you can re-run bin/buildout and start your hello-world project&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr commit -m &quot;Include the new package in the build&quot;&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bin/buildout -N&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bin/paster serve --reload development.ini&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;

&lt;p&gt;To be continued: &lt;a href=&quot;http://mg.pov.lt/blog/pylons-with-buildout-2.html&quot;&gt;telling buildbot to create bin/test; using ctags and omelette&lt;/a&gt;.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Footnotes done well</title>
		<link href="http://mg.pov.lt/blog/footnotes-done-well.html"/>
		<id>http://mg.pov.lt/blog/footnotes-done-well.html</id>
		<updated>2009-09-11T22:58:00+00:00</updated>
		<content type="html">&lt;p&gt;I like the way footnotes are implemented here: &lt;a href=&quot;http://jacobian.org/writing/snakes-on-the-web/&quot;&gt; Snakes on the Web&lt;/a&gt;
by Jacob Kaplan-Moss.&lt;/p&gt;

&lt;center&gt;
  &lt;img src=&quot;http://mg.pov.lt/jacobian-footnote.gif&quot; width=&quot;400&quot; height=&quot;80&quot; alt=&quot;mini-screencast of animated footnote&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;&lt;small&gt;(Recorded with &lt;a href=&quot;http://people.freedesktop.org/~company/byzanz/&quot;&gt;byzanz&lt;/a&gt;.  My gif-fu
  is nonexistent or I would make it loop, but with a sufficiently long delay
  at the end to avoid irritation.  Now you have to reload the whole page if
  you missed the animation.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;I'm somewhat ambivalent about the animation effect.  On one hand, shiny!  On
the other hand, hitting tiny clickable areas is not good usability.  Still,
&lt;em&gt;shiny!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Footnotes are kind of a &lt;a href=&quot;http://mg.pov.lt/blog/footnotes-on-the-web.html&quot;&gt;personal pet-peeve of
  mine&lt;/a&gt;.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Local changes to buildout.cfg</title>
		<link href="http://mg.pov.lt/blog/buildout-local-config.html"/>
		<id>http://mg.pov.lt/blog/buildout-local-config.html</id>
		<updated>2009-08-03T17:26:00+00:00</updated>
		<content type="html">&lt;p&gt;Most of Python packages in the Zope world use &lt;a href=&quot;http://www.buildout.org&quot;&gt;Buildout&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;
svn co svn+ssh://svn.zope.org/repos/main/plone.z3cform/trunk plone.z3cform
cd plone.z3cform
python2.4 bootstrap.py
bin/buildout
bin/test -pvc
&lt;/pre&gt;

&lt;p&gt;Now suppose you want to change the buildout environment somehow, e.g.
use the current development version of zope.testing instead of whatever is
specified in buildout.cfg.  Don't edit the existing buildout.cfg (you might
accidentally commit your local debug changes), instead create a new cfg file,
e.g. test.cfg:
&lt;/p&gt;

&lt;pre&gt;
[buildout]
extends = buildout.cfg
develop += ../zope.testing

[versions]
# override any existing version pins
zope.testing =
&lt;/pre&gt;

&lt;p&gt;Now re-run buildout&lt;/p&gt;

&lt;pre&gt;
bin/buildout -c test.cfg
bin/test -pvc
&lt;/pre&gt;

&lt;p&gt;And the tests should be run with the newest zope.testing.code.&lt;/p&gt;

&lt;p&gt;Only this does not work with plone.z3cform, and I have no clue why.
It generally works with other packages (at least those that use the
zc.recipe.testrunner rather than collective.recipe.z2testrunner).
Buildout is like that sometimes :(&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Python-related updates for the last couple of months</title>
		<link href="http://mg.pov.lt/blog/happenings.html"/>
		<id>http://mg.pov.lt/blog/happenings.html</id>
		<updated>2009-07-24T23:14:00+00:00</updated>
		<content type="html">&lt;p&gt;Went to &lt;a href=&quot;http://www.europython.eu/&quot;&gt;EuroPython&lt;/a&gt;, met new people,
had a great time.&lt;/p&gt;

&lt;p&gt;Updated &lt;a href=&quot;https://launchpad.net/gtkeggdeps&quot;&gt;gtkeggdeps&lt;/a&gt;, the
interactive Python package dependency browser.  Collaborated with &lt;a href=&quot;http://thomas-lotze.de/en/&quot;&gt;Thomas Lotze&lt;/a&gt;, who maintains the engine
(&lt;a href=&quot;http://pypi.python.org/pypi/tl.eggdeps&quot;&gt;tl.eggdeps&lt;/a&gt;) that
gtkeggdeps wraps, to resolve API mismatches.  Moved the sources to &lt;a href=&quot;https://code.launchpad.net/gtkeggdeps&quot;&gt;launchpad.net&lt;/a&gt;, added a test
suite, made it use &lt;a href=&quot;http://buildout.org&quot;&gt;zc.buildout&lt;/a&gt; for convenient
development.&lt;/p&gt;

&lt;p&gt;Moved the source repository of &lt;a href=&quot;https://launchpad.net/gtimelog&quot;&gt;gtimelog&lt;/a&gt;, the simple desktop time
tracker, to &lt;a href=&quot;https://code.launchpad.net/gtimelog&quot;&gt;launchpad.net&lt;/a&gt;.
Failed to do anything else with it.  &lt;tt&gt;:-(&lt;/tt&gt;&lt;/p&gt;

&lt;p&gt;Tried to work on &lt;a href=&quot;http://code.google.com/p/jrfonseca/wiki/XDot&quot;&gt;xdot&lt;/a&gt;, wrestled with
git-svn merges, failed abysmally.  &lt;a href=&quot;http://code.google.com/p/jrfonseca/issues/detail?id=19&quot;&gt;Asked
  upstream&lt;/a&gt; to upload xdot to &lt;a href=&quot;http://pypi.python.org/pypi&quot;&gt;PyPI&lt;/a&gt;.&lt;/a&gt;

&lt;p&gt;Released &lt;a href=&quot;https://launchpad.net/zodbbrowser&quot;&gt;ZODB Browser&lt;/a&gt;, but
this deserves a separate post.&lt;/p&gt;

&lt;p&gt;Sent a bunch of &lt;a href=&quot;http://www.divmod.org/trac/wiki/DivmodPyflakes&quot;&gt;pyflakes&lt;/a&gt; patches from
&lt;a href=&quot;https://code.launchpad.net/~mgedmin/pyflakes/pyflakes-mg&quot;&gt;my old
  branch&lt;/a&gt; upstream, created &lt;a href=&quot;http://www.divmod.org/trac/query?status=new&amp;status=assigned&amp;status=reopened&amp;reporter=mgedmin&amp;component=Pyflakes&amp;order=priority&quot;&gt;trac
  tickets&lt;/a&gt; for the rest.  Wrestled with bzr-svn merges, failed abysmally.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">df</title>
		<link href="http://mg.pov.lt/blog/disk-free.html"/>
		<id>http://mg.pov.lt/blog/disk-free.html</id>
		<updated>2009-07-14T22:33:00+00:00</updated>
		<content type="html">&lt;p&gt;Modern Linux system have all sorts of fake filesystems cluttering the output
of df and mount: tmpfs, bind mounts, fuse for ~/.gvfs, etc.  I have only one
real partition on my laptop, yet mount returns 22 lines of output.&lt;/p&gt;

&lt;p&gt;Question: are there any df-like utilities that filter out all the crap and
show only interesting bits?  The standard df as well as &lt;a href=&quot;http://kassiopeia.juls.savba.sk/~garabik/software/pydf/&quot;&gt;pydf&lt;/a&gt; both
display 8 lines instead of 1.  &lt;a href=&quot;http://nickshontz.com/blog/ubuntu-hard-drive-usage&quot;&gt;Discus&lt;/a&gt; is
worse: it shows 20.  GUI utilities like &lt;a href=&quot;http://www.marzocca.net/linux/baobab/&quot;&gt;Baobab&lt;/a&gt; also suffer from this
confusion, especially bind mounts.&lt;/p&gt;

&lt;p&gt;Ironically, Ubuntu's update-motd &lt;a href=&quot;https://bugs.launchpad.net/ubuntu/+source/update-motd/+bug/399513&quot;&gt;gets
  confused&lt;/a&gt; by Ubuntu's private user directories and displays disk stats for
~/Private as if it were a real partition.  &lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Surprising old-style class behaviour</title>
		<link href="http://mg.pov.lt/blog/suprising-old-style-classes.html"/>
		<id>http://mg.pov.lt/blog/suprising-old-style-classes.html</id>
		<updated>2009-05-21T19:12:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;span&gt;Some anonymous Planet Python poster (at least I couldn't find the author's
  name on the blog)&lt;/span&gt; Christian Wyglendowski &lt;a href=&quot;http://blog.dowski.com/2009/05/21/odd-old-style-vs-new-style-class-behavior/&quot;&gt;asks
about a surprising difference between old-style and new-style classes&lt;/a&gt;.
Since the comments on their blog are closed (which you find out only after
pressing Submit), I'll answer here.&lt;/p&gt;

&lt;p&gt;The question, slightly paraphrased: given a class&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;
&lt;span class=&quot;def&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;LameContainerOld&lt;/span&gt;:
    &lt;span class=&quot;def&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;__init__&lt;/span&gt;(&lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;):
        &lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;_items&lt;/span&gt; = {&lt;span class=&quot;string&quot;&gt;'bar'&lt;/span&gt;:&lt;span class=&quot;string&quot;&gt;'test'&lt;/span&gt;}
 
    &lt;span class=&quot;def&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;__getitem__&lt;/span&gt;(&lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;, &lt;span class=&quot;name&quot;&gt;name&lt;/span&gt;):
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;_items&lt;/span&gt;[&lt;span class=&quot;name&quot;&gt;name&lt;/span&gt;]
 
    &lt;span class=&quot;def&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;__getattr__&lt;/span&gt;(&lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;, &lt;span class=&quot;name&quot;&gt;attr&lt;/span&gt;):
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;getattr&lt;/span&gt;(&lt;span class=&quot;name&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;_items&lt;/span&gt;, &lt;span class=&quot;name&quot;&gt;attr&lt;/span&gt;)
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;why does the 'in' operator work&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;container&lt;/span&gt; = &lt;span class=&quot;name&quot;&gt;LameContainerOld&lt;/span&gt;()
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;'foo'&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;container&lt;/span&gt;
&lt;span class=&quot;output&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;'bar'&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;container&lt;/span&gt;
&lt;span class=&quot;output&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;when the equivalent new-style class raises a KeyError: 0 exception? Also, why
does __getattr__ appear to be called to get the bound __getitem__ method of the
dict?&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;container&lt;/span&gt;.&lt;span class=&quot;name&quot;&gt;__getitem__&lt;/span&gt;
&lt;span class=&quot;output&quot;&gt;&amp;lt;bound method LameContainerNew.__getitem__ of {'bar': 'test'}&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;What actually happens here is that LameOldContainer.__getattr__ gets called
for special methods such as __contains__ and __repr__.  This is why (1) the
'in' check works, and (2) it appears, at first glance, that you get the wrong
__getitem__ bound method.   If you pay close attention to the output, you'll
see that it's the __getitem__ of LameOldContainer; it's just that
repr(LameOldContainer()) gets proxied through to the dict.__repr__ when you
don't expect it:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;name&quot;&gt;container&lt;/span&gt;
&lt;span class=&quot;output&quot;&gt;{'bar': 'test'}&lt;/span&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;/p&gt;Special methods never go through __getattr__ for new-style classes,
therefore neither __contains__ nor __repr__ are proxied if you make the
container inherit object.  If there's no __contains__ method, Python falls back
to the sequence protocol and starts calling __getitem__ for numbers 0 through
infinity, or until it gets an IndexError exception.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Enabling comments in PyBlosxom</title>
		<link href="http://mg.pov.lt/blog/blog-comments.html"/>
		<id>http://mg.pov.lt/blog/blog-comments.html</id>
		<updated>2009-05-16T03:13:00+00:00</updated>
		<content type="html">&lt;p&gt;I've just spent the whole night setting up blog comments.  PyBlosxom doesn't
make it painless, sadly, more like the opposite.&lt;/p&gt;

&lt;p&gt;First: don't be scared by the list of comment-related plugins on the
PyBlosxom site.  There's only one important plugin: comments.  All others
depend on it and enhance its functionality. The last three or four times I was
about to add comments to my blog I got scared at step one: evaluate the
available plugins.  Don't repeat my mistake!&lt;/p&gt;

&lt;p&gt;Second, follow the instructions carefully.  There's no shortcut.&lt;/p&gt;

&lt;p&gt;Third, fix what's broken.  Be prepared to debug the source code.  &lt;tt&gt;print
  &amp;gt;&amp;gt; sys.stderr, &quot;message&quot;&lt;/tt&gt; is your friend.&lt;/p&gt;

&lt;p&gt;Fourth, fiddle with the look (CSS and HTML).&lt;/p&gt;

&lt;p&gt;Fifth, write a blog post and eagerly await your first comments.&lt;/p&gt;

&lt;p&gt;Step 3 screams for an explanation, doesn't it?  Problem 1: the comments
plugin requires that you use categories in your blog.  I'm not (I'm holding out
for tags).  Workaround: comment out &lt;tt&gt;if entry['absolute_path']&lt;/tt&gt; check in
cb_story and cb_story_end.&lt;/p&gt;

&lt;p&gt;Problem 2: the AJAX post returns &quot;Empty response from server&quot;.  Workaround:
modify cb_story_end to call readComments directly if &lt;tt&gt;entry['num_comments']
  is
  None&lt;/tt&gt;, since cb_story, which usually does the read, is not called during
the AJAX post.&lt;/p&gt;

&lt;p&gt;Problem 3: if you enable comment moderation (by setting comment_draft_ext to
a different value from comment_ext), the AJAX post returns &quot;Empty response from
server&quot; once more.  Workaround: modify cb_prepare to notice this case and set
&lt;tt&gt;data['moderated'] = True&lt;/tt&gt;, create a new template comment-moderated and
render it in cb_story_end just like the preview template is rendered; also modify
__shouldOutput to return True when rendering comment-moderated.&lt;/p&gt;

&lt;p&gt;I'll post patches to the pyblosxom mailing tomorrow, unless I forget.  It's
6 am already, and I'm kind of sleepy.  I just hope I haven't inadvertently
broken my RSS feed or flooded any planets.&lt;/p&gt;

&lt;p&gt;Oh, and a helpful hint: don't name the post you're writing
&lt;tt&gt;comments.txt&lt;/tt&gt;, or the #comments anchor will point to the start of the
story instead of the comments.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Buildbot issues on Ubuntu Hardy</title>
		<link href="http://mg.pov.lt/blog/hardy-nfs-sighup.html"/>
		<id>http://mg.pov.lt/blog/hardy-nfs-sighup.html</id>
		<updated>2009-05-15T12:33:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: The story continues, but solution is not in sight
yet.&lt;/p&gt;

&lt;p&gt;I upgraded a buildbot slave to Ubuntu 8.04 (Hardy) recently and now I'm
getting a strange intermittent failure: sometimes
&lt;tt&gt;cp -r /local/dir /nfs/mounted/dir&lt;/tt&gt; fails
(&quot;process killed by signal 1&quot;, i.e. SIGHUP).&lt;/p&gt;

&lt;p&gt;I wonder if NFS is relevant or incidental to the issue?&lt;/p&gt;

&lt;p&gt;Google finds &lt;a href=&quot;http://osdir.com/ml/python.buildbot.devel/2005-07/msg00000.html&quot;&gt;an old
  thread from 2005&lt;/a&gt;, with a workaround (usepty=False), but I'd like to
understand the problem before applying random fixes.&lt;/p&gt;

&lt;p&gt;So far three different build steps doing &lt;tt&gt;cp -r&lt;/tt&gt; have failed during
10 days.  I've now changed them all to &lt;tt&gt;cp -rv&lt;/tt&gt;, so I can at least see
if the failure is in the middle of the copy or at the end, if it fails
again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: so far 4 build steps have failed on 6 separate
occasions:&lt;/p&gt;


&lt;pre&gt;
May  5 02:31: cp -r local-dir1 nfs-mounted-dir1  
May  6 02:31: cp -r local-dir1 nfs-mounted-dir1  
May  6 04:33: cp -r local-dir2 nfs-mounted-dir2  
May 15 02:00: cp -r local-dir3 nfs-mounted-dir3  
May 17 04:32: rm -rf nfs-mounted-dir4            
May 20 04:31: rm -rf nfs-mounted-dir4            
&lt;/pre&gt;

&lt;p&gt;I see no particular correlation between step duration and results, e.g.
the rm -rf step usually takes between 2.2 and 4.6 seconds.  The two SIGHUPs
happened after 2.4 seconds.
&lt;/p&gt;



&lt;p&gt;They all make no output.  When I changed the cp steps and added a -v, they
stopped failing, but that could be just a coincidence.&lt;/p&gt;

&lt;p&gt;We're having an email conversation with Jean-Paul Calderone (&quot;exarkun&quot;)
about the possibility of this being PTY-related, with no clear resolution
so far.&lt;/p&gt;

&lt;p&gt;And, hey, now this blog supports comments ;)&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Lęšis.lt</title>
		<link href="http://blog.miliauskas.lt/2009/05/lesislt.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-5209446679094653452</id>
		<updated>2009-05-14T02:21:05+00:00</updated>
		<content type="html">&lt;p&gt;A friend of mine has recently launched a contact lens e-shop, &lt;a href=&quot;http://www.lesis.lt&quot;&gt;lesis.lt&lt;/a&gt;.  It only ships in Lithuania at the moment, but if you're based here, have a look, you might find it useful.&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-5209446679094653452?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Expert Python Programming</title>
		<link href="http://mg.pov.lt/blog/expert-python-programming.html"/>
		<id>http://mg.pov.lt/blog/expert-python-programming.html</id>
		<updated>2009-05-08T03:09:00+00:00</updated>
		<content type="html">&lt;p&gt;It's been a while since the last &lt;a href=&quot;http://www.packtpub.com/expert-python-programming/book&quot;&gt;Expert Python
  Programming&lt;/a&gt; review on &lt;a href=&quot;http://planet.python.org&quot;&gt;Planet
  Python&lt;/a&gt;.  Y'all might've forgotten about this book by now.  Time for a
reminder?  (Actually, I'm just &lt;span&gt;lazy&lt;/span&gt; busy, and this is why this review hasn't appeared
sooner.)&lt;/p&gt;

&lt;p&gt;I received a free PDF copy of this book from Packt Publishing, with the
understanding that I'll post a review on my blog.  This is it.  Short summary:
it is a good book marred by a lot of mostly inconsequential little mistakes.
I'd give it four stars out of five.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Aside: the PDF that I could download was personalized and had my
  name and address in the footer of every page.  A very nice form of DRM that
  did not restrict my software choices for reading the book (Evince and also
  PDF Reader on Nokia Internet Tablets).&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;I bring it up here because it seems that Packt could've also applied fixes
  for &lt;a href=&quot;http://www.packtpub.com/view_errata/book/expert-python-programming&quot;&gt;the
    known errata&lt;/a&gt; to the personalized version, yet missed that opportunity.
  Perhaps it's technically more difficult than slapping a footer on every page.
  Or maybe it's better if everyone buying the book, whether in paper or in
  PDF, gets to see the same text.&lt;/small&gt;&lt;/p&gt; 

&lt;p&gt;The author (Tarek Ziade) covers a wide range of topics in the book, ranging
from syntax (probably useful for those who've been programming in Python for
quite a few years, and didn't have the time to keep up with the language
changes before picking up this book) to style, source code organization,
project infrastructure, software life cycle, documentation, testing and
optimization, and finally ending with a review of some of the popular design
patterns.  The middle parts were the most interesting for me personally.  I
learned a thing or two, disagreed with the author on a few minor points (which
are mostly a matter of preference), and managed to finish the book despite
constant irritating little pricks I feel when I notice an error (I confess I'm
a pedant.  A missing space after a colon drives me up the wall).&lt;/p&gt;

&lt;p&gt;As an example of the disagreement: I have an aversion to code-generating
tools where you have to edit the generated code by hand.  I could say more, but
this is a topic for another time.  Next, I strongly dislike &lt;tt&gt;sudo
  easy_install&lt;/tt&gt; since it scribbles onto the part of the filesystem
exclusively reserved for your OS's package management tools.  And I don't think
porting the original 23 design patterns to other programming languages is a
good way to describe what those languages are about.  (Also, &lt;tt&gt;set
  tabstop=4&lt;/tt&gt; in your .vimrc?  Heresy!  The Right Thing To Do is
 &lt;tt&gt;set &lt;em&gt;soft&lt;/em&gt;tabstop=4&lt;/tt&gt;, as all right-thinking Vim users will
 doubtlessly agree.  All hail the one true text editor! &lt;small&gt;Oh dear, now I'm
   glad I don't have comments on this blog...&lt;/small&gt;)&lt;/p&gt;

&lt;p&gt;The goodies: Chapter 1 (the bits about &lt;a href=&quot;http://docs.python.org/using/cmdline.html#envvar-PYTHONSTARTUP&quot;&gt;PYTHONSTARTUP&lt;/a&gt;
on page 19) gave me persistent history for my interactive Python prompt, nicely
complementing the coloured prompt and tab-completion I already had snarfed from
somewhere else on the net (probably Peter Norvig's &lt;a href=&quot;http://norvig.com/python-iaq.html&quot;&gt;Python IAQ&lt;/a&gt;).  Chapter 12
provided good examples of how to do profiling for time (page 281) and memory
(page 291).  I like Tarek's @profile decorator (measure time, pystones
&lt;em&gt;and&lt;/em&gt; memory at the same time).  &lt;small&gt;My &lt;a href=&quot;http://pypi.python.org/pypi/profilehooks&quot;&gt;profilehooks&lt;/a&gt; module was
not mentioned, *sniff*  ;-).&lt;/small&gt;  Chapter 13 told me about &lt;a href=&quot;http://docs.python.org/library/queue.html#Queue.Queue.join&quot;&gt;Queue.join&lt;/a&gt;
and &lt;a href=&quot;http://docs.python.org/library/queue.html#Queue.Queue.task_done&quot;&gt;task_done&lt;/a&gt;
that snuck into the stdlib with Python 2.5 without me noticing.&lt;/p&gt;



&lt;p&gt;I haven't mentioned topics covered in the book that I was already familiar
with, such as setuptools, virtualenv, zc.buildout, Sphinx, Nose, Buildbot, or
Mercurial.  Yet, in my opinion, those are the most useful parts of the book.
The breadth of the topics is amazing: I could hardly think of something that
every serious Python programmer should know that isn't wasn't mentioned.  I
believe the depth was exactly right: mention solutions that are available, show
how they feel when used and what they can do, point to the relevant web page
and then stop.  And not only tools, the descriptions of workflows (how to
organize your source trees, how to develop software consisting of multiple
packages, how to make releases), while hardly universal, are invaluable.&lt;/p&gt;

&lt;p&gt;One thing prevents this from being a perfect book: errata.  At around page
95, according to my notes, I invented a new metric of book quality: WTFs per
page, It's closely related to &lt;a href=&quot;http://www.osnews.com/story/19266/WTFs_m&quot;&gt;WTFs per minute&lt;/a&gt;, but
independent of your reading speed.  At around page 165 I got tired of making a
note of every little thing that I noticed and started just reading.  This was
considerably more enjoyable.  I hope there's a second edition will all the bugs
shaken out.  To that end, I should go through my notes again and submit them
via the online errata form.  &lt;small&gt;Yay, more work...&lt;/small&gt;&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Piano improv</title>
		<link href="http://blog.miliauskas.lt/2009/04/piano-improv.html"/>
		<id>tag:blogger.com,1999:blog-9890172.post-1820680421562431513</id>
		<updated>2009-04-15T16:40:39+00:00</updated>
		<content type="html">My today's experiments on piano:

&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9890172-1820680421562431513?l=blog.miliauskas.lt&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content>
		<author>
			<name>Gintautas Miliauskas</name>
			<email>noreply@blogger.com</email>
			<uri>http://blog.miliauskas.lt/</uri>
		</author>
		<source>
			<title type="html">Prose practice</title>
			<subtitle type="html">Life stuff and computer stuff.</subtitle>
			<link rel="self" href="http://blog.miliauskas.lt/atom.xml"/>
			<id>tag:blogger.com,1999:blog-9890172</id>
			<updated>2012-02-17T07:19:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Filing bugs on GUI apps</title>
		<link href="http://mg.pov.lt/blog/filing-bugs-on-gui-apps.html"/>
		<id>http://mg.pov.lt/blog/filing-bugs-on-gui-apps.html</id>
		<updated>2009-04-09T19:29:00+00:00</updated>
		<content type="html">&lt;p&gt;Ubuntu people want users to use apport to report bugs.  There's a command-line
tool called 'ubuntu-bug' that you can use if you know the name of the package
or at least the name of executable.  There's a &quot;Report a problem&quot; menu item
in many, but not all GUI apps.&lt;/p&gt;

&lt;p&gt;Here's what you can do if the GUI app in question doesn't have that menu
item, and you don't remember what it's called, and you're the same sort of a
crazy command-line person that I am:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;xprop|grep PID&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Click on the app's window.  Watch that shell command return a line that
looks like&lt;/p&gt;

&lt;pre&gt;
_NET_WM_PID(CARDINAL) = 807
&lt;/pre&gt;

Now run

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;ps 807&lt;/span&gt;  # substitute the real number
&lt;/pre&gt;

&lt;p&gt;You'll see the command name, e.g.&lt;/p&gt;

&lt;pre&gt;
  PID TTY      STAT   TIME COMMAND
  807 ?        S      0:02 /usr/lib/indicator-applet/indicator-applet --oaf-acti
&lt;/pre&gt;

&lt;p&gt;Now you can run&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;ubuntu-bug /usr/lib/indicator-applet/indicator-applet&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;If you're not running Jaunty, you'll need to do one more step to find the
name of the Ubuntu package:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;dpkg -S /usr/lib/indicator-applet/indicator-applet&lt;/span&gt;
indicator-applet: /usr/lib/indicator-applet/indicator-applet
&lt;/pre&gt;

&lt;p&gt;You can use that with apport-cli or on the Launchpad online bug reporting
form.&lt;/p&gt;

&lt;p&gt;For some (many?) programs you can short-circuit this trail by looking at
the WM_CLASS property instead of the _NET_WM_PID property:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;xprop|grep CLASS&lt;/span&gt;
WM_CLASS(STRING) = &quot;indicator-applet&quot;, &quot;Indicator-applet&quot;
&lt;/pre&gt;

&lt;p&gt;While there is no requirement for the window class name to match the name of
the Ubuntu package or the name of the executable, it may give you a reasonable
guess.&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Upgrade to Ubuntu Jaunty</title>
		<link href="http://mg.pov.lt/blog/upgrade-to-jaunty.html"/>
		<id>http://mg.pov.lt/blog/upgrade-to-jaunty.html</id>
		<updated>2009-04-05T23:28:00+00:00</updated>
		<content type="html">&lt;p&gt;Ubuntu 9.04 is going to be released in around three weeks.  As usual I
couldn't wait (and saw that some bugs that were irritating me every day
were fixed in Jaunty), so I upgraded to the current beta.&lt;/p&gt;

&lt;p&gt;After &lt;a href=&quot;https://bugs.launchpad.net/ubuntu/+source/update-manager/+bug/154236/comments/3&quot;&gt;a
  little hiccough&lt;/a&gt; at the beginning, the upgrade was the smoothest Ubuntu
upgrade I've ever had: I spent those two and a half hours browsing the web,
watching screencasts and chatting on IRC, while update-manager worked in the
background.  Firefox was mostly very responsive, only stuttering when
update-manager got around to unpacking openoffice.org-common.  There were few
debconf or conffile questions (one from sysstat 2 minutes into the upgrade,
then a conffile question after 1 hour and 20 minutes, then two more after 15
minutes, and one more 5 minutes later.  And the last one 10 minutes later).
There were no ugly theme changes or failing GNOME applet error messages during
the upgrade.  Near the end X-Chat automatically started showing new-style
notifications (beautiful!) and Firefoxes nicely asked to be restarted with a
fold-down notification bar.&lt;/p&gt;

&lt;p&gt;Nice.  Now, after a reboot things were not so nice: I couldn't login.
After typing in my password and a couple of mode changes I was kicked back
to the GDM prompt.  I panicked and started logging into the text consoles
and trying to run startx, quite in vain, since when I just tried gdm again
it worked fine.&lt;/p&gt;

&lt;p&gt;The intel video driver feels slower, as promised by the release notes,
but it's acceptable as long as you don't try to rotate the external screen.
Then it's horrible and unusable—a regression since Intrepid.  I'll have
to retry with UXA.&lt;/p&gt;

&lt;p&gt;Compiz failed to enable a plugin (GNOME Compatibility), so a couple of
key bindings didn't work (Alt+F1 to get the menu, Alt+F2 to get the run dialog,
my custom keybinding to open a terminal) until someone on FreeNode told me
what to enable.&lt;/p&gt;

&lt;p&gt;The Flash plugin is now swfdec, and it is unable to cope with Youtube music
videos—the sound is all choppy.  I'm wondering if this is swfdec's fault,
pulseaudio's fault (it's common knowledge that all audio problems stem from
pulseaudio, right? ;) or X.org's fault (top shows it's X that's eating 90% CPU
when swfdec is trying to play a video).&lt;/p&gt;

&lt;p&gt;A lot of very irritating bugs are gone.  I don't need to restart Compiz
after playing with xrandr.  X doesn't crash after I play with xrandr.
Two-finger scrolling with the Synaptics touchpad doesn't produce phantom
scroll-down-17-pages events when I take my fingers off the touchpad.  The
GNOME panels don't migrate to the external screen when I play with xrandr
(but one of them &lt;a href=&quot;https://bugs.launchpad.net/ubuntu/+source/gnome-panel/+bug/355848&quot;&gt;jumps
  from the bottom to the top&lt;/a&gt; when I play some more).  The new splash
screen has a pretty gradient for its progress bar (but is displayed off-center,
maybe because I added vga=872 to my GRUB kernel options list to avoid ugly
stretching of text consoles).  X.org no longer distorts the aspect ratio of
1024x768 when stretching it to fit the 1280x800 screen—now I get sensible
black bars on the sides. &lt;strong&gt;The new notification bubbles are
  beautiful!&lt;/strong&gt;.  I could stare at them all day.  (But the new indicator
applet &lt;a href=&quot;https://bugs.launchpad.net/ubuntu/+source/indicator-applet/+bug/334490&quot;&gt;is
  ugly&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Overall I'm happy.  A bunch of very irritating bugs were replaced with
a smaller bunch of somewhat less irritating bugs.  The intel video slowdown
scares me a bit, though, but the prettiness of the notification bubbles
outweigh everything else.  What can I say, I like pretty things—Ooh,
shiny!&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Submitting patches the Launchpad way</title>
		<link href="http://mg.pov.lt/blog/smooth-bug-reporting.html"/>
		<id>http://mg.pov.lt/blog/smooth-bug-reporting.html</id>
		<updated>2009-04-05T21:45:00+00:00</updated>
		<content type="html">&lt;p&gt;Today I happened to read about &lt;a href=&quot;http://pypi.python.org/pypi/lazr.enum&quot;&gt;lazr.enum&lt;/a&gt; in a mailing list.
I went to &lt;a href=&quot;http://pypi.python.org/pypi/lazr.enum&quot;&gt;the PyPI page&lt;/a&gt; and
saw raw &lt;a href=&quot;http://docutils.sourceforge.net/rst.html&quot;&gt;ReStructuredText&lt;/a&gt;
markup instead of a nicely formatted page.  Now I know from prior experience
that this happens when the package's description has an error in the markup.
I thought I'd report a bug and provide a patch.&lt;/p&gt;

&lt;p&gt;Leap of knowledge: since I know lazr.enum was created by the Launchpad.net
team I could safely assume they were keeping the sources in Launchpad.  Therefore
I was pretty sure I could get them with&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr branch lp:lazr.enum&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;so I ran that command and it worked.&lt;/p&gt;

&lt;p&gt;Next I looked at setup.py to see how it produces the long_description field.
It was reading the contents of a couple of text files, one of them being
src/lazr/enum/README.txt.  I looked at that and saw a
&lt;tt&gt;.. toc-tree:&lt;/tt&gt; directive that does not exists in plain docutils
(it's a &lt;a href=&quot;http://sphinx.pocoo.org/&quot;&gt;Sphinx&lt;/a&gt; extension).&lt;/p&gt;

&lt;p&gt;I added up a couple of lines to setup.py to strip that out, tested it
(with &lt;tt&gt;setup.py --long-description &amp;gt; test.rst; restview test.rst&lt;/tt&gt;)
committed to my local branch, and created a bug report in Launchpad.  Then I
was a bit lost, since I didn't know how to make my fix available.  Attach a
patch?  Maybe, but I wanted to see if this distributed version control thing is
good for anything else.&lt;/p&gt;

&lt;p&gt;I thought that first I'd make that branch public, and then see if there
was a way to link it to the bug report.  I ran&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;prompt&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;typing&quot;&gt;bzr push lp:~mgedmin/lazr.enum/pypi-fix&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;which took a few seconds to create a new public branch on Launchpad with my
fix in it (it would be nice if I didn't have to explicitly specify my Launchpad
username and the project name—both of which bzr already knows—and
just specify the name of the branch).  Then I went back to my bug report and
saw an option to link it to a branch.  There was a search field in the popup
that found my &quot;~mgedmin/lazr.enum/pypi-fix&quot; easily enough when I pasted it
into the search box.&lt;/p&gt;

&lt;p&gt;After clicking on the branch, I saw a &quot;propose a merge&quot; option.  I did that
and Launchpad sent an email to the developers asking them to merge my fix.&lt;/p&gt;

&lt;p&gt;I made one mistake, I think: I should've created the bug report
&lt;em&gt;first&lt;/em&gt;, and then mentioned the bug number in my commit message (with
&lt;tt&gt;bzr commit --fixes=NNN&lt;/tt&gt;, although here I'm suddenly not sure if the bug
number should be left bare, or prefixed with something like &quot;lp&quot; to indicate it
was a Launchpad bug number?).&lt;/p&gt;

&lt;p&gt;Other than that it was a pretty smooth experience.  When will I be able to
do that for Ubuntu packages?&lt;/p&gt;</content>
		<author>
			<name>Marius Gedminas</name>
			<uri>http://mg.pov.lt/blog</uri>
		</author>
		<source>
			<title type="html">Random notes from mg</title>
			<subtitle type="html">a blog by Marius Gedminas</subtitle>
			<link rel="self" href="http://mg.pov.lt/blog//?flav=rss"/>
			<id>http://mg.pov.lt/blog//?flav=rss</id>
			<updated>2012-02-23T04:19:03+00:00</updated>
		</source>
	</entry>

</feed>

