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

<channel>
	<title>numerodix blog &#187; code</title>
	<atom:link href="http://www.matusiak.eu/numerodix/blog/index.php/category/techno-babble/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.matusiak.eu/numerodix/blog</link>
	<description>A blog about nothing</description>
	<lastBuildDate>Sun, 12 Feb 2012 12:20:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>re: for the man with many repos</title>
		<link>http://www.matusiak.eu/numerodix/blog/index.php/2011/11/13/re-for-the-man-with-many-repos/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2011/11/13/re-for-the-man-with-many-repos/#comments</comments>
		<pubDate>Sun, 13 Nov 2011 14:21:30 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=3323</guid>
		<description><![CDATA[As it often goes, re is a tool that grew out of a bunch of shell scripts. I kept adding stuff to the scripts for a long time, but eventually it went beyond the point of being manageable.
The tool addresses three different issues:

Cloning/pulling multiple repos in one step.
Keeping repo clones in sync across machines.
Better handling [...]]]></description>
			<content:encoded><![CDATA[<p>As it often goes, <code>re</code> is a tool that grew out of a bunch of shell scripts. I kept adding stuff to the scripts for a long time, but eventually it went beyond the point of being manageable.</p>
<p>The tool addresses three different issues:</p>
<ul>
<li>Cloning/pulling multiple repos in one step.</li>
<li>Keeping repo clones in sync across machines.</li>
<li>Better handling of local tracking branches.</li>
</ul>
<h3>Listing repos</h3>
<p>Let&#8217;s start with a basic situation. I&#8217;ve cloned some of my repos on github:</p>
<pre class="bash">$ ls -F
galleryforge/  italian-course/  re/  spiderfetch/</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/re_ls_repos.txt">re_ls_repos.txt</a></p>
<p>I run <code>re list</code> to scan the current path recursively and discover all the repos that exist:</p>
<pre class="bash">$ re list
<span style="color: #66cc66;">&#91;</span>galleryforge:git<span style="color: #66cc66;">&#93;</span>
    origin.url = git@github.com:numerodix/galleryforge.git
<span style="color: #66cc66;">&#91;</span>italian-course:git<span style="color: #66cc66;">&#93;</span>
    origin.url = git@github.com:numerodix/italian-course.git
<span style="color: #66cc66;">&#91;</span>re:git<span style="color: #66cc66;">&#93;</span>
    origin.url = git@github.com:numerodix/re.git
<span style="color: #66cc66;">&#91;</span>spiderfetch:git<span style="color: #66cc66;">&#93;</span>
    origin.url = git@github.com:numerodix/spiderfetch.git
&gt; Run with -u to update .reconfig</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/re_list.txt">re_list.txt</a></p>
<p>It creates a configuration file called <code>.reconfig</code> that contains the output you see there. By default it doesn&#8217;t overwrite the config, just shows you the result of the detection action. Pass <code>-u</code> to update it.</p>
<p>This file format is similar to <code>.git/config</code>. Every block is a repo, and <code>:git</code> is a tag saying &#8220;this is a git repo&#8221;. (By design <code>re</code> is vcs agnostic, but in practice I only ever use git and the only backend right now is for git. It probably smells a lot of git in any case.)</p>
<p>Every line inside a block represents a remote (git terminology). By default there is only one. If you add add a remote in the repo and re-run <code>re list</code> it will detect it. But it will assume that <code>origin</code> is the canonical remote (more on why this matters later).</p>
<h3>Pulling repos</h3>
<p>Now let&#8217;s say I want to pull all those repos to sync them with github. I use (you guessed it) <code>re pull</code>:</p>
<pre class="bash">$ re pull
&gt; Fetching galleryforge
&gt; Fetching italian-course
&gt; Fetching re
&gt; Fetching spiderfetch
&gt; Merging galleryforge
&gt; Merging italian-course
&gt; Merging re
&gt; Merging spiderfetch
-&gt; Setting up <span style="color: #000066;">local</span> tracking branch ruby-legacy
-&gt; Setting up <span style="color: #000066;">local</span> tracking branch sqlite-try
-&gt; Setting up <span style="color: #000066;">local</span> tracking branch db-subclass
-&gt; Setting up <span style="color: #000066;">local</span> tracking branch next</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/re_pull.txt">re_pull.txt</a></p>
<p>As you can see it does fetching and merging in separate steps. Fetching is where all the network traffic happens, merging is local, which is why I think it&#8217;s nice to separate them. (But there are <a href="http://longair.net/blog/2009/04/16/git-fetch-and-merge/">more reasons to avoid git pull</a>.)</p>
<p>What it also does is set up local tracking branches against the canonical remote. The canonical remote is the one listed <em>first</em> in <code>.reconfig</code>. So it doesn&#8217;t matter what it&#8217;s called, but it&#8217;s a good idea to make it <code>origin</code>, because that&#8217;s what <code>re list</code> will assume when you use it to update <code>.reconfig</code> after you add/remove repos.</p>
<p>It handles local tracking branches only against one remote, because if both <code>origin</code> and <code>sourceforge</code> have a branch called <code>stable</code> then it&#8217;s not clear which one of those the local branch <code>stable</code> is supposed to track. I find this convention quite handy, but your mileage may vary.</p>
<p>If I later remove the branch <code>ruby-legacy</code> from github and run <code>re pull</code>, it&#8217;s going to detect that I have a local tracking branch that is pointing at something that doesn&#8217;t exist anymore:</p>
<pre class="bash">$ re pull spiderfetch
&gt; Fetching spiderfetch
&gt; Merging spiderfetch
-&gt; Stale <span style="color: #000066;">local</span> tracking branch ruby-legacy, remove? <span style="color: #66cc66;">&#91;</span>yN<span style="color: #66cc66;">&#93;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/re_pull_stale_local_tracking.txt">re_pull_stale_local_tracking.txt</a></p>
<h3>Scaling beyond a single machine</h3>
<p>Now, <code>re</code> helps you manage multiple repos, but it also helps you keep your repos synced across machines. <code>.reconfig</code> is a kind of spec for what you want your repo-hosting directory to contain, so you can just ship it to a different machine, <code>re pull</code> and it will clone all the repos over there, set up local tracking branches, all the same stuff.</p>
<p>In fact, why not keep <code>.reconfig</code> <em>itself</em> in a repo, which again you can push to a central location and from which you can pull onto all your machines:</p>
<pre class="bash">$ re list
<span style="color: #66cc66;">&#91;</span>.:git<span style="color: #66cc66;">&#93;</span>
    origin.url = user@host:~/repohost.git
<span style="color: #66cc66;">&#91;</span>galleryforge:git<span style="color: #66cc66;">&#93;</span>
    origin.url = git@github.com:numerodix/galleryforge.git
<span style="color: #66cc66;">&#91;</span>italian-course:git<span style="color: #66cc66;">&#93;</span>
    origin.url = git@github.com:numerodix/italian-course.git
<span style="color: #66cc66;">&#91;</span>re:git<span style="color: #66cc66;">&#93;</span>
    origin.url = git@github.com:numerodix/re.git
<span style="color: #66cc66;">&#91;</span>spiderfetch:git<span style="color: #66cc66;">&#93;</span>
    origin.url = git@github.com:numerodix/spiderfetch.git
&gt; Run with -u to update .reconfig</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/re_list_reconfig.txt">re_list_reconfig.txt</a></p>
<p>It does not manage <code>.gitignore</code>, so you have to do that yourself.</p>
<h3>Advanced uses</h3>
<p>Those are the basics of <code>re</code>, but the thing to realize is that it doesn&#8217;t limit you to a situation like the one we&#8217;ve seen in the examples so far, with a single directory that contains repos. You can have repos at any level of depth, you can have <code>.reconfig</code>s at different levels too, and you can then use a single <code>re pull -r</code> to recursively pull absolutely everything in one step.</p>
<p>Get it from github:</p>
<ul>
<li><a href="https://github.com/numerodix/re">re</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2011/11/13/re-for-the-man-with-many-repos/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>nametrans: renaming with search/replace</title>
		<link>http://www.matusiak.eu/numerodix/blog/index.php/2011/03/25/nametrans-renaming-with-search-replace/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2011/03/25/nametrans-renaming-with-search-replace/#comments</comments>
		<pubDate>Fri, 25 Mar 2011 17:06:14 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=3159</guid>
		<description><![CDATA[Keeping filenames properly organized is a pain when all you have available for the job is renaming files one by one. It&#8217;s most disheartening when there is something you have to do to all the files in the current directory. This is where a method of renaming by search and replace, just as in a [...]]]></description>
			<content:encoded><![CDATA[<p>Keeping filenames properly organized is a pain when all you have available for the job is renaming files one by one. It&#8217;s most disheartening when there is something you have to do to all the files in the current directory. This is where a method of renaming by search and replace, just as in a text document, would help immensely. Something like this perhaps:</p>
<p><img class="aligncenter size-full wp-image-3191" title="nametrans_ss" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_ss.png" alt="nametrans_ss" width="293" height="64" /></p>
<h3>Simple substitutions</h3>
<p>The simplest use is just a straight search and replace. All the files in the current directory will be tried to see if they match the search string.</p>
<pre class="bash">$ nametrans.py <span style="color: #ff0000;">"apple"</span> <span style="color: #ff0000;">"orange"</span>
 * I like apple.jpg    -&gt; I like orange.jpg
 * pineapple.jpg       -&gt; pineorange.jpg
 * The best apples.jpg -&gt; The best oranges.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_applelist">nametrans_applelist</a></p>
<p>There are also a number of options that simply common tasks. Options can be combined and the order in which they are set does not matter.</p>
<p><strong>Ignore case</strong></p>
<p>Matching against strings with different case is easy.</p>
<pre class="bash">$ nametrans.py -i <span style="color: #ff0000;">"pine"</span> <span style="color: #ff0000;">"wood"</span>
 * pineapple.jpg -&gt; woodapple.jpg
 * Pinetree.jpg  -&gt; woodtree.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_ignorecase">nametrans_ignorecase</a></p>
<p><strong>Literal</strong></p>
<p>The search string is actually a regular expression. If you use characters that have a special meaning in regular expressions then set the literal option and it will do a standard search and replace. (If you don&#8217;t know what regular expressions are, just use this option always and you&#8217;ll be fine.)</p>
<pre class="bash">$ nametrans.py --lit <span style="color: #ff0000;">"(1)"</span> <span style="color: #ff0000;">"1"</span>
 * funny picture <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>.jpg -&gt; funny picture <span style="color: #cc66cc;">1</span>.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_literal">nametrans_literal</a></p>
<p><strong>Root</strong></p>
<p>If you prefer the spelling &#8220;oranje&#8221; instead of &#8220;orange&#8221; you can replace the G with a J. This will also match the extension &#8220;.jpg&#8221;, however. So in a case like this set the root option to consider only the root of the filename for matching.</p>
<pre class="bash">$ nametrans.py --root <span style="color: #ff0000;">"g"</span> <span style="color: #ff0000;">"j"</span>
 * I like orange.jpg    -&gt; I like oranje.jpg
 * pineorange.jpg       -&gt; pineoranje.jpg
 * The best oranges.jpg -&gt; The best oranjes.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_root">nametrans_root</a></p>
<h3>Hygienic uses</h3>
<p>Short of specific cases of transforms, there are some general options that have to do with maintaining consistency in filenames that can apply to many scenarios.</p>
<p><strong>Neat</strong></p>
<p>The neat option tries to make filenames neater by capitalizing words and removing characters that are typically junk. It also does some simple sanity checks like removing spaces or underscores at the ends of the name.</p>
<pre class="bash">$ nametrans.py --neat
 * _funny___picture_<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>.jpg -&gt; Funny - Picture <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>.jpg
 * i like apple.jpg         -&gt; I Like Apple.jpg
 * i like peach.jpg         -&gt; I Like Peach.jpg
 * pineapple.jpg            -&gt; Pineapple.jpg
 * the best apples.jpg      -&gt; The Best Apples.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_neat">nametrans_neat</a></p>
<p><strong>Lower</strong></p>
<p>If you prefer lowercase, here is the option for you.</p>
<pre class="bash">$ nametrans.py --lower
 * Funny - Picture <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>.jpg -&gt; funny - picture <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>.jpg
 * I Like Apple.jpg        -&gt; i like apple.jpg
 * I Like Peach.JPG        -&gt; i like peach.jpg
 * Pineapple.jpg           -&gt; pineapple.jpg
 * The Best Apples.jpg     -&gt; the best apples.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_lower">nametrans_lower</a></p>
<p>If you want the result of neat and then lowercase, just set them both. (If you like underscores instead of spaces, also set <code>--under</code>.)</p>
<h3>Non-flat uses</h3>
<p>Presuming the files are named consistently you can throw them into separate directories by changing some character into the path separator.</p>
<p>Note: On Windows, the path separator is \ and you may have to write it as &#8220;\\\\&#8221;.</p>
<pre class="bash">$ nametrans.py <span style="color: #ff0000;">" - "</span> <span style="color: #ff0000;">"/"</span>
 * france - nice - seaside.jpg -&gt; france/nice/seaside.jpg
 * italy - rome.jpg            -&gt; italy/rome.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_prefixasdir">nametrans_prefixasdir</a></p>
<p>The inverse operation is to flatten the entire directory tree so that all the files are put in the current directory. The empty directories are removed.</p>
<pre class="bash">$ nametrans.py --flatten
 * france/nice/seaside.jpg -&gt; france - nice - seaside.jpg
 * italy/rome.jpg          -&gt; italy - rome.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_flatten">nametrans_flatten</a></p>
<p>In general, the recursive option will take all files found recursively and make them available for substitutions. It can be combined with other options to do the same thing recursively as would otherwise happen in a single directory.</p>
<pre class="bash">$ nametrans.py -r --neat
 * france/nice/seaside.jpg -&gt; France/Nice/Seaside.jpg
 * italy/rome.jpg          -&gt; Italy/Rome.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_recursive">nametrans_recursive</a></p>
<p>In recursive mode the whole path will be matched against. You can make sure the matching only happens against the file part of the path with <code>--files</code> or only the directory part with <code>--dirs</code>.</p>
<h3>Special uses</h3>
<p><strong>Directory name</strong></p>
<p>Sometimes filenames carry no useful information and serve only to maintain them in a specific order. The typical case is pictures from your camera that have meaningless sequential names, often with gaps in the sequence where you have deleted some pictures that didn&#8217;t turn out well. In this case you might want to just use the name of the directory to rename all the files sequentially.</p>
<pre class="bash">$ nametrans.py -r --dirname
 * rome/DSC00001.jpg -&gt; rome/rome <span style="color: #cc66cc;">1</span>.jpg
 * rome/DSC00007.jpg -&gt; rome/rome <span style="color: #cc66cc;">2</span>.jpg
 * rome/DSC00037.jpg -&gt; rome/rome <span style="color: #cc66cc;">3</span>.jpg
 * rome/DSC00039.jpg -&gt; rome/rome <span style="color: #cc66cc;">4</span>.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_dirname">nametrans_dirname</a></p>
<p><strong>Rename sequentially</strong></p>
<p>Still in the area of sequential names, at times the numbers have either too few leading zeros to be sorted correctly or too many unnecessary zeros. With this option you can specify how many leading zeros you want (and if you don&#8217;t say how many, it will find out on its own). Based on <a href="http://www.matusiak.eu/numerodix/blog/index.php/2008/05/01/renaming-sequentially/">an old piece of code</a> that has been integrated.</p>
<pre class="bash">$ nametrans.py -r --renseq <span style="color: #cc66cc;">1</span>:<span style="color: #cc66cc;">3</span>
 * rome/<span style="color: #cc66cc;">1</span>.jpg   -&gt; rome/<span style="color: #cc66cc;">001</span>.jpg
 * rome/<span style="color: #cc66cc;">7</span>.jpg   -&gt; rome/<span style="color: #cc66cc;">007</span>.jpg
 * rome/<span style="color: #cc66cc;">14</span>.jpg  -&gt; rome/<span style="color: #cc66cc;">014</span>.jpg
 * rome/<span style="color: #cc66cc;">18</span>.jpg  -&gt; rome/<span style="color: #cc66cc;">018</span>.jpg
 * rome/<span style="color: #cc66cc;">123</span>.jpg -&gt; rome/<span style="color: #cc66cc;">123</span>.jpg</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/nametrans_renseq">nametrans_renseq</a></p>
<p>The argument required here means <code>field:width</code>, so in a name like:</p>
<blockquote><p>series14_angle3_shot045.jpg</p></blockquote>
<p>the number 045 can be shortened to 45 with &#8220;3:2&#8243; (third field from the beginning) or &#8220;-1:2&#8243; (first field from the end).</p>
<p>Get it from sourceforge:</p>
<ul>
<li><a href="http://nametrans.sourceforge.net/">nametrans</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2011/03/25/nametrans-renaming-with-search-replace/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ansicolor: because the view is better in colors</title>
		<link>http://www.matusiak.eu/numerodix/blog/index.php/2010/08/06/ansicolor-because-the-view-is-better-in-colors/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2010/08/06/ansicolor-because-the-view-is-better-in-colors/#comments</comments>
		<pubDate>Fri, 06 Aug 2010 13:35:59 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2730</guid>
		<description><![CDATA[If you&#8217;re a coder you probably try to modularize everything to death on a daily basis. If not, your practices are a little suspicious.   Alas, it&#8217;s not so easy to knock out something that I can say with confidence will be reusable in the future. One piece of functionality I keep reimplementing is [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re a coder you probably try to modularize everything to death on a daily basis. If not, your practices are a little suspicious. <img src='http://www.matusiak.eu/numerodix/blog/wp-includes/images/smilies/nervous.png' alt=':nervous:' class='wp-smiley' />  Alas, it&#8217;s not so easy to knock out something that I can say with confidence will be reusable in the future. One piece of functionality I keep reimplementing is output in colors, because it&#8217;s hugely helpful to making things look more distinct. The first time I wrote this module I knew I would be using it again and I wished to make it nice and reusable, but I didn&#8217;t know what the future uses would be. So I put that off until &#8220;later&#8221;. In the meantime I copy/pasted it a couple of times into other projects. Shameful, but effective.</p>
<p>I finally got around to organizing these types of bits that have no specific place of their own into a new github repository, appropriately named &#8220;pybits&#8221;. It holds the <a href="http://www.matusiak.eu/numerodix/blog/index.php/2010/04/25/pretty-printing-for-everyone/">pretty printer</a> and this rewritten ansicolor module, and it&#8217;ll probably grow with the ages.</p>
<p>But to business. Anyone spitting out ansi escapes who has figured out the system knows it&#8217;s trivial to make a color chart. So to keep the tradition going, here&#8217;s proof that ansicolor is able to enumerate the colors:</p>
<p><img class="aligncenter size-full wp-image-2737" title="ansicolor_chart" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/ansicolor_chart.png" alt="ansicolor_chart" width="333" height="337" /></p>
<p>Notice that section at the bottom about highlighting colors. As you might be able to deduce by sheer logic, black and white are not great colors for highlighting something in a terminal, because they are typically used respectively as the background and foreground of the term (or vice versa). (The colors of a term can actually be anything, but black and white are the common ones. Ideally, code should detect this at runtime, but I don&#8217;t know of a way to check for this. Besides, lots of programs [eg. portage] do make this assumption also.) So the highlighting colors are supposed to be useful for when you want to output a wall of text and mark something in the middle of it, so the user can spot it.</p>
<p>Suppose you are (as I have been in the past) developing a regular expression and you can&#8217;t get it right on the first try (yeah, unbelievable, I know). Well, what you do is highlight the string so you can see how the matching worked out:</p>
<p><img class="aligncenter size-full wp-image-2751" title="ansicolor_1regex" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/ansicolor_1regex.png" alt="ansicolor_1regex" width="242" height="46" /></p>
<p>Regular expressions tend to get hairy (yes way) so it helps to compare their results when you&#8217;re trying to unify two half-working variants into one. Adding a second regex will show the matches from both. Where they overlap the styling is bold:</p>
<p><img class="aligncenter size-full wp-image-2753" title="ansicolor_2regex" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/ansicolor_2regex.png" alt="ansicolor_2regex" width="242" height="60" /></p>
<p>Think of the green highlighting as a layer of paint on the wall. You then paint a layer of yellow on top, but you don&#8217;t cover exactly the same area. So where the green wasn&#8217;t painted over it&#8217;s still green. Where the yellow covered it, the paint is thicker. And where the yellow didn&#8217;t overlap the green it&#8217;s just plain yellow.</p>
<p>Adding a third regex potentially produces segments highlighted three layers thick, so there the color becomes reverse.</p>
<p><img class="aligncenter size-full wp-image-2756" title="ansicolor_3regex" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/ansicolor_3regex.png" alt="ansicolor_3regex" width="243" height="76" /></p>
<p>And then bold <em>and</em> reverse.</p>
<p><img class="aligncenter size-full wp-image-2759" title="ansicolor_4regex" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/ansicolor_4regex.png" alt="ansicolor_4regex" width="242" height="89" /></p>
<p>ansicolor doesn&#8217;t support background colors, but that&#8217;s a product of my use so far, I&#8217;ve never needed it. I don&#8217;t think they improve readability.</p>
<p>You will find this cutting edge technology in the repo:</p>
<ul>
<li><a href="http://github.com/numerodix/pybits">pybits</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2010/08/06/ansicolor-because-the-view-is-better-in-colors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>pretty printing for everyone!</title>
		<link>http://www.matusiak.eu/numerodix/blog/index.php/2010/04/25/pretty-printing-for-everyone/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2010/04/25/pretty-printing-for-everyone/#comments</comments>
		<pubDate>Sun, 25 Apr 2010 16:32:00 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2651</guid>
		<description><![CDATA[I&#8217;ve been toying with the idea of trying my hand a generic pretty printer module for a while. Lately I&#8217;ve had to deal with cyclic object graphs and things like that, where having a dump of the data is pretty handy. Granted there is a pprint module in the standard library. But what it does [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been toying with the idea of trying my hand a generic pretty printer module for a while. Lately I&#8217;ve had to deal with cyclic object graphs and things like that, where having a dump of the data is pretty handy. Granted there is a <code>pprint</code> module in the standard library. But what it does is format and print iterables (lists, dicts, tuples..), it doesn&#8217;t attempt to show you the contents of an object. Of course, when you&#8217;re messing with objects this is very useful to have.</p>
<p>So I thought that I would build a recursive iterable that I can give to <code>pprint</code>. Here&#8217;s an example:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">class</span> Node<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    classatt = <span style="color: #483d8b;">'hidden'</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">name</span> = name
&nbsp;
a, b, c, d = Node<span style="color: black;">&#40;</span><span style="color: #483d8b;">'A'</span><span style="color: black;">&#41;</span>, Node<span style="color: black;">&#40;</span><span style="color: #483d8b;">'B'</span><span style="color: black;">&#41;</span>, Node<span style="color: black;">&#40;</span><span style="color: #483d8b;">'C'</span><span style="color: black;">&#41;</span>, Node<span style="color: black;">&#40;</span><span style="color: #483d8b;">'D'</span><span style="color: black;">&#41;</span>
a.<span style="color: black;">refs</span> = <span style="color: black;">&#91;</span>b, d<span style="color: black;">&#93;</span>
b.<span style="color: black;">refs</span> = <span style="color: black;">&#91;</span>c<span style="color: black;">&#93;</span>
c.<span style="color: black;">refs</span> = <span style="color: black;">&#91;</span>a<span style="color: black;">&#93;</span>
d.<span style="color: black;">refs</span> = <span style="color: black;">&#91;</span>c<span style="color: black;">&#93;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/pretty_printing_object.py">pretty_printing_object.py</a></p>
<p>This will give you:</p>
<pre class="python"><span style="color: black;">&#123;</span><span style="color: #483d8b;">'__type__'</span>: <span style="color: #483d8b;">'&lt;Node {id0}&gt;'</span>,
 <span style="color: #483d8b;">'name'</span>: <span style="color: #483d8b;">"'A'"</span>,
 <span style="color: #483d8b;">'refs'</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'__type__'</span>: <span style="color: #483d8b;">'&lt;Node {id1}&gt;'</span>,
           <span style="color: #483d8b;">'name'</span>: <span style="color: #483d8b;">"'B'"</span>,
           <span style="color: #483d8b;">'refs'</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'__type__'</span>: <span style="color: #483d8b;">'&lt;Node {id2}&gt;'</span>,
                     <span style="color: #483d8b;">'name'</span>: <span style="color: #483d8b;">"'C'"</span>,
                     <span style="color: #483d8b;">'refs'</span>: <span style="color: black;">&#91;</span><span style="color: #483d8b;">'dup &lt;Node {id0}&gt;'</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span>,
          <span style="color: black;">&#123;</span><span style="color: #483d8b;">'__type__'</span>: <span style="color: #483d8b;">'&lt;Node {id3}&gt;'</span>,
           <span style="color: #483d8b;">'name'</span>: <span style="color: #483d8b;">"'D'"</span>,
           <span style="color: #483d8b;">'refs'</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'__type__'</span>: <span style="color: #483d8b;">'&lt;Node {id2}&gt;'</span>,
                     <span style="color: #483d8b;">'name'</span>: <span style="color: #483d8b;">"'C'"</span>,
                     <span style="color: #483d8b;">'refs'</span>: <span style="color: black;">&#91;</span><span style="color: #483d8b;">'dup &lt;Node {id0}&gt;'</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/pretty_printing_output.py">pretty_printing_output.py</a></p>
<p>There are two things being shown here:</p>
<ul>
<li>node C is reachable through ABC <em>and</em> ADC.</li>
<li>A takes part in two cycles: ABCA and ADCA.</li>
</ul>
<p>It would be nice to have a way to see this from the output. So aside from the object attributes themselves there is also a <code>__type__</code> attribute which tells you the type that you&#8217;re looking at. And it has a marker of the form <code>{id1}</code>, where <code>id1</code> is an identifier for this object, so that you can see where it pops up in a different part of the graph.</p>
<p>Now, suppose we follow A to B to C and then to A. We are now seeing A for the second time. Instead of printing the object again we print a duplicate marker: <code>dup &lt;Node {id0}&gt;</code>. The identifier is supposed to be vim <code>*</code> friendly, so if you pipe the output to vim, put the cursor over it and hit <code>*</code> (also might want to do <code>set hlsearch</code>) then you&#8217;ll see it light up all the other instances of it in the graph.</p>
<p><img class="alignnone size-full wp-image-2659" title="pretty_printing_gvim" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/pretty_printing_gvim.png" alt="pretty_printing_gvim" width="518" height="400" /></p>
<p>Well, that&#8217;s all for now. It&#8217;s definitely not the last word in pretty printing, but it&#8217;s useful already.</p>
<p>I thought maybe github&#8217;s gists would be appropriate for something like this:</p>
<ul>
<li><a href="http://gist.github.com/378503">pp module</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2010/04/25/pretty-printing-for-everyone/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>how do you structure your python codebase?</title>
		<link>http://www.matusiak.eu/numerodix/blog/index.php/2010/04/13/how-do-you-structure-your-python-codebase/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2010/04/13/how-do-you-structure-your-python-codebase/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 18:22:30 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2576</guid>
		<description><![CDATA[One thing that&#8217;s awesome in python is having a small codebase that can fit in a single directory. It&#8217;s a comfy setting, everything is right there at your fingertips, no directory traversal needed to get a hold of a file.
Flat structure
Let&#8217;s check out one right now:
./frame.py
./master.py
./mystring.py
./page.py
./sentence.py
./user.py
Download this code: python_codebase_structure_flat.txt
And here&#8217;s the import relationship between them:

Easy, [...]]]></description>
			<content:encoded><![CDATA[<p>One thing that&#8217;s awesome in python is having a small codebase that can fit in a single directory. It&#8217;s a comfy setting, everything is right there at your fingertips, no directory traversal needed to get a hold of a file.</p>
<h3>Flat structure</h3>
<p>Let&#8217;s check out one right now:</p>
<pre class="bash">./frame.py
./master.py
./mystring.py
./page.py
./sentence.py
./user.py</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_codebase_structure_flat.txt">python_codebase_structure_flat.txt</a></p>
<p>And here&#8217;s the import relationship between them:</p>
<p style="text-align: left;"><img class="alignnone size-full wp-image-2575" title="python_codebase_structure" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_codebase_structure.png" alt="python_codebase_structure" width="448" height="347" /></p>
<p style="text-align: left;">Easy, straightforward. I can execute any one of the files by itself to make sure the syntax is correct or to run an &#8220;if __main__&#8221; style unit test on it.</p>
<h3 style="text-align: left;">Tree structure</h3>
<p style="text-align: left;">But suppose the codebase is expanding and I decide I have to get a bit more structured? I devise a directory structure like this:</p>
<p style="text-align: left;">
<pre class="bash">./media/book/__init__.py
./media/book/page.py
./media/book/sentence.py
./media/__init__.py
./media/master.py
./media/movie/frame.py
./media/movie/__init__.py
./media/mystring.py
./user.py</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_codebase_structure_tree.txt">python_codebase_structure_tree.txt</a></p>
</p>
<p style="text-align: left;">The same files, but now with __init__.py files all over the codebase to tell python to treat each directory as a package. And now my import statements have to be changed too, let&#8217;s see <code>master</code>:</p>
<p style="text-align: left;">
<pre class="python"><span style="color: #808080; font-style: italic;"># from:</span>
<span style="color: #ff7700;font-weight:bold;">import</span> mystring
<span style="color: #ff7700;font-weight:bold;">import</span> page
<span style="color: #808080; font-style: italic;"># to:</span>
<span style="color: #ff7700;font-weight:bold;">import</span> media.<span style="color: black;">mystring</span>
<span style="color: #ff7700;font-weight:bold;">import</span> media.<span style="color: black;">book</span>.<span style="color: black;">page</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_codebase_structure_master.py">python_codebase_structure_master.py</a></p>
</p>
<p style="text-align: left;">Nice one. Okay, let&#8217;s see how this works now:</p>
<p style="text-align: left;">
<pre class="bash">$ python user.py
page says hello!
sentence says hello!
frame says hello!
mystring says hello!
master says hello!</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_codebase_structure_run_user.txt">python_codebase_structure_run_user.txt</a></p>
</p>
<p style="text-align: left;"><code>user</code> imports <code>page</code> and then <code>master</code>. The first 4 lines are due to <code>page</code>, which imports three modules, and finally we see <code>master</code> arriving at the scene. All the files <em>it</em> imports have already been imported, so python doesn&#8217;t redo those. Everything is in order.</p>
<p style="text-align: left;">As you can see, imports between modules in the tree work out just fine, <code>page</code> finds both the local <code>sentence</code> and the distant <code>frame</code>.</p>
<p style="text-align: left;">But if we run <code>master</code> it&#8217;s a different story:</p>
<p style="text-align: left;">
<pre class="bash">$ python media/master.py
master says hello!
Traceback <span style="color: #66cc66;">&#40;</span>most recent call last<span style="color: #66cc66;">&#41;</span>:
  File <span style="color: #ff0000;">"media/master.py"</span>, line <span style="color: #cc66cc;">3</span>, <span style="color: #b1b100;">in</span> &lt;module&gt;
    import media.mystring
ImportError: No module named media.mystring</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_codebase_structure_run_master.txt">python_codebase_structure_run_master.txt</a></p>
</p>
<p style="text-align: left;">And it doesn&#8217;t actually matter if we run <code>master</code> from <code>media/</code> or run <code>media/master</code> from <code>.</code>, it&#8217;s the same result. And it&#8217;s the same story with <code>page</code>, which is deeper in the tree.</p>
<p style="text-align: left;">These modules, which used to be executable standalone, no longer are. <img src='http://www.matusiak.eu/numerodix/blog/wp-includes/images/smilies/frown.png' alt=':(' class='wp-smiley' /> </p>
<h3 style="text-align: left;">A hackish solution</h3>
<p style="text-align: left;">So we need something. The nature of the problem is that once we traverse into <code>media/</code>, python no longer can see that there is a package called <code>media</code>, because it&#8217;s not found anywhere on <code>sys.path</code>. What if we could tell it?</p>
<p style="text-align: left;">The problem pops up when the module is being executed directly, in fact when <code>__name__</code> == &#8216;<code>__main__</code>&#8216;. So this is the case in which we need to do something differently.</p>
<p style="text-align: left;">Here&#8217;s the idea. We put a file in the root directory of the codebase, a file we can find that marks where the root is. Then, whenever we need to find the root, we traverse up the tree until we find it. The file is called <code>.codebase_root</code>. And for our special when-executed logic, we use a file called <code>__path__</code> that we import conditionally. Here&#8217;s what it looks like:</p>
<p style="text-align: left;">
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> find_codebase<span style="color: black;">&#40;</span>mypath, codebase_rootfile<span style="color: black;">&#41;</span>:
    root, branch = mypath, <span style="color: #483d8b;">'nonempty'</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> branch:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>root, codebase_rootfile<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            codebase_root = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>root<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span> codebase_root
        root, branch = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span>root<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span>codebase_rootfile<span style="color: black;">&#41;</span>:
    thisfile = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">abspath</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">modules</span><span style="color: black;">&#91;</span>__name__<span style="color: black;">&#93;</span>.__file__<span style="color: black;">&#41;</span>
    mypath = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>thisfile<span style="color: black;">&#41;</span>
    codebase_root = find_codebase<span style="color: black;">&#40;</span>mypath, codebase_rootfile<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> codebase_root:
        <span style="color: #ff7700;font-weight:bold;">if</span> codebase_root <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>:
            <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>.<span style="color: black;">insert</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, codebase_root<span style="color: black;">&#41;</span>
&nbsp;
codebase_rootfile = <span style="color: #483d8b;">'.codebase_root'</span>
main<span style="color: black;">&#40;</span>codebase_rootfile<span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_codebase_structure_fix.py">python_codebase_structure_fix.py</a></p>
</p>
<p style="text-align: left;">So now, when we find ourselves in a module that&#8217;s somewhere inside the <code>media/</code> package, we have this bit of special handling:</p>
<p style="text-align: left;">
<pre class="python"><span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">"master says hello!"</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> __path__
<span style="color: #ff7700;font-weight:bold;">import</span> media.<span style="color: black;">mystring</span>
<span style="color: #ff7700;font-weight:bold;">import</span> media.<span style="color: black;">book</span>.<span style="color: black;">page</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_codebase_structure_master_new.py">python_codebase_structure_master_new.py</a></p>
</p>
<p style="text-align: left;">Unfortunately, importing <code>__path__</code> unconditionally breaks the case where the file is not being executed directly and I haven&#8217;t been able to figure out why, so it has to be done like this. <img src='http://www.matusiak.eu/numerodix/blog/wp-includes/images/smilies/lala.png' alt=':/' class='wp-smiley' /> </p>
<p style="text-align: left;"><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_codebase_structure_tree.png"><img class="size-full wp-image-2604 alignright" title="python_codebase_structure_tree" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_codebase_structure_tree.png" alt="python_codebase_structure_tree" width="164" height="321" /></a>You end up with a tree looking as you can see in the screenshot.</p>
<p style="text-align: left;">I&#8217;ve pushed the example to Github so by all means have a look:</p>
<ul>
<li><a href="http://github.com/numerodix/python-codebase-structure">python-codebase-structure</a></li>
</ul>
<p>We pass the test, all the modules are executable standalone again. But I can&#8217;t say that it&#8217;s awesome to have to do it like this.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2010/04/13/how-do-you-structure-your-python-codebase/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>aopy: aspect oriented python</title>
		<link>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/12/aopy-aspect-oriented-python/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/12/aopy-aspect-oriented-python/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 19:36:36 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2128</guid>
		<description><![CDATA[Aspect oriented programming is one of those old new ideas that haven&#8217;t really made a big impact (although perhaps it still will, research ideas sometimes take decades to appear in the professional world). The idea is really neat. We&#8217;ve had a few decades now to practice our modularity and the problem hasn&#8217;t really been solved [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.scientificcommons.org/42389517">Aspect oriented programming</a> is one of those old new ideas that haven&#8217;t really made a big impact (although perhaps it still will, research ideas sometimes take decades to appear in the professional world). The idea is really neat. We&#8217;ve had a few decades now to practice our modularity and the problem hasn&#8217;t really been solved fully (the number of design patterns that have been invented I think is telling). What&#8217;s different about AOP from just plain old &#8220;architecture&#8221; is the notion of &#8220;horizontal&#8221; composition. That is to say you don&#8217;t solve the problem by decomposing and choosing your parts more carefully, you inject code into critical places instead. The technique is just as general, but I would suggest differently applicable.</p>
<p>I realized I haven&#8217;t really explained anything yet, so let&#8217;s look at a suitably contrived example.</p>
<h3>A network manager</h3>
<p>Suppose you&#8217;re writing a network manager type of application (I actually tried that <a href="http://repo.or.cz/w/dumbwifi.git">once</a>). You might have a class called <code>NetworkIface</code>. And the class has an attribute <code>ip</code>. So how does <code>ip</code> get its value? Well, it can be set statically, or via dhcp. In the latter case there is a method <code>dhcp_request</code>, which requests an ip address and assigns to <code>ip</code>.</p>
<pre class="python"><span style="color: #808080; font-style: italic;"># &lt;./main.py&gt;</span>
<span style="color: #ff7700;font-weight:bold;">class</span> NetworkIface<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">ip</span> = <span style="color: #008000;">None</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> dhcp_request<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">ip</span> = <span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">131</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># XXX magic goes here</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    iface = NetworkIface<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    iface.<span style="color: black;">ip</span> = <span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    iface.<span style="color: black;">ip</span> = <span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
    iface.<span style="color: black;">dhcp_request</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/main.py">main.py</a></p>
<p>Now suppose you are in the course of writing this application, and you need to do some debugging. It would be nice to know a few things about <code>NetworkIface</code>:</p>
<ol>
<li>The dhcp server seems to be assigning ip addresses to clients in a (possibly) erroneous manner. We&#8217;d like to keep a list of all the ips we&#8217;ve been assigned.</li>
<li>Sometimes the time between making a dhcp request and getting a response seems longer than reasonable. We&#8217;d like to time the execution of the <code>dhcp_request</code> method.</li>
<li>Some users are reporting strange failures that we can&#8217;t seem to reproduce. We would like to do exhaustive logging, ie. every method entry and exit, with parameters.</li>
</ol>
<p>Now, this kind of debugging logic, however we realize it, is not really something we want in the release version of the application. It doesn&#8217;t belong. It belongs in debug builds, and we&#8217;re probably not going to need it permanently.</p>
<p>Here we will demo how to achieve the first point and omit the other two for brevity.</p>
<h3>Where AOP comes in</h3>
<p>Common to these issues is the fact that they all have to do with information gathering. But that&#8217;s not necessarily the only thing we might want to do. We might want to tweak the behavior of <code>dhcp_request</code> for the purpose of debugging. For instance, if it took too long to get an ip, we could set one statically after some seconds. Again, that would be a temporary piece of logic not meant to be in the release version.</p>
<p>Now, AOP says &#8220;don&#8217;t change your code, you&#8217;ll only make a mess of it&#8221;. Instead you can write that piece of code you need to write, but quite separately from your codebase. This you call an <em>aspect</em>, with the intention that it captures some aspect of behavior you want to inject into your code. And then, during compilation from source code to bytecode (or object code) you inject the aspect code where you want it to go. Compiler? Yes, AOP comes with a special compiler, which makes injection very toggable. Want vanilla code? Use the regular compiler. Want aspected code? Use the AOP compiler.</p>
<p>How does the compiler know where to inject the aspect code? AOP defines strategic injection points called <em>join points</em>. Exactly what these are depends on the programming language, but typically there is a join point preceding a method body, a join point preceding a method call, a method return and so on. (As we shall see, in aopy we are being more Pythonic.) Join points are defined by the AOP framework. But how do you tell it to inject there? With <em>point cuts</em>. A point cut is a matching string (ie. regular expression) which is matched against every join point and determines if injection happens there.</p>
<h3>Back to you, John</h3>
<p>Enough chatter, the code is getting cold! As it happens, Python has first rate facilities for writing AOP-ish code. We already have language features that can modify or add behavior to existing code:</p>
<ul>
<li>Properties let us micromanage assignment to/reading from instance variables.</li>
<li>Decorators let us wrap function execution with additional logic, or even replace the original function with another.</li>
<li>Metaclasses can do just about anything to a class by rebinding the class namespace arbitrarily.</li>
</ul>
<p>We will use these language constructs as units of code injection, called <em>advice</em> in AOP. This way we can reuse all the decorators and metaclasses we already have and we can do AOP much the way we write code already. Let&#8217;s see the aspects then.</p>
<h3>A caching aspect</h3>
<p>The first thing we wanted was to cache the values of <code>ip</code>. For this we have a pair of functions which will become methods in <code>NetworkIface</code> and make <code>ip</code> a property.</p>
<pre class="python"><span style="color: #808080; font-style: italic;"># &lt;aspects/cache.py&gt;</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Cache<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">values</span> = <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">value</span> = <span style="color: #008000;">None</span>
cache = Cache<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> cache.<span style="color: black;">value</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, value<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> value:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">"c New value: %s"</span> % <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>value<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> any<span style="color: black;">&#40;</span>cache.<span style="color: black;">values</span><span style="color: black;">&#41;</span>:
        prev = <span style="color: #483d8b;">", "</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>val<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> val <span style="color: #ff7700;font-weight:bold;">in</span> cache.<span style="color: black;">values</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">"c  Previous values: %s"</span> % prev
    <span style="color: #ff7700;font-weight:bold;">if</span> value:
        cache.<span style="color: black;">values</span> = cache.<span style="color: black;">values</span>.<span style="color: black;">union</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>value<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    cache.<span style="color: black;">value</span> = value</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/cache.py">cache.py</a></p>
<p><code>Cache</code> is the helper class that will store all the values.</p>
<h3>A spec</h3>
<p>Aspects are defined in specification files which provide the actual link between the codebase and the aspect code.</p>
<pre class="python"><span style="color: #808080; font-style: italic;"># &lt;./spec.py&gt;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> aopy
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> aspects.<span style="color: black;">cache</span>
&nbsp;
caching_aspect = aopy.<span style="color: black;">Aspect</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
caching_aspect.<span style="color: black;">add_property</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'main:NetworkIface/ip'</span>,
    fget=aspects.<span style="color: black;">cache</span>.<span style="color: black;">get</span>, fset=aspects.<span style="color: black;">cache</span>.<span style="color: #008000;">set</span><span style="color: black;">&#41;</span>
&nbsp;
__all__ = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'caching_aspect'</span><span style="color: black;">&#93;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/spec.py">spec.py</a></p>
<p>We start by importing the aopy library and the aspect code we&#8217;ve written. Then we create an <code>Aspect</code> instance and call <code>add_property</code> to add a property advice to this aspect. The first argument is the point cut, ie. the matching string which defines what this property is to be applied to. Here we say &#8220;in a module called <code>main</code>, in a class called <code>NetworkIface</code>, find a member called <code>ip</code>&#8220;. The other two arguments provide the two functions we wish to use in this property.</p>
<h3>Compiling</h3>
<p>To compile the aspect into the codebase we run the compiler, giving the spec file. And we give it a module (or a path) that indicates the codebase.</p>
<pre class="bash">$ aopyc -t spec.py main.py
Transforming module /home/alex/uu/colloq/aopy/code/main.py
Pattern matched: main:NetworkIface/ip on main:NetworkIface/ip</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/main.compile">main.compile</a></p>
<p>The compiler will examine all the modules in the codebase (in this case only <code>main.py</code>) and attempt code injection in each one. Whenever a point cut matches, injection happens. The transformed module is then compiled to bytecode and written to disk (as <code>main.pyc</code>).</p>
<p><code>main.pyc</code> now looks like this:</p>
<pre class="python"><span style="color: #808080; font-style: italic;"># &lt;./main.py&gt; transformed</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span> <span style="color: #808080; font-style: italic;">### &lt;-- injected</span>
<span style="color: #ff7700;font-weight:bold;">for</span> path <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'.'</span><span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;">### &lt;-- injected</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> path <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>: <span style="color: #808080; font-style: italic;">### &lt;-- injected</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;">### &lt;-- injected</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> aspects.<span style="color: black;">cache</span> as cache <span style="color: #808080; font-style: italic;">### &lt;-- injected</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> NetworkIface<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">ip</span> = <span style="color: #008000;">None</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> dhcp_request<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">ip</span> = <span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">131</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># XXX magic goes here</span>

    ip = <span style="color: #008000;">property</span><span style="color: black;">&#40;</span>fget=cache.<span style="color: black;">get</span>, fset=cache.<span style="color: #008000;">set</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;">### &lt;-- injected</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    iface = NetworkIface<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    iface.<span style="color: black;">ip</span> = <span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    iface.<span style="color: black;">ip</span> = <span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
    iface.<span style="color: black;">dhcp_request</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/main_t.py">main_t.py</a></p>
<p>Injected lines are marked. First we find some import statements that are meant to ensure that the codebase can find the aspect code on disk. Then we import the actual aspect module that holds our advice. And finally we can ascertain that <code>NetworkIface</code> has gained a property, with get and set methods pulled in from our aspect code.</p>
<h3>Running aspected</h3>
<p>When we now run <code>main.pyc</code> we get a message every time <code>ip</code> gets a new value. We also get a printout of all the previous values.</p>
<pre class="bash">c New value: <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
c New value: <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>
c  Previous values: <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
c New value: <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">131</span><span style="color: #66cc66;">&#41;</span>
c  Previous values: <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/main.output">main.output</a></p>
<p>And the yet the codebase has not been touched, if we execute <code>main.py</code> instead we find the original code.</p>
<h3>Here the show endeth</h3>
<p>And that wraps up a hasty introduction to AOP with aopy. There is a lot more to be said, both about AOP in Python and aopy in particular. Interested parties are kindly directed to these two papers:</p>
<ol>
<li><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/aop_strategies.pdf">Strategies for aspect oriented programming in Python</a></li>
<li><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/aopy.pdf">aopy: A program transformation-based aspect oriented framework for Python</a></li>
</ol>
<p>If you prefer reading code rather than English (variable names are still in English though, sorry about that), here is the repo for your pleasure:</p>
<ul>
<li><a href="http://github.com/numerodix/aopy">aopy repo</a></li>
</ul>
<p>And if you still have no idea what AOP is and think the whole thing is bogus then you can watch this <a href="http://video.google.com/videoplay?docid=8566923311315412414">google talk</a> (and who doesn&#8217;t love a google talk!) by mr. AOP himself.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/12/aopy-aspect-oriented-python/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>python patterns for graph traversal</title>
		<link>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/08/python-patterns-for-graph-traversal/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/08/python-patterns-for-graph-traversal/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 15:24:07 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2501</guid>
		<description><![CDATA[Graphs, they are fun. You can use them for all sorts of things, like drawing a picture of the internet (or your favorite regular expression!)
For example, look at that handsome guy there on the right. Is that a gorgeous graph, or what? (Incidentally, if you aren&#8217;t yet a fan of graphviz, it&#8217;s time to become [...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-2500 alignright" title="python_graphtraversal_pic" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_pic.png" alt="python_graphtraversal_pic" width="196" height="251" />Graphs, they are fun. You can use them for all sorts of things, like drawing a picture of the internet (or your favorite regular expression!)</p>
<p>For example, look at that handsome guy there on the right. Is that a gorgeous graph, or what? (Incidentally, if you aren&#8217;t yet a fan of <a href="http://www.graphviz.org/">graphviz</a>, it&#8217;s time to become one, it&#8217;s superb!)</p>
<p>Now take a gander at the code snippet below, that&#8217;s the python representation of it.</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">class</span> Node<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">name</span> = name
&nbsp;
a, b, c, d = Node<span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>, Node<span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: black;">&#41;</span>, Node<span style="color: black;">&#40;</span><span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span>, Node<span style="color: black;">&#40;</span><span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span>
a.<span style="color: black;">refs</span> = <span style="color: black;">&#91;</span>b, d<span style="color: black;">&#93;</span>
b.<span style="color: black;">refs</span> = <span style="color: black;">&#91;</span>c<span style="color: black;">&#93;</span>
c.<span style="color: black;">refs</span> = <span style="color: black;">&#91;</span>a<span style="color: black;">&#93;</span>
d.<span style="color: black;">refs</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_model.py">python_graphtraversal_model.py</a></p>
<p>But it&#8217;s not there just to be stared at, so let&#8217;s do something with it! One thing we could do is go over the graph and print out the nodes. But let&#8217;s do one better, let&#8217;s also show how deep into the graph we are by indenting the output! What we want is this:</p>
<pre class="python">a
__b
____c
__d</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_spec.py">python_graphtraversal_spec.py</a></p>
<p>We don&#8217;t have the nice arrows here, but you can still make out the shape of the graph.</p>
<h3>First iteration</h3>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">def</span> traverse_naive<span style="color: black;">&#40;</span>node, depth<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__'</span>*depth + node.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> ref <span style="color: #ff7700;font-weight:bold;">in</span> node.<span style="color: black;">refs</span>:
        traverse_naive<span style="color: black;">&#40;</span>ref, depth<span style="color: #ff4500;">+1</span><span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_naive.py">python_graphtraversal_naive.py</a></p>
<p>Very simple. Print the name of the node at the current level of depth, and then recurse down the outgoing edges. But when we run this something bad happens:</p>
<pre class="python">&gt;&gt;&gt; traverse_naive<span style="color: black;">&#40;</span>a, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
a
__b
____c
______a
________b
..
<span style="color: #008000;">RuntimeError</span>: maximum recursion depth exceeded</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_naive_output.py">python_graphtraversal_naive_output.py</a></p>
<p>There&#8217;s no sign of d, instead we keep going round and round along the path a-b-c-a. Woops.</p>
<h3>Preempting cycles</h3>
<p>Traditionally, graph traversal algorithms have set properties on nodes in the graph to indicate to themselves that a particular node had been seen before. For example, we could set <code>node.been_here_before = True</code> every time we enter a node, and then we could check for this property to make sure we don&#8217;t re-enter the node later.</p>
<p>But this is not awesome, because we then have to change the graph as we traverse it. What if we want to traverse it again later, do we then need another traversal algorithm to remove all the markers or what?</p>
<p>There is another way to do this, however. We can use a data structure completely outside the graph in which we keep track of what we&#8217;ve seen so far (imagine a guy walking around a warehouse with a clipboard, he then doesn&#8217;t have to mark any of the merchandise!).</p>
<p>So instead of checking the value of <code>node.been_here_before</code>, we&#8217;re going to check the value of <code>cache[node]</code>.</p>
<p>Now, there are two main strategies for where to do this check. We can do it right before the recursive call, or right after.</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">def</span> traverse_check_before<span style="color: black;">&#40;</span>node, depth, cache<span style="color: black;">&#41;</span>:
    cache<span style="color: black;">&#91;</span>node<span style="color: black;">&#93;</span> = <span style="color: #008000;">None</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__'</span>*depth + node.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> ref <span style="color: #ff7700;font-weight:bold;">in</span> node.<span style="color: black;">refs</span>:
        <span style="color: #808080; font-style: italic;"># we are about to recurse, first check if the node we want</span>
        <span style="color: #808080; font-style: italic;"># to recurse on is in the cache</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> ref <span style="color: #ff7700;font-weight:bold;">in</span> cache:
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Already in cache: %s'</span> % ref.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">continue</span>
        <span style="color: #808080; font-style: italic;"># recurse if we reach this point</span>
        traverse_cached<span style="color: black;">&#40;</span>ref, depth<span style="color: #ff4500;">+1</span>, cache<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> traverse_check_after<span style="color: black;">&#40;</span>node, depth, cache<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># we have just recursed, return if this node is already in</span>
    <span style="color: #808080; font-style: italic;"># the cache</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> node <span style="color: #ff7700;font-weight:bold;">in</span> cache:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Already in cache: %s'</span> % node.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span>
    cache<span style="color: black;">&#91;</span>node<span style="color: black;">&#93;</span> = <span style="color: #008000;">None</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__'</span>*depth + node.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> ref <span style="color: #ff7700;font-weight:bold;">in</span> node.<span style="color: black;">refs</span>:
        <span style="color: #808080; font-style: italic;"># recurse without exception</span>
        traverse_cached<span style="color: black;">&#40;</span>ref, depth<span style="color: #ff4500;">+1</span>, cache<span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_two.py">python_graphtraversal_two.py</a></p>
<p>Here it doesn&#8217;t matter which one we use, so we&#8217;re just going to use the second option.</p>
<h3>Second iteration</h3>
<p>At this point you might be thinking that everything is going swimmingly, but in fact a small problem has crept up. It cannot have escaped your attention that we&#8217;ve snuck another parameter into that function definition. This means that we have to call the function like this:</p>
<pre class="python">&gt;&gt;&gt; traverse_check_after<span style="color: black;">&#40;</span>a, <span style="color: #ff4500;">0</span>, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
a
__b
____c
Already <span style="color: #ff7700;font-weight:bold;">in</span> cache: a
__d</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_param.py">python_graphtraversal_param.py</a></p>
<p>The function works, but we really, really don&#8217;t want to have to do it like this. There is no reason the caller has to know about the cache, let alone that it is a dictionary. And if we ever decide to change the cache mechanism, we have to update all the client code.</p>
<p>So what can we do? We can&#8217;t set up the cache in the function body, because the function is recursive!</p>
<p>This is where you might get that look in your eye that you get when you&#8217;re being clever. Hah, but what about this:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">def</span> traverse_cached<span style="color: black;">&#40;</span>node, depth, cache=<span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> node <span style="color: #ff7700;font-weight:bold;">in</span> cache:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Already in cache: %s'</span> % node.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span>
    cache<span style="color: black;">&#91;</span>node<span style="color: black;">&#93;</span> = <span style="color: #008000;">None</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__'</span>*depth + node.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> ref <span style="color: #ff7700;font-weight:bold;">in</span> node.<span style="color: black;">refs</span>:
        traverse_cached<span style="color: black;">&#40;</span>ref, depth<span style="color: #ff4500;">+1</span>, cache=cache<span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_cached.py">python_graphtraversal_cached.py</a></p>
<p>Brilliant! We don&#8217;t have to set up the cache <em>neither</em> inside the function body <em>nor</em> at the call site. This cache has to be initialized somewhere between the call and the function being executed, but somehow we&#8217;ve found a magical in-between, haven&#8217;t we!</p>
<p>Keyword parameters really are a tremendous boon, but unfortunately they will not save our skin this time. Do you know what happens if we do this?</p>
<pre class="python">&gt;&gt;&gt; traverse_cached<span style="color: black;">&#40;</span>a, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&gt;&gt;&gt; traverse_cached<span style="color: black;">&#40;</span>a, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_cached_call.py">python_graphtraversal_cached_call.py</a></p>
<p>Read and weep:</p>
<pre class="python">&gt;&gt;&gt; traverse_cached<span style="color: black;">&#40;</span>a, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
a
__b
____c
Already <span style="color: #ff7700;font-weight:bold;">in</span> cache: a
__d
&gt;&gt;&gt; traverse_cached<span style="color: black;">&#40;</span>a, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
Already <span style="color: #ff7700;font-weight:bold;">in</span> cache: a</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_cached_output.py">python_graphtraversal_cached_output.py</a></p>
<h3>Keyword parameters</h3>
<p>Keyword parameters don&#8217;t do what you thought they did. You thought <code>traverse_cached</code> would get a new dictionary every time it was called without a cache argument. But that&#8217;s not what happens. (But isn&#8217;t python magical???)</p>
<p>In fact, it works like this. The cache keyword parameter gets initialized once and for all when the function is compiled. Since the value it is set to is an empty dictionary, the dict object is initially empty. But every time you call the function, it&#8217;s the <strong>same</strong> dictionary that gets passed in! <img src='http://www.matusiak.eu/numerodix/blog/wp-includes/images/smilies/eek.png' alt=':eek:' class='wp-smiley' /> </p>
<h3>Third iteration</h3>
<p>It&#8217;s come to this, I&#8217;m afraid. The problem is unsurmountable. We can&#8217;t <em>not</em> pass the cache parameter. But we definitely don&#8217;t want to do it at the call site. Which leaves no other option than&#8230;</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">def</span> traverse_cached_fixed<span style="color: black;">&#40;</span>node, depth<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> rec<span style="color: black;">&#40;</span>node, depth, cache<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> node <span style="color: #ff7700;font-weight:bold;">in</span> cache:
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Already in cache: %s'</span> % node.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span>
        cache<span style="color: black;">&#91;</span>node<span style="color: black;">&#93;</span> = <span style="color: #008000;">None</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__'</span>*depth + node.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> ref <span style="color: #ff7700;font-weight:bold;">in</span> node.<span style="color: black;">refs</span>:
            rec<span style="color: black;">&#40;</span>ref, depth<span style="color: #ff4500;">+1</span>, cache<span style="color: black;">&#41;</span>
    rec<span style="color: black;">&#40;</span>node, depth, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_fixed.py">python_graphtraversal_fixed.py</a></p>
<p>I really hate using an inner function just for this. It makes it messier, you have to route the arguments through an extra function call. But that&#8217;s the price you pay, I&#8217;m afraid.</p>
<h3>Postscript</h3>
<p>By now you must be fuming at the fact that I&#8217;ve come all this way while pretending that the function call didn&#8217;t have another parameter that was completely pointless and indeed deserving of the very same criticism.</p>
<p>Well, the difference is that you can set <code>depth=0</code> as a keyword parameter in the function definition, so that you don&#8217;t have to pass it. And this doesn&#8217;t break anything. But why??</p>
<p>The answer is found when poking around python. <span style="text-decoration: line-through;">A function is in fact a mutable object.</span> Have a look:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">def</span> f<span style="color: black;">&#40;</span>a=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>:
    a = <span style="color: #ff4500;">1</span>
&nbsp;
&gt;&gt;&gt; <span style="color: #ff7700;font-weight:bold;">print</span> f.<span style="color: black;">func_defaults</span>
<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_keywords1.py">python_graphtraversal_keywords1.py</a></p>
<p><code>func_defaults</code> is the tuple that stores the values of the keyword parameters which have a default value. The value we see here is the integer 0, and it will not change no matter how many times we execute the function.</p>
<p>But collection types (and your own types too) are different:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">def</span> g<span style="color: black;">&#40;</span>a=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
    a.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> a
&nbsp;
&gt;&gt;&gt; <span style="color: #ff7700;font-weight:bold;">print</span> g.<span style="color: black;">func_defaults</span>
<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>,<span style="color: black;">&#41;</span>
&gt;&gt;&gt; g<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
&gt;&gt;&gt; <span style="color: #ff7700;font-weight:bold;">print</span> g.<span style="color: black;">func_defaults</span>
<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>,<span style="color: black;">&#41;</span>
&gt;&gt;&gt; g<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_keywords2.py">python_graphtraversal_keywords2.py</a></p>
<p>Despite different, it actually works the same way (sorta). <strong>The binding of the keyword default is constant.</strong> But with an integer, the parameter is bound to the constant 0, whereas with &#8220;heavier&#8221; objects, it is bound to the object, but the object&#8217;s inner properties can very well mutate!!!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/08/python-patterns-for-graph-traversal/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>detecting the os and distro on the system</title>
		<link>http://www.matusiak.eu/numerodix/blog/index.php/2010/01/06/detecting-the-os-and-distro-on-the-system/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2010/01/06/detecting-the-os-and-distro-on-the-system/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 00:25:14 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2478</guid>
		<description><![CDATA[Linux, in all its diversity, sometimes lacks very basic mechanisms that you would be prepared to take for granted. For instance, picture this scenario.. you are on some system you don&#8217;t know well. Maybe it&#8217;s your friend who called you over to his house for help with something. Maybe it&#8217;s the computer lab where you [...]]]></description>
			<content:encoded><![CDATA[<p>Linux, in all its diversity, sometimes lacks very basic mechanisms that you would be prepared to take for granted. For instance, picture this scenario.. you are on some system you don&#8217;t know well. Maybe it&#8217;s your friend who called you over to his house for help with something. Maybe it&#8217;s the computer lab where you don&#8217;t know the setup. Maybe it&#8217;s a remote session to a box you&#8217;ve never seen. Quick question: what&#8217;s it running?</p>
<p>Well, <code>bash --version</code> tells you about bash, <code>ls --version</code> tells you about coreutils and so on, you can keep going with that. <code>uname</code> will tell you about the platform and the kernel, useful stuff. What about the distro? Distros are diverse, sometimes it helps a lot to know what kind of environment you&#8217;re in. Well, strangely enough, there&#8217;s no standard answer to that.</p>
<p>They all do their own thing, if they do at all. Some distros use <code>lsb_release</code> to dispense this information. Others have files in <code>/etc</code> that you can check for, if you know what they are supposed to be called. So I decided to try and detect this. I&#8217;ve checked a bunch of livecds and it works on those distros that identify themselves somehow.</p>
<p><img class="alignnone size-full wp-image-2481" title="osdetect" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/osdetect.png" alt="osdetect" width="424" height="39" /></p>
<pre class="bash"><span style="color: #808080; font-style: italic;"># Author: Martin Matusiak &lt;numerodix@gmail.com&gt;</span>
<span style="color: #808080; font-style: italic;"># Licensed under the GNU Public License, version 3</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># &lt;desc&gt; Detect OS (platform and version) of local machine &lt;/desc&gt;</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># &lt;usage&gt;</span>
<span style="color: #808080; font-style: italic;"># source this file in bash, then run `osdetect`</span>
<span style="color: #808080; font-style: italic;"># &lt;/usage&gt;</span>
&nbsp;
&nbsp;
_concat<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000066;">local</span> <span style="color: #0000ff;">s=</span><span style="color: #ff0000;">"$1"</span>;shift;
	<span style="color: #b1b100;">while</span> <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">"$1"</span> <span style="color: #66cc66;">&#93;</span>; <span style="color: #b1b100;">do</span>
		<span style="color: #0000ff;">s=</span><span style="color: #ff0000;">"$s $1"</span>; <span style="color: #000066;">shift</span>
	<span style="color: #b1b100;">done</span>
	<span style="color: #000066;">echo</span> <span style="color: #ff0000;">"$s"</span> | sed <span style="color: #ff0000;">"s|^[ <span style="color: #000099; font-weight: bold;">\\t</span>]*||g"</span> | sed <span style="color: #ff0000;">"s|[ <span style="color: #000099; font-weight: bold;">\\t</span>]*$||g"</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
_glob<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
	<span style="color: #000066;">local</span> <span style="color: #0000ff;">file=</span>
	<span style="color: #000066;">local</span> <span style="color: #0000ff;">glob=</span>
	<span style="color: #000066;">local</span> <span style="color: #0000ff;">lst=</span>
	<span style="color: #b1b100;">while</span> <span style="color: #66cc66;">&#91;</span> -z <span style="color: #ff0000;">"$file"</span> <span style="color: #66cc66;">&#93;</span> &amp;&amp; <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">"$1"</span> <span style="color: #66cc66;">&#93;</span>; <span style="color: #b1b100;">do</span>
		<span style="color: #0000ff;">glob=</span><span style="color: #ff0000;">"$1"</span>;shift;
		<span style="color: #0000ff;">lst=</span>$<span style="color: #66cc66;">&#40;</span>ls <span style="color: #0000ff;">$glob</span> <span style="color: #cc66cc;">2</span>&gt;/dev/null | grep -v /etc/lsb-release<span style="color: #66cc66;">&#41;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">"$lst"</span> <span style="color: #66cc66;">&#93;</span>; <span style="color: #b1b100;">then</span>
			<span style="color: #0000ff;">file=</span>$<span style="color: #66cc66;">&#40;</span><span style="color: #000066;">echo</span> <span style="color: #ff0000;">"$lst"</span> | head -n1<span style="color: #66cc66;">&#41;</span>
		<span style="color: #b1b100;">fi</span>
	<span style="color: #b1b100;">done</span>
	<span style="color: #000066;">echo</span> <span style="color: #ff0000;">"$file"</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
osdetect<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
	<span style="color: #808080; font-style: italic;"># ref: http://linuxmafia.com/faq/Admin/release-files.html</span>
&nbsp;
	<span style="color: #000066;">local</span> <span style="color: #0000ff;">os=</span>
	<span style="color: #000066;">local</span> <span style="color: #0000ff;">release=</span>
	<span style="color: #000066;">local</span> <span style="color: #0000ff;">machine=</span>
	<span style="color: #b1b100;">if</span> ! which uname &amp;&gt;/dev/null; <span style="color: #b1b100;">then</span>
		<span style="color: #000066;">echo</span> -e <span style="color: #ff0000;">"${cred}No uname on system${creset}"</span> &gt;&amp;<span style="color: #cc66cc;">2</span>
		<span style="color: #0000ff;">os=</span><span style="color: #ff0000;">"N/A"</span>
	<span style="color: #b1b100;">else</span>
		<span style="color: #0000ff;">os=</span>$<span style="color: #66cc66;">&#40;</span>uname -s<span style="color: #66cc66;">&#41;</span>
		<span style="color: #0000ff;">release=</span>$<span style="color: #66cc66;">&#40;</span>uname -r<span style="color: #66cc66;">&#41;</span>
		<span style="color: #0000ff;">machine=</span>$<span style="color: #66cc66;">&#40;</span>uname -m<span style="color: #66cc66;">&#41;</span>
	<span style="color: #b1b100;">fi</span>
	<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">"$os"</span> = <span style="color: #ff0000;">"SunOS"</span> <span style="color: #66cc66;">&#93;</span>; <span style="color: #b1b100;">then</span>
		<span style="color: #0000ff;">os=</span><span style="color: #ff0000;">"Solaris"</span>
		<span style="color: #0000ff;">machine=</span>$<span style="color: #66cc66;">&#40;</span>uname -p<span style="color: #66cc66;">&#41;</span>
	<span style="color: #b1b100;">fi</span>
	<span style="color: #000066;">local</span> <span style="color: #0000ff;">platform=</span><span style="color: #ff0000;">"$(_concat "</span><span style="color: #0000ff;">$os</span><span style="color: #ff0000;">" "</span><span style="color: #0000ff;">$release</span><span style="color: #ff0000;">" "</span><span style="color: #0000ff;">$machine</span><span style="color: #ff0000;">")"</span>
&nbsp;
	<span style="color: #808080; font-style: italic;"># prefer lsb_release</span>
	<span style="color: #b1b100;">if</span> which lsb_release &amp;&gt;/dev/null; <span style="color: #b1b100;">then</span>
		<span style="color: #000066;">local</span> <span style="color: #0000ff;">id=</span><span style="color: #ff0000;">"$(_concat "</span>$<span style="color: #66cc66;">&#40;</span>lsb_release -i | sed <span style="color: #ff0000;">"s|.*:||g"</span><span style="color: #66cc66;">&#41;</span><span style="color: #ff0000;">")"</span>
		<span style="color: #000066;">local</span> <span style="color: #0000ff;">rel=</span><span style="color: #ff0000;">"$(_concat "</span>$<span style="color: #66cc66;">&#40;</span>lsb_release -r | sed <span style="color: #ff0000;">"s|.*:||g"</span><span style="color: #66cc66;">&#41;</span><span style="color: #ff0000;">")"</span>
		<span style="color: #000066;">local</span> <span style="color: #0000ff;">code=</span><span style="color: #ff0000;">"$(_concat "</span>$<span style="color: #66cc66;">&#40;</span>lsb_release -c | sed <span style="color: #ff0000;">"s|.*:||g"</span><span style="color: #66cc66;">&#41;</span><span style="color: #ff0000;">")"</span>
	<span style="color: #b1b100;">elif</span> <span style="color: #66cc66;">&#91;</span> -f /etc/lsb-release <span style="color: #66cc66;">&#93;</span>; <span style="color: #b1b100;">then</span>
		<span style="color: #000066;">local</span> <span style="color: #0000ff;">id=</span><span style="color: #ff0000;">"$(_concat "</span>$<span style="color: #66cc66;">&#40;</span>grep DISTRIB_ID /etc/lsb-release | sed <span style="color: #ff0000;">"s|.*=||g"</span><span style="color: #66cc66;">&#41;</span><span style="color: #ff0000;">")"</span>
		<span style="color: #000066;">local</span> <span style="color: #0000ff;">rel=</span><span style="color: #ff0000;">"$(_concat "</span>$<span style="color: #66cc66;">&#40;</span>grep DISTRIB_RELEASE /etc/lsb-release | sed <span style="color: #ff0000;">"s|.*=||g"</span><span style="color: #66cc66;">&#41;</span><span style="color: #ff0000;">")"</span>
		<span style="color: #000066;">local</span> <span style="color: #0000ff;">code=</span><span style="color: #ff0000;">"$(_concat "</span>$<span style="color: #66cc66;">&#40;</span>grep DISTRIB_CODENAME /etc/lsb-release | sed <span style="color: #ff0000;">"s|.*=||g"</span><span style="color: #66cc66;">&#41;</span><span style="color: #ff0000;">")"</span>
&nbsp;
	<span style="color: #808080; font-style: italic;"># find a file or another</span>
	<span style="color: #b1b100;">else</span>
		<span style="color: #000066;">local</span> <span style="color: #0000ff;">vfile=</span>$<span style="color: #66cc66;">&#40;</span>_glob <span style="color: #ff0000;">"/etc/*-rel*"</span> <span style="color: #ff0000;">"/etc/*_ver*"</span> <span style="color: #ff0000;">"/etc/*-version"</span><span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">"$vfile"</span> <span style="color: #66cc66;">&#93;</span> &amp;&amp; <span style="color: #000066;">local</span> <span style="color: #0000ff;">id=</span>$<span style="color: #66cc66;">&#40;</span>cat <span style="color: #ff0000;">"$vfile"</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
		<span style="color: #808080; font-style: italic;"># distro specific</span>
		<span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">"$vfile"</span> = /etc/debian_version <span style="color: #66cc66;">&#93;</span> &amp;&amp; <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">"$id"</span> <span style="color: #66cc66;">&#93;</span> &amp;&amp; <span style="color: #0000ff;">id=</span><span style="color: #ff0000;">"Debian $id"</span>
	<span style="color: #b1b100;">fi</span>
&nbsp;
	<span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">"$id"</span> = <span style="color: #ff0000;">"n/a"</span> <span style="color: #66cc66;">&#93;</span> &amp;&amp; <span style="color: #0000ff;">id=</span>
	<span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">"$rel"</span> = <span style="color: #ff0000;">"n/a"</span> <span style="color: #66cc66;">&#93;</span> &amp;&amp; <span style="color: #0000ff;">rel=</span>
	<span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">"$code"</span> = <span style="color: #ff0000;">"n/a"</span> <span style="color: #66cc66;">&#93;</span> &amp;&amp; <span style="color: #0000ff;">code=</span>
&nbsp;
	<span style="color: #000066;">local</span> <span style="color: #0000ff;">version=</span><span style="color: #ff0000;">"$(_concat "</span><span style="color: #0000ff;">$id</span><span style="color: #ff0000;">" "</span><span style="color: #0000ff;">$rel</span><span style="color: #ff0000;">" "</span><span style="color: #0000ff;">$code</span><span style="color: #ff0000;">")"</span>
	<span style="color: #66cc66;">&#91;</span> ! -z <span style="color: #ff0000;">"$version"</span> <span style="color: #66cc66;">&#93;</span> &amp;&amp; <span style="color: #0000ff;">version=</span><span style="color: #ff0000;">" ~ ${cyellow}$version${creset}"</span>
&nbsp;
	<span style="color: #000066;">echo</span> -e <span style="color: #ff0000;">"Platform: ${ccyan}${platform}${creset}${version}"</span>
<span style="color: #66cc66;">&#125;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/osdetect.sh">osdetect.sh</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2010/01/06/detecting-the-os-and-distro-on-the-system/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>lazy function loading</title>
		<link>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/08/lazy-function-loading/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/08/lazy-function-loading/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 12:20:31 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2461</guid>
		<description><![CDATA[Even though bash is not my favorite programming language, I end up writing a bit of code in it. It&#8217;s just super practical to have something in bash if you can. I mentioned in the past how it&#8217;s a good idea to avoid unnecessary cpu/io while initializing the shell by doing deferred aliasing. That solves [...]]]></description>
			<content:encoded><![CDATA[<p>Even though bash is not my favorite programming language, I end up writing a bit of code in it. It&#8217;s just super practical to have something in bash if you can. I mentioned in the past how it&#8217;s a good idea to avoid unnecessary cpu/io while initializing the shell by doing <a href="http://www.matusiak.eu/numerodix/blog/index.php/2008/11/27/deferred-aliasing/">deferred aliasing</a>. That solves the alias problem, but I also have a bunch of bash code in terms of functions. So I was thinking the same principle could be applied again.</p>
<p>Let&#8217;s use <a href="http://www.matusiak.eu/numerodix/blog/index.php/2009/10/14/findpkgs-find-packages-for-application/">findpkgs</a> as an example here. The function is defined in a separate file and the file is source&#8217;d. But this means that every time I start a new shell session the whole function has to be read and loaded into memory. That might not be convenient if there are a number of those. <a href="http://www.matusiak.eu/numerodix/blog/index.php/2009/06/14/networktest-improved-network-detection/">networktest</a>, for instance, defines four function and is considerably longer.</p>
<p>So let&#8217;s &#8220;compile to bytecode&#8221; again:</p>
<pre class="bash">findpkgs <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #66cc66;">&#91;</span> -f ~/.myshell/findpkgs.sh <span style="color: #66cc66;">&#93;</span> &amp;&amp; . ~/.myshell/findpkgs.sh;
    findpkgs $@
<span style="color: #66cc66;">&#125;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/lazyfuncionload_loadfunc">lazyfuncionload_loadfunc</a></p>
<p>When the function is defined this way, the script actually hasn&#8217;t been sourced yet (and that&#8217;s precisely the idea), but it will be the minute we call the function. This, naturally, will rebind the name <code>findpkgs</code>, and then we call the function again, with the given arguments, but this time giving them to the actual function.</p>
<p>Okay, so that was easy. But what if you have a bunch of functions loaded like that? It&#8217;s gonna be kinda messy copy-pasting that boilerplate code over and over. So let&#8217;s not write that code, let&#8217;s generate it:</p>
<pre class="bash">lazyimport<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
<span style="color: #808080; font-style: italic;"># generate code for lazy import of function</span>
	<span style="color: #0000ff;">function=</span><span style="color: #ff0000;">"$1"</span>;shift;
	<span style="color: #0000ff;">script=</span><span style="color: #ff0000;">"$1"</span>;shift;
&nbsp;
	<span style="color: #0000ff;">dec=</span><span style="color: #ff0000;">"$function() {
		[ -f ~/.myshell/$script.sh ] &amp;&amp; . ~/.myshell/$script.sh
		$function <span style="color: #000099; font-weight: bold;">\\$</span>@
	}"</span>
	<span style="color: #000066;">eval</span> <span style="color: #ff0000;">"$dec"</span>
<span style="color: #66cc66;">&#125;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/lazyfuncionload_lazyimport">lazyfuncionload_lazyimport</a></p>
<p>Don&#8217;t worry, it&#8217;s the same thing as before, just wrapped in quotes. And now we may import all the functions we want in the namespace by calling this import function with the name of the function we want to &#8220;byte compile&#8221; and the script where it is found:</p>
<pre class="bash"><span style="color: #808080; font-style: italic;">## findpkgs.sh</span>
&nbsp;
lazyimport findpkgs findpkgs
&nbsp;
<span style="color: #808080; font-style: italic;">## networktest.sh</span>
&nbsp;
lazyimport havenet networktest
lazyimport haveinet networktest
lazyimport wifi networktest
lazyimport wifiscan networktest
&nbsp;
<span style="color: #808080; font-style: italic;">## servalive.sh</span>
&nbsp;
lazyimport servalive servalive</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/lazyfuncionload_functions">lazyfuncionload_functions</a></p>
<p>So let&#8217;s imagine a hypothetical execution. It goes like this:</p>
<ol>
<li>Start a new bash shell.</li>
<li>Source <code>import.sh</code> where all this code is.</li>
<li>On each call to <code>lazyimport</code> a function declaration is generated, and eval&#8217;d. The function we want is now bound to its name in the shell.</li>
<li>On the first call to the function, the generated code for the function is executed, which actually sources the script, which <em>rebinds</em> the name of the function to the actual code that belongs to it.</li>
<li>The function is executed with arguments.</li>
<li>On subsequent executions the function is already &#8220;compiled&#8221;, ie. bound to its proper code.</li>
</ol>
<p>So what happens, you may wonder, in cases like the above with <code>networktest</code>, where several mock functions are generated, all of which will source the same script? Well nothing, whichever of them is called first will source the script and overwrite all the bindings, remember? It only takes one call to whichever function and all of them become rebound to the real thing. So all is well. <img src='http://www.matusiak.eu/numerodix/blog/wp-includes/images/smilies/smile.png' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/08/lazy-function-loading/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>peek: monitor files for changes</title>
		<link>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/01/peek-monitor-files-for-changes/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/01/peek-monitor-files-for-changes/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 15:16:15 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2446</guid>
		<description><![CDATA[It seems to me that we have pretty good tools for managing files that aren&#8217;t changing. We have file managers that display all the pertinent details, they&#8217;ll detect the file type, they&#8217;ll even show a preview if the content is an image or a video.
But what about files that are changing? Files get transfered all [...]]]></description>
			<content:encoded><![CDATA[<p>It seems to me that we have pretty good tools for managing files that aren&#8217;t changing. We have file managers that display all the pertinent details, they&#8217;ll detect the file type, they&#8217;ll even show a preview if the content is an image or a video.</p>
<p>But what about files that are changing? Files get transfered all the time, but network connections are not always reliable. Have you ever been in the middle of a transfer wondering if it just stopped dead, wondering if it&#8217;s crawling along very slowly, too slow, almost, to notice? Or how about downloading something where the host doesn&#8217;t transmit the size of the file, so you&#8217;re just downloading not knowing how much there is left?</p>
<p>These things happen, not everyday, but from time to time they do. And it&#8217;s annoying. A file manager doesn&#8217;t really do a great job of showing you what&#8217;s happening. Of course you can stare at the directory and reload the display to see if the file size is changing. (Or the time stamp? But that&#8217;s not very convenient to check against the current time to measure how long it was since the last change.) Or maybe the file manager displays those updates dynamically? But it&#8217;s still somewhat lacking.</p>
<p>Basically, what you want to know is:</p>
<ol>
<li>Is the file being written to right now?</li>
<li>How long since the last modification?</li>
</ol>
<p>And you want those on a second-by-second basis, ideally. Something like this perhaps?</p>
<p><img class="alignnone size-full wp-image-2447" title="peek" src="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/peek.png" alt="peek" width="433" height="55" /></p>
<p>Here you have the files in this directory sorted by modification time (mtime). One file is actively being written to, you can see the last mtime was 0 seconds ago at the time of the last sampling. Sampling happens every second, so in that interval 133kb were written to the file and the mtime was updated. The other file has not been changed for the last 7 minutes.</p>
<p>The nice thing about this display is that whether you run the monitor while the file is being transfered or you start it after it&#8217;s already finished, you see what is happening, and if nothing is, you see <em>when</em> the last action took place.</p>
<pre class="python"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Author: Martin Matusiak &lt;numerodix@gmail.com&gt;</span>
<span style="color: #808080; font-style: italic;"># Licensed under the GNU Public License, version 3.</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># &lt;desc&gt; Watch directory for changes to files being written &lt;/desc&gt;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #dc143c;">Formatter</span><span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    size_units = <span style="color: black;">&#91;</span><span style="color: #483d8b;">' b'</span>, <span style="color: #483d8b;">'kb'</span>, <span style="color: #483d8b;">'mb'</span>, <span style="color: #483d8b;">'gb'</span>, <span style="color: #483d8b;">'tb'</span>, <span style="color: #483d8b;">'pb'</span>, <span style="color: #483d8b;">'eb'</span>, <span style="color: #483d8b;">'zb'</span>, <span style="color: #483d8b;">'yb'</span><span style="color: black;">&#93;</span>
    time_units = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'sec'</span>, <span style="color: #483d8b;">'min'</span>, <span style="color: #483d8b;">'hou'</span>, <span style="color: #483d8b;">'day'</span>, <span style="color: #483d8b;">'mon'</span>, <span style="color: #483d8b;">'yea'</span><span style="color: black;">&#93;</span>
&nbsp;
    @<span style="color: #008000;">classmethod</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> simplify_time<span style="color: black;">&#40;</span>cls, tm<span style="color: black;">&#41;</span>:
        unit = <span style="color: #ff4500;">0</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> tm &gt; <span style="color: #ff4500;">59</span>:
            unit += <span style="color: #ff4500;">1</span>
            tm = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>tm<span style="color: black;">&#41;</span> / <span style="color: #ff4500;">60</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> tm &gt; <span style="color: #ff4500;">59</span>:
                unit += <span style="color: #ff4500;">1</span>
                tm = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>tm<span style="color: black;">&#41;</span> / <span style="color: #ff4500;">60</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> tm &gt; <span style="color: #ff4500;">23</span>:
                    unit += <span style="color: #ff4500;">1</span>
                    tm = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>tm<span style="color: black;">&#41;</span> / <span style="color: #ff4500;">24</span>
                    <span style="color: #ff7700;font-weight:bold;">if</span> tm &gt; <span style="color: #ff4500;">29</span>:
                        unit += <span style="color: #ff4500;">1</span>
                        tm = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>tm<span style="color: black;">&#41;</span> / <span style="color: #ff4500;">30</span>
                        <span style="color: #ff7700;font-weight:bold;">if</span> tm &gt; <span style="color: #ff4500;">11</span>:
                            unit += <span style="color: #ff4500;">1</span>
                            tm = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>tm<span style="color: black;">&#41;</span> / <span style="color: #ff4500;">12</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">round</span><span style="color: black;">&#40;</span>tm<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>, cls.<span style="color: black;">time_units</span><span style="color: black;">&#91;</span>unit<span style="color: black;">&#93;</span>
&nbsp;
    @<span style="color: #008000;">classmethod</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> simplify_filesize<span style="color: black;">&#40;</span>cls, size<span style="color: black;">&#41;</span>:
        unit = <span style="color: #ff4500;">0</span>
        <span style="color: #ff7700;font-weight:bold;">while</span> size &gt; <span style="color: #ff4500;">1023</span>:
            unit += <span style="color: #ff4500;">1</span>
            size = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span> / <span style="color: #ff4500;">1024</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">round</span><span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>, cls.<span style="color: black;">size_units</span><span style="color: black;">&#91;</span>unit<span style="color: black;">&#93;</span>
&nbsp;
    @<span style="color: #008000;">classmethod</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> mtime<span style="color: black;">&#40;</span>cls, reftime, mtime<span style="color: black;">&#41;</span>:
        delta = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>reftime - mtime<span style="color: black;">&#41;</span>
        tm, unit = cls.<span style="color: black;">simplify_time</span><span style="color: black;">&#40;</span>delta<span style="color: black;">&#41;</span>
        delta_s = <span style="color: #483d8b;">"%s%s"</span> % <span style="color: black;">&#40;</span>tm, unit<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> delta_s
&nbsp;
    @<span style="color: #008000;">classmethod</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> filesize<span style="color: black;">&#40;</span>cls, size<span style="color: black;">&#41;</span>:
        size, unit = cls.<span style="color: black;">simplify_filesize</span><span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>
        size_s = <span style="color: #483d8b;">"%s%s"</span> % <span style="color: black;">&#40;</span>size, unit<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> size_s
&nbsp;
    @<span style="color: #008000;">classmethod</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> filesizedelta<span style="color: black;">&#40;</span>cls, size<span style="color: black;">&#41;</span>:
        size, unit = cls.<span style="color: black;">simplify_filesize</span><span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>
        sign = size &gt; <span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #483d8b;">"+"</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #483d8b;">""</span>
        size_s = <span style="color: #483d8b;">"%s%s%s"</span> % <span style="color: black;">&#40;</span>sign, size, unit<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> size_s
&nbsp;
    @<span style="color: #008000;">classmethod</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> bold<span style="color: black;">&#40;</span>cls, s<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">""</span><span style="color: #483d8b;">"Display in bold"</span><span style="color: #483d8b;">""</span>
        term = <span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">"TERM"</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> term <span style="color: #ff7700;font-weight:bold;">and</span> term != <span style="color: #483d8b;">"dumb"</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">"<span style="color: #000099; font-weight: bold;">\\0</span>33[1m%s<span style="color: #000099; font-weight: bold;">\\0</span>33[0m"</span> % s
        <span style="color: #ff7700;font-weight:bold;">return</span> s
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #008000;">File</span><span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    sample_limit = <span style="color: #ff4500;">60</span>  <span style="color: #808080; font-style: italic;"># don't hold more than x samples</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">file</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: #008000;">file</span> = <span style="color: #008000;">file</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">mtimes</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_name<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: #008000;">file</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_last_mtime<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        tm, sz = <span style="color: #008000;">self</span>.<span style="color: black;">mtimes</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">-1</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> tm
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_last_size<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        tm, sz = <span style="color: #008000;">self</span>.<span style="color: black;">mtimes</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">-1</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> sz
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_last_delta<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        size_last = <span style="color: #008000;">self</span>.<span style="color: black;">get_last_size</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            mtime_beforelast, size_beforelast = <span style="color: #008000;">self</span>.<span style="color: black;">mtimes</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">-2</span><span style="color: black;">&#93;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span> size_last - size_beforelast
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IndexError</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">0</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> prune_samples<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">""</span><span style="color: #483d8b;">"Remove samples older than x samples back"</span><span style="color: #483d8b;">""</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">mtimes</span><span style="color: black;">&#41;</span> % <span style="color: #008000;">self</span>.<span style="color: black;">sample_limit</span> == <span style="color: #ff4500;">0</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">mtimes</span> = <span style="color: #008000;">self</span>.<span style="color: black;">mtimes</span><span style="color: black;">&#91;</span>-<span style="color: #008000;">self</span>.<span style="color: black;">sample_limit</span>:<span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> sample<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, mtime, size<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">""</span><span style="color: #483d8b;">"Sample file status"</span><span style="color: #483d8b;">""</span>
        <span style="color: #808080; font-style: italic;"># Don't keep too many samples</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">prune_samples</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Update time and size</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">mtimes</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>mtime, size<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Directory<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, path<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">path</span> = path
        <span style="color: #008000;">self</span>.<span style="color: black;">files</span> = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> prune_files<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">""</span><span style="color: #483d8b;">"Remove indexed files no longer on disk (by deletion/rename)"</span><span style="color: #483d8b;">""</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">files</span>.<span style="color: black;">values</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            name = f.<span style="color: black;">get_name</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">file</span> = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">path</span>, name<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span><span style="color: #008000;">file</span><span style="color: black;">&#41;</span>:
                <span style="color: #ff7700;font-weight:bold;">del</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">files</span><span style="color: black;">&#91;</span>name<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> scan_files<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># remove duds first</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">prune_files</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># find items, grab only files</span>
        items = <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">path</span><span style="color: black;">&#41;</span>
        items = <span style="color: #008000;">filter</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> f: <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">path</span>, f<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
                       items<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># stat files, building/updating index</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> items:
            st = <span style="color: #dc143c;">os</span>.<span style="color: #dc143c;">stat</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">path</span>, f<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: black;">files</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>:
                <span style="color: #008000;">self</span>.<span style="color: black;">files</span><span style="color: black;">&#91;</span>f<span style="color: black;">&#93;</span> = <span style="color: #008000;">File</span><span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">files</span><span style="color: black;">&#91;</span>f<span style="color: black;">&#93;</span>.<span style="color: black;">sample</span><span style="color: black;">&#40;</span>st.<span style="color: black;">st_mtime</span>, st.<span style="color: black;">st_size</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> display_line<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name, time_now, tm, size, sizedelta<span style="color: black;">&#41;</span>:
        time_fmt = <span style="color: #dc143c;">Formatter</span>.<span style="color: black;">mtime</span><span style="color: black;">&#40;</span>time_now, tm<span style="color: black;">&#41;</span>
        size_fmt = <span style="color: #dc143c;">Formatter</span>.<span style="color: black;">filesize</span><span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>
        sizedelta_fmt = <span style="color: #dc143c;">Formatter</span>.<span style="color: black;">filesizedelta</span><span style="color: black;">&#40;</span>sizedelta<span style="color: black;">&#41;</span>
        line = <span style="color: #483d8b;">"%6.6s   %5.5s   %6.6s   %s"</span> % <span style="color: black;">&#40;</span>time_fmt, size_fmt,
                                               sizedelta_fmt, name<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> time_now - tm &lt; <span style="color: #ff4500;">6</span>:
            line = <span style="color: #dc143c;">Formatter</span>.<span style="color: black;">bold</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> line
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> sort_by_name<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, files<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">files</span>.<span style="color: black;">values</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, key=<span style="color: #ff7700;font-weight:bold;">lambda</span> x: x.<span style="color: black;">get_name</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> sort_by_mtime<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, files<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">files</span>.<span style="color: black;">values</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,
                      key=<span style="color: #ff7700;font-weight:bold;">lambda</span> x: <span style="color: black;">&#40;</span>x.<span style="color: black;">get_last_mtime</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,x.<span style="color: black;">get_name</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> display<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        time_now = <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        files = <span style="color: #008000;">self</span>.<span style="color: black;">sort_by_mtime</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">files</span>.<span style="color: black;">values</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">"<span style="color: #000099; font-weight: bold;">\\n</span>mtime&gt;   size&gt;   delta&gt;   name&gt;"</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> files:
            line = <span style="color: #008000;">self</span>.<span style="color: black;">display_line</span><span style="color: black;">&#40;</span>f.<span style="color: black;">get_name</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,
                                     time_now, f.<span style="color: black;">get_last_mtime</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,
                                     f.<span style="color: black;">get_last_size</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, f.<span style="color: black;">get_last_delta</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
    directory = Directory<span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            directory.<span style="color: black;">scan_files</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            directory.<span style="color: black;">display</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">KeyboardInterrupt</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">"<span style="color: #000099; font-weight: bold;">\\r</span>User terminated"</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        path = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IndexError</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">"Usage:  %s /path"</span> % <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    main<span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>
&nbsp;</pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/peek.py">peek.py</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/01/peek-monitor-files-for-changes/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

