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

    ip = <span style="color: #008000;">property</span><span style="color: black;">&#40;</span>fget=cache.<span style="color: black;">get</span>, fset=cache.<span style="color: #008000;">set</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;">### &lt;-- injected</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    iface = NetworkIface<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    iface.<span style="color: black;">ip</span> = <span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    iface.<span style="color: black;">ip</span> = <span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
    iface.<span style="color: black;">dhcp_request</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/main_t.py">main_t.py</a></p>
<p>Injected lines are marked. First we find some import statements that are meant to ensure that the codebase can find the aspect code on disk. Then we import the actual aspect module that holds our advice. And finally we can ascertain that <code>NetworkIface</code> has gained a property, with get and set methods pulled in from our aspect code.</p>
<h3>Running aspected</h3>
<p>When we now run <code>main.pyc</code> we get a message every time <code>ip</code> gets a new value. We also get a printout of all the previous values.</p>
<pre class="bash">c New value: <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
c New value: <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>
c  Previous values: <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
c New value: <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">131</span><span style="color: #66cc66;">&#41;</span>
c  Previous values: <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/main.output">main.output</a></p>
<p>And the yet the codebase has not been touched, if we execute <code>main.py</code> instead we find the original code.</p>
<h3>Here the show endeth</h3>
<p>And that wraps up a hasty introduction to AOP with aopy. There is a lot more to be said, both about AOP in Python and aopy in particular. Interested parties are kindly directed to these two papers:</p>
<ol>
<li><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/aop_strategies.pdf">Strategies for aspect oriented programming in Python</a></li>
<li><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/aopy.pdf">aopy: A program transformation-based aspect oriented framework for Python</a></li>
</ol>
<p>If you prefer reading code rather than English (variable names are still in English though, sorry about that), here is the repo for your pleasure:</p>
<ul>
<li><a href="http://github.com/numerodix/aopy">aopy repo</a></li>
</ul>
<p>And if you still have no idea what AOP is and think the whole thing is bogus then you can watch this <a href="http://video.google.com/videoplay?docid=8566923311315412414">google talk</a> (and who doesn&#8217;t love a google talk!) by mr. AOP himself.</p>
<img src="http://feeds.feedburner.com/~r/numerodix/~4/yfQWcahhAUo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/12/aopy-aspect-oriented-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.matusiak.eu/numerodix/blog/index.php/2010/03/12/aopy-aspect-oriented-python/</feedburner:origLink></item>
		<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. <span style="text-decoration: line-through;">A function is in fact a mutable object.</span> Have a look:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">def</span> f<span style="color: black;">&#40;</span>a=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>:
    a = <span style="color: #ff4500;">1</span>
&nbsp;
&gt;&gt;&gt; <span style="color: #ff7700;font-weight:bold;">print</span> f.<span style="color: black;">func_defaults</span>
<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: black;">&#41;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_keywords1.py">python_graphtraversal_keywords1.py</a></p>
<p><code>func_defaults</code> is the tuple that stores the values of the keyword parameters which have a default value. The value we see here is the integer 0, and it will not change no matter how many times we execute the function.</p>
<p>But collection types (and your own types too) are different:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">def</span> g<span style="color: black;">&#40;</span>a=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
    a.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> a
&nbsp;
&gt;&gt;&gt; <span style="color: #ff7700;font-weight:bold;">print</span> g.<span style="color: black;">func_defaults</span>
<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>,<span style="color: black;">&#41;</span>
&gt;&gt;&gt; g<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
&gt;&gt;&gt; <span style="color: #ff7700;font-weight:bold;">print</span> g.<span style="color: black;">func_defaults</span>
<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>,<span style="color: black;">&#41;</span>
&gt;&gt;&gt; g<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span></pre>
<p><i>Download this code: </i><a href="http://www.matusiak.eu/numerodix/blog/wp-content/uploads/python_graphtraversal_keywords2.py">python_graphtraversal_keywords2.py</a></p>
<p>Despite different, it actually works the same way (sorta). <strong>The binding of the keyword default is constant.</strong> But with an integer, the parameter is bound to the constant 0, whereas with &#8220;heavier&#8221; objects, it is bound to the object, but the object&#8217;s inner properties can very well mutate!!!</p>
<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>
	</channel>
</rss><!-- Dynamic Page Served (once) in 1.029 seconds --><!-- Cached page served by WP-Cache -->
