<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>numerodix blog</title>
	
	<link>http://www.matusiak.eu/numerodix/blog</link>
	<description>A blog about nothing</description>
	<lastBuildDate>Mon, 08 Mar 2010 15:24:07 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/numerodix" /><feedburner:info uri="numerodix" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>python patterns for graph traversal</title>
		<link>http://feedproxy.google.com/~r/numerodix/~3/q_tQu1OG7Ok/</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. A function is in fact a mutable object. 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>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/q_tQu1OG7Ok" height="1" width="1"/>]]></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>0</slash:comments>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/08/python-patterns-for-graph-traversal/</feedburner:origLink></item>
		<item>
		<title>we assume that you said yes</title>
		<link>http://feedproxy.google.com/~r/numerodix/~3/ovyjA6r5NBo/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/07/we-assume-that-you-said-yes/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 17:08:43 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[issues]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2495</guid>
		<description><![CDATA[It seems I&#8217;m late to the party. I read the call to arms on Ars Technica this morning (a site I like a lot, I have to say, although I don&#8217;t really visit much), and I immediately felt like I should have some reaction to it. I&#8217;ve made a pass or two over the topic [...]]]></description>
			<content:encoded><![CDATA[<p>It seems I&#8217;m late to the party. I read the <a href="http://arstechnica.com/business/news/2010/03/why-ad-blocking-is-devastating-to-the-sites-you-love.ars">call to arms</a> on Ars Technica this morning (a site I like a lot, I have to say, although I don&#8217;t really visit much), and I immediately felt like I should have some reaction to it. I&#8217;ve made a pass or two over the topic in the past, and so I felt hooked in. But nothing came to mind with immediate effect. So I put it away until I saw <a href="http://briancarper.net/blog/advertising-is-devastating-to-my-well-being">Brian&#8217;s shot heard around the world</a> on Planet Larry. And that&#8217;s when it finally hit me what this whole thing is about.</p>
<p>Ars Technica is bending over backwards not to make The Big Accusation, namely &#8220;if you skip the ads you are stealing&#8221;. And yet they still try to guilt trip you saying &#8220;well gosh, our business is on the line here, y&#8217;know?&#8221;.</p>
<p>I don&#8217;t know where Al Gore is, but there is a highly Inconvenient Truth here. And it is this: publishers are working from the assumption that the viewer has implicitly agreed to make them money without ever agreeing to it. This is why the Ars Technica article has to do that weird dance around the issue where they&#8217;re not calling you a cheat, but then they are, but then they&#8217;re not etc. Because if they did just come out and say it, they couldn&#8217;t look themselves in the mirror, because they have more self respect than <a href="http://www.matusiak.eu/numerodix/blog/index.php/2007/08/17/whyfirefoxisblocked-adorable-muppets/">certain muppets</a>.</p>
<p>Ars Technica couldn&#8217;t live with themselves if they actually came out and said: <em>Dear viewer, when we built this site we made the assumption that you would help us pay for it by looking at our ads. We never ran this by you, but we take it for granted that you have accepted this deal. Now we expect you to honor it.</em></p>
<p>There are others who are not so &#8220;modest&#8221;, like the entertainment industry claiming billions in damages based on sales they would have had if the people who downloaded stuff had paid for it. Here again, the assumption is that the consumer agreed to pay for something, and then refused. So who&#8217;s being cheated? The publisher!</p>
<p>But the viewer agreed to no such thing.</p>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/ovyjA6r5NBo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/07/we-assume-that-you-said-yes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/07/we-assume-that-you-said-yes/</feedburner:origLink></item>
		<item>
		<title>fake a dual monitor display!</title>
		<link>http://feedproxy.google.com/~r/numerodix/~3/-3Fcr6q37HE/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2010/01/30/fake-a-dual-monitor-display/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 15:56:16 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2491</guid>
		<description><![CDATA[Wouldn&#8217;t we all love to have a beefy workstation with at least two giant lcd monitors? Alas, I have a slim laptop with a small screen. And another laptop, almost 10 years old, albeit with a nice and large screen. I naturally prefer to use the newer machine for performance, but it also means making [...]]]></description>
			<content:encoded><![CDATA[<p>Wouldn&#8217;t we all love to have a beefy workstation with at least two giant lcd monitors? Alas, I have a slim laptop with a small screen. And another laptop, almost 10 years old, albeit with a nice and large screen. I naturally prefer to use the newer machine for performance, but it also means making do with a small monitor.</p>
<p>I can tell you it&#8217;s a real pain to author latex documents this way, I can&#8217;t fit both the kile and evince on the screen at the same time. It wasn&#8217;t until recently that it hit me what I was doing wrong. There are three processes involved here:</p>
<ol>
<li>Document editor.</li>
<li>Compiler (I run a loop that invokes make continuously in the background).</li>
<li>Document viewer.</li>
</ol>
<p>Come to think of it, this applies just as well to coding if you think &#8220;running the code&#8221; on the last step.</p>
<p>Well, X11 is a display server, for peet&#8217;s sake! So you have the editor on the workstation, but then you log in from the other laptop (with the larger screen) and run evince to display there.</p>
<p>Just do:</p>
<p style="padding-left: 30px;">oldlaptop$ ssh -XYC workstation</p>
<p>Don&#8217;t ask me why -Y, I don&#8217;t know, but that&#8217;s how I get my ubuntu to allow remote connections.</p>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/-3Fcr6q37HE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2010/01/30/fake-a-dual-monitor-display/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2010/01/30/fake-a-dual-monitor-display/</feedburner:origLink></item>
		<item>
		<title>a firewall in layman’s terms</title>
		<link>http://feedproxy.google.com/~r/numerodix/~3/THQZ2t4yKrY/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2010/01/21/a-firewall-in-laymans-terms/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 22:29:44 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2488</guid>
		<description><![CDATA[Dealing with companies can be frustrating, because they like to appear opaque to the outside world. When you look on the website you find a page with contact information. You&#8217;ll find a phone number and an email address, and maybe more than one if it&#8217;s a large company with several departments. But they all point [...]]]></description>
			<content:encoded><![CDATA[<p>Dealing with companies can be frustrating, because they like to appear opaque to the outside world. When you look on the website you find a page with contact information. You&#8217;ll find a phone number and an email address, and maybe more than one if it&#8217;s a large company with several departments. But they all point to the reception. Few companies are generous enough to give you direct access to their personnel with a listing of employees and their contact information.</p>
<p>So if there is a person you have to get to you have to do it through the reception. &#8220;Yes, I am blah and I need bleh and why don&#8217;t you just transfer me to the person I need to talk to, <em>per favore</em>!&#8221; It&#8217;s not a lot of fun, but this way whoever makes this decision to give out only the number of the reception can also decide who may and may not receive calls. And even on what conditions. If you say the magic word then, yes, you can get Frank on the line, otherwise not. And maybe Steve has been known to say too much and has a history of divulging information he wasn&#8217;t supposed to. So no, you can&#8217;t talk to Steve.</p>
<p>Well, this is the principle of a firewall. The reception screens calls with the discretion to reject or divert according to the protocol that has been instituted. Some people can be reached anytime, others only at certain intervals. Some are available depending on your request, and some are completely unreachable.</p>
<p>This picture, however, conflicts with the original meaning of the word firewall, which is a wall erected to stop a fire from spreading. Unconditionally.</p>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/THQZ2t4yKrY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2010/01/21/a-firewall-in-laymans-terms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2010/01/21/a-firewall-in-laymans-terms/</feedburner:origLink></item>
		<item>
		<title>detecting the os and distro on the system</title>
		<link>http://feedproxy.google.com/~r/numerodix/~3/RzjfgdA6PCA/</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>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/RzjfgdA6PCA" height="1" width="1"/>]]></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>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2010/01/06/detecting-the-os-and-distro-on-the-system/</feedburner:origLink></item>
		<item>
		<title>lazy function loading</title>
		<link>http://feedproxy.google.com/~r/numerodix/~3/FOoS_GCBkdA/</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>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/FOoS_GCBkdA" height="1" width="1"/>]]></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>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/08/lazy-function-loading/</feedburner:origLink></item>
		<item>
		<title>I must stop being amazed</title>
		<link>http://feedproxy.google.com/~r/numerodix/~3/K7vJi68jhys/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/04/i-must-stop-being-amazed/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 14:56:36 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[observations]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2456</guid>
		<description><![CDATA[Amazement is something for a special occasion. It is supposed to be rare. It is supposed to be worth a story. It is not for everyday use.
I amaze so easily, and so frequently, that amazement has ceased to be special to me. It has become mundane. I need to check my standards for amazement. I [...]]]></description>
			<content:encoded><![CDATA[<p>Amazement is something for a special occasion. It is supposed to be rare. It is supposed to be worth a story. It is not for everyday use.</p>
<p>I amaze so easily, and so frequently, that amazement has ceased to be special to me. It has become mundane. I need to check my standards for amazement. I need to raise the bar. I need to make amazement once again worth having.</p>
<p>I must stop being amazed, for example, when a man rings my doorbell because he cannot figure out the house numbers on my street. &#8220;Is this number thirty&#8221;, he asks. I lean out, in a mock gesture, to gaze at the street number opposite my front door. It does not say thirty. I imagine this gesture will suffice to make him understand. Instead he reiterates his dilemma. &#8220;Is this number thirty.&#8221; No. It is not. I must not be amazed, even if it is a man in his fifties. With gray hair, an elegant tie, and a fancy suit. Who proceeds to reenter his expensive automobile. How does a person like that not know how to read street numbers. I must not be amazed.</p>
<p>I must not be amazed, either, at the communal workers. Who must necessarily have intimate knowledge of such complicated administrative intricacies as are street numbers. Through their work of visiting various addresses everyday. Who still ring my doorbell by mistake.</p>
<p>One wonders how such people can accomplish complicated tasks like air travel, which requires all sorts of documents, procedures, requires remembering important facts and following a timetable. How do they manage it? It seems <span style="text-decoration: line-through;">amaz</span> I&#8217;m sure they pull it off somehow.</p>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/K7vJi68jhys" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/04/i-must-stop-being-amazed/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/04/i-must-stop-being-amazed/</feedburner:origLink></item>
		<item>
		<title>peek: monitor files for changes</title>
		<link>http://feedproxy.google.com/~r/numerodix/~3/yMziRwa4hx0/</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>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/yMziRwa4hx0" height="1" width="1"/>]]></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>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2009/12/01/peek-monitor-files-for-changes/</feedburner:origLink></item>
		<item>
		<title>a filter for life</title>
		<link>http://feedproxy.google.com/~r/numerodix/~3/rvx_PRZZo2g/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2009/11/05/a-filter-for-life/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 19:11:48 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[issues]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2429</guid>
		<description><![CDATA[There was a movement within the Norwegian education system at one point to emphasize the goal that kids in school should be critical. More than that, it should be the goal of the education system to teach us to be read critically. Don&#8217;t take everything you hear as gospel. This was back when I was [...]]]></description>
			<content:encoded><![CDATA[<p>There was a movement within the Norwegian education system at one point to emphasize the goal that kids in school should be critical. More than that, it should be the goal of the education system to teach us to be read critically. Don&#8217;t take everything you hear as gospel. This was back when I was still in junior high, so a good 15 years back. I don&#8217;t know if this theme is still current today, but at the very least it made a good pass through the common consciousness at one point.</p>
<p>So why did this come about? Well, in the early 90s television was privatized. There had been cable tv for a number of years already, but in 1992 the channel TV2, the first commercial tv station to broadcast nationally, alongside the state broadcaster NRK, was launched. Effectively, television was let go from under the control of the rather insular NRK and freed to be driven by commercial profit. Naturally, TV2 in short order proceeded to import all of the popular culture, chiefly American, that has informed our lives. Another characteristic of TV2, quite unlike NRK &#8212; the absolute sterility of any form of even mild intellectualism. (Aside from NRK which may have as much as 2-3 weekly hours of programming suited to the more discerning viewer, provided the topic is up your street.)</p>
<p>Another big development in the mid and late 90s, of course &#8212; wide access to the internet. Here again is a brand new medium with immense amounts of information and culture &#8220;beamed&#8221; right into our homes.</p>
<p>I feel it was these two developments that formed the impetus behind this fashion within the education system. All of a sudden students would be writing essays using web pages for sources that, believe it or not, were just <em>incorrect</em>. <img src='http://www.matusiak.eu/numerodix/blog/wp-includes/images/smilies/eek.png' alt=':eek:' class='wp-smiley' />  Oh noes, something has to be done! And so it began. The internet is not trustworthy. You can&#8217;t believe everything you read. The deeper reasoning behind this is the question of <strong>motive</strong>. More important than what they are saying; why are they saying it? Back in my junior high days we received the dumbed down version (as, actually, with everything in junior high). The question was framed in terms of <em>sources</em>. This source is reliable, because it&#8217;s Encyclopedia Britannica. This source is not, because it&#8217;s a web page, or I heard it on tv. Never mind who gets to decide what is reliable and why.</p>
<p>Of course, the truth, as your astute self would have figured out by now, is that nothing is in and of itself trustworthy. It&#8217;s not just when you go online that you find garbage. There&#8217;s just as much garbage in books, in what your teachers tell you, in what your parents tell you, and above all in what your peers tell you. You need to be critical of all this stuff, not just of those crazy people on the internet.</p>
<p><em>I&#8217;m inadvertently rehashing <a href="http://the-gay-bar.com/index.php?/archives/341-On-sources/">Jürgen&#8217;s argument</a> here. I read his entry and didn&#8217;t give it any more thought, but perhaps my subconsciousness has been chewing on it ever since? Thanks, Jürgen.</em></p>
<p>Naturally, some people are just malicious, but that is not the main problem. Even if you do have a piece of insight that you honestly believe is beneficial to someone, there are still a lot of things that can go wrong:</p>
<ol>
<li>You&#8217;re plain mistaken.</li>
<li>It works for you, but it doesn&#8217;t work for everyone.</li>
<li>Even though you have the right idea, you fail to communicate it effectively.</li>
</ol>
<p>The last one is particularly unfortunate. How many times has someone told you that they&#8217;ve just this discovered this new thing and it&#8217;s everything they needed, and then you say &#8220;but I told you that already a long time ago!&#8221;. Well, I guess you didn&#8217;t tell me in the words that I needed to hear in order to absorb the information, or in order to be convinced.</p>
<p>Parental advice, of course, is susceptible to the same flaw as those self help books. I&#8217;m sure you&#8217;ve seen some of those around, the basic premise is always the same &#8212; some person has figured out how to do something and wants to tell everyone. The problem is that just because it worked for him, doesn&#8217;t mean it will work for you. Especially when you hear it from a secondary source (a relative comes up and says &#8220;I read this amazing book, it changed my life, all you have to do is..&#8221;). But it&#8217;s not science. At best it &#8220;sorta works a lot of the time, kind of&#8221;.</p>
<p>So over time you develop a filter. &#8220;This person is not worth listening to on <em>these</em> topics, <em>this</em> book is written by someone who has no idea what he&#8217;s talking about, this website is usually reliable on <em>these</em> issues&#8221;. Now everything depends on that filter of yours. You may find one day that you bought into some utter nonsense, or that you discarded good insight.</p>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/rvx_PRZZo2g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2009/11/05/a-filter-for-life/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2009/11/05/a-filter-for-life/</feedburner:origLink></item>
		<item>
		<title>how much time you got?</title>
		<link>http://feedproxy.google.com/~r/numerodix/~3/44HDvR3ie4Q/</link>
		<comments>http://www.matusiak.eu/numerodix/blog/index.php/2009/10/23/how-much-time-you-got/#comments</comments>
		<pubDate>Fri, 23 Oct 2009 13:25:18 +0000</pubDate>
		<dc:creator>numerodix</dc:creator>
				<category><![CDATA[observations]]></category>

		<guid isPermaLink="false">http://www.matusiak.eu/numerodix/blog/?p=2426</guid>
		<description><![CDATA[One of the most important currencies of today is time. Of course, people have always been trading in time, paying people to do things for them that they were either too lazy, or &#8220;too important&#8221;, to do. But in today&#8217;s world time has gone as far as to replace money in the daily rhetoric of [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most important currencies of today is time. Of course, people have always been trading in time, paying people to do things for them that they were either too lazy, or &#8220;too important&#8221;, to do. But in today&#8217;s world time has gone as far as to replace money in the daily rhetoric of many people. I wonder if people in the past spent as much time complaining about not having enough time as it&#8217;s common to do today. We have more freedoms and opportunities than ever, there&#8217;s just no time to enjoy them all.</p>
<p>The biggest complaint among people today, once they stop complaining about lack of money, is lack of time. There is a strange kind of contempt for people who have time.<br />
- Look at this cool thing these guys did.<br />
- Yeah they really have a lot of time on their hands (those rich bastards!)</p>
<p>Strangely enough, there are also those who have a sense of pride about *not* having time. They just love fake-complaining to you about how busy they are. Well who decided you have to be so busy? Oh, I know, *you* did. Here, I have the solution for you. Ditch _everything_ that you&#8217;re doing right now and you&#8217;ll have more time than you ever dreamed of.</p>
<p>Being busy is also the standard way to lie to yourself when rejecting people. &#8220;Oh dear, I&#8217;d love to come to your whatever, but I&#8217;m just so darn busy&#8221;. No, you just decided that you&#8217;d rather do something else. *I* know what it means, and you might as well just have told me that you weren&#8217;t interested instead of telling yourself that you&#8217;re a caring person who never lets anyone down. Because that&#8217;s just plain obnoxious.</p>
<p>Now, what people seem to forget is that unlike money, time is very much your own choice. You don&#8217;t choose to be born into a wealthy family, but you can easily choose to be rich on time. Here&#8217;s a simple test: do you have a tv? Unplug it. You just won hours upon hours of time and it didn&#8217;t cost you a dime! (Unless of course tv is what you most want to use your time for, but then you shouldn&#8217;t complain about lack of time, you should revel in all the tv time you have!)</p>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/44HDvR3ie4Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2009/10/23/how-much-time-you-got/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2009/10/23/how-much-time-you-got/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic Page Served (once) in 1.531 seconds --><!-- Cached page served by WP-Cache -->
