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

<channel>
	<title>Let's discuss the matter further</title>
	<atom:link href="http://rhodesmill.org/brandon/feed/" rel="self" type="application/rss+xml" />
	<link>http://rhodesmill.org/brandon</link>
	<description>Thoughts of Brandon Craig Rhodes</description>
	<pubDate>Sat, 19 Apr 2008 18:31:24 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Name your home machines using Tomato</title>
		<link>http://rhodesmill.org/brandon/2008/tomato-reverse-dns/</link>
		<comments>http://rhodesmill.org/brandon/2008/tomato-reverse-dns/#comments</comments>
		<pubDate>Thu, 17 Apr 2008 03:38:25 +0000</pubDate>
		<dc:creator>Brandon Craig Rhodes</dc:creator>
		
		<category><![CDATA[Computing]]></category>

		<guid isPermaLink="false">http://rhodesmill.org/brandon/?p=16</guid>
		<description><![CDATA[  
I am enjoying my first weeks of using the Tomato Firmware. I purchased a Linksys WRT54GL wireless router because of its admirable support for third-party firmware like Tomato, which replaces the traditional Linksys setup screens with an alterative system with many more configuration options. I can also connect directly to Tomato over SSH and [...] ]]></description>
			<content:encoded><![CDATA[<p> <iframe src="http://rcm.amazon.com/e/cm?t=letsdisthemat-20&#038;o=1&#038;p=8&#038;l=as1&#038;asins=B000BTL0OA&#038;fc1=000000&#038;IS2=1&#038;lt1=_blank&#038;lc1=0000FF&#038;bc1=000000&#038;bg1=FFFFFF&#038;f=ifr" style="width:120px;height:240px;float:right;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe></p>
<p>I am enjoying my first weeks of using the <a href="http://www.polarcloud.com/tomato">Tomato Firmware</a>. I purchased a <a href="http://www.amazon.com/gp/product/B000BTL0OA?ie=UTF8&#038;tag=letsdisthemat-20&#038;linkCode=as2&#038;camp=1789&#038;creative=9325&#038;creativeASIN=B000BTL0OA">Linksys WRT54GL wireless router</a> because of its admirable support for third-party firmware like Tomato, which replaces the traditional Linksys setup screens with an alterative system with many more configuration options. I can also connect directly to Tomato over SSH and use it as a very small Linux system! This opens endless possibilities for writing fancy firewall rules and running small embedded applications right at the border of my home network.</p>
<p>The Tomato firmware uses a small DNS server named <b><a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a></b> to answer the steady stream of domain name requests from my home computers. It converts domain names that I type, like <tt>rhodesmill.org</tt> or <tt>google.com</tt>, into the low-level IP addresses with which computers identify each other.</p>
<p>But I also like using hostnames for the machines sitting right in my home, even though they do not have “real names” out on the Internet. I recommend placing local hostnames inside of a top-level domain that is local to your own network. Choose a suffix that differs from all of the top-level domains that exist out on the Internet — avoid <tt>.com</tt>, <tt>.net</tt>, or <tt>.uk</tt>, for example, in favor of something like <tt>.home</tt> or <tt>.myhouse</tt> instead. How, I wondered, could I add extra host names to <b>dnsmasq</b>?</p>
<p><span id="more-16"></span></p>
<p>After my first glance through the <b>dnsmasq</b> documentation, I thought that a series of <tt>address</tt> options might be the best way to provide my local hosts with names. So I visited its Tomato setup screen, which is under the <i>DHCP / DNS</i> section of the <i>Advanced</i> configuration options, and entered something like this into the “Custom Configuration” file:</p>
<pre>
local-ttl=1
address=/mail.home/192.168.1.2
address=/gamebox.home/192.168.1.3
address=/printer.home/192.168.1.5
</pre>
<p>The <tt>local-ttl</tt> option is necessary because the default value, zero, encourages the <i>host(1)</i> command on my Linux machine to issue a warning message for every host I look up.</p>
<p>This setup seemed to work fine, and made it possible to use hostnames like <tt>gamebox.home</tt> when connecting from one machine to another on my home network. But I noticed delays when creating SSH connections between home machines, as well as errors in my system logs, and, as a result, discovered that this configuration was only working in the forward direction: <b>dnsmasq</b> knew that <tt>gamebox.home</tt> was a name for the IP address 192.168.1.3, but it could <i>not</i> answer the reverse question, “What name belongs to the IP address 192.168.1.3?”</p>
<p>I returned to the <b>dnsmasq</b> documentation, read more thoroughly, and learned that it publishes <i>both</i> forward and reverse names for hosts that it finds in the <tt>/etc/hosts</tt> file. While the Tomato firmware does not seem to support an editable <tt>/etc/hosts</tt> file whose contents will reappear when the Linksys router reboots, it does provide an auxiliary flash-based filesystem. So I was able to solve my problem in three steps:</p>
<ul>
<li>I visited the <i>JFFS2</i> screen in <b>dnsmasq</b>, under the <i>Administration</i> section, and enabled it. This creates a writable flash-based filesystem that gets mounted at <tt>/jffs</tt> every time the router boots up.
<li>I created a <tt>/jffs/hosts</tt> file by connecting to Tomato with SSH and using <tt>vi</tt> to edit and save the file. It looks like a normal <tt>/etc/hosts</tt> file:
<pre>
192.168.1.2 mail.home
192.168.1.3 gamebox.home
192.168.1.5 printer.home
</pre>
<li>Finally, I removed all of the host names from the <b>dnsmasq</b> configuration itself, and simply provided the path to my new <tt>hosts</tt> file instead:
<pre>
local-ttl=1
addn-hosts=/jffs/hosts
</pre>
</ul>
<p>With this improvement, both forward and reverse name lookups now work perfectly! To add or remove a host name in the future, I can simply re-edit the file. Though I once dreaded the inflexibility of small embedded appliances, Tomato has finally convinced me to replace the large, noisy Linux box at the edge of my network with something far more tidy and sleek.</p>
]]></content:encoded>
			<wfw:commentRss>http://rhodesmill.org/brandon/2008/tomato-reverse-dns/feed/</wfw:commentRss>
		</item>
		<item>
		<title>How To Produce A Linux Screencast</title>
		<link>http://rhodesmill.org/brandon/2008/how-to-produce-a-linux-screencast/</link>
		<comments>http://rhodesmill.org/brandon/2008/how-to-produce-a-linux-screencast/#comments</comments>
		<pubDate>Wed, 27 Feb 2008 05:50:33 +0000</pubDate>
		<dc:creator>Brandon Craig Rhodes</dc:creator>
		
		<category><![CDATA[Computing]]></category>

		<guid isPermaLink="false">http://rhodesmill.org/brandon/2008/how-to-produce-a-linux-screencast/</guid>
		<description><![CDATA[  Learning how to create Linux screencasts has been the most frustrating technical challenge that I have tackled for a very long time. I should have been worried when a search for “Linux video editing” returned, as its top hit, a bare and completely unstyled web page from 2002 which concludes that “video editing on [...] ]]></description>
			<content:encoded><![CDATA[<p> Learning how to create Linux screencasts has been the most frustrating technical challenge that I have tackled for a very long time. I should have been worried when a search for “Linux video editing” returned, as its top hit, a <a href="http://www.robfisher.net/video/">bare and completely unstyled web page from 2002</a> which concludes that “video editing on Linux hasn&#8217;t really arrived yet.”</p>
<p>My efforts were, in the end, successful, and you can see the result — my first two screencasts — <a href="http://rhodesmill.org/brandon/2008/presentations-on-buildout-and-kss/">in my previous blog entry</a>, which I posted earlier this week.</p>
<p>In the hope that my toil can benefit others, let me outline the details of the process that I have worked out for creating, editing, and posting Linux screencasts. For the impatient, here are the three most important things I learned:</p>
<ul>
<li>Linux tools have great difficulty keeping audio and video from gradually going out of sync over several minutes. To avoid problems, always run <a href="http://recordmydesktop.iovar.org/">recordmydesktop</a> with its “on-the-fly encoding” option, and never let “ffmpeg” anywhere near your audio! This not only means that you have to use “mencoder” instead when converting between video formats, but even within mencoder you must avoid the “lavc” audio module, since its code seems to have the same problems.
<li>Do not attempt to directly edit the resulting Ogg/Theora video! Instead, convert first to the Digial Video (DV) format, and perform your editing there. Be prepared for the fact that DV files are enormous, and that DV pixels are not square.
<li>Finally, convert to something like AVI for submission to <a href="http://video.google.com/">Google Video</a>. Avoid submitting a raw Ogg/Theora file, since even though Google can decode it, their decoders will waste valuable screen space by placing an empty border around the result.
</ul>
<p>For those interested in more details, I have more to share. Keep reading!</p>
<p><span id="more-14"></span></p>
<h3>Recording the screencast</h3>
<p>In order to record a screencast using Linux, use <a href="http://recordmydesktop.iovar.org/">recordmydesktop</a>. I can&#8217;t tell you how to get your sound card working with it, because — much to my surprise — when I plugged my old 1990s-vintage sound card microphone into my sound card, it <i>simply worked</i> and my voice was right there in the recording. So I was at least spared an epic battle with my audio configuration.</p>
<p>The recordmydesktop tool produces video in the open Ogg/Theora format, and the results look very sharp. It names its first output file <tt>out.ogv</tt> and, if you run it again, next uses the names <tt>out.ogv.1</tt>, <tt>out.ogv.2</tt>, and so forth. This makes it easy to sort through the clips that you have produced after making several attempts at a particular scene. There are four options that I found helpful when using recordmydesktop:</p>
<ul>
<li>Ask for the video to be encoded during recording, rather than at the end:
<pre>recordmydesktop --on-the-fly-encoding</pre>
<p>This uses more CPU during the presentation, but was necessary — at least on my machine — to produce audio and video that stayed in sync. Without it, the audio and video started to diverge visibly within a minute or so, and by minute three or four you would hear me talking about a completely different slide than the one showing on the screen.</p>
<li>Ask for a full screen-shot to be made every frame:
<pre> --full-shots</pre>
<p>I needed this because the presentation software that I use, <a href="http://keyjnote.sourceforge.net/">KeyJnote</a>, uses OpenGL to produce extremely smooth transitions between my PDF slides, and only full screen-shots capture the contents of OpenGL accelerated windows. (If you&#8217;re curious: I created my presentation slides with OpenOffice Impress, and then exported to PDF.)</p>
<li>Choose a recording area and frame rate appropriate for the Digital Video format we will use for editing:
<pre> -fps 29.97 -width 720 -height 528</pre>
<p>You might have thought that, since DV frames are 720×480 pixels in size, you should use those dimensions when running recordmydesktop. But it turns out that, while pixels on a typical computer display are square, DV pixels are noticeably taller — so our 528 vertical pixels of captured video will just barely fill the 480 vertical lines of each DV frame. I should thank <a href="http://lipas.uwasa.fi/~f76998/video/conversion/">Jukka Aho&#8217;s guide to video resolution</a>, without which this aspect ratio problem might have left me very confused.</p>
<li>Finally, I ask for the recording area to be offset a bit from the upper-left corner of the screen:
<pre> -x 20 -y 40</pre>
<p>This offset allows me to hide the borders around my KeyJnote window, or any other window — such as an xterm — that I place in the area of my screen that is being recorded. Before doing my first real screen captures, I start up recordmydesktop, and use the box that it draws around its recording area to position my other windows so that only their content shows.</p>
</ul>
<p>I noticed that recordmydesktop often does not record exactly the area that I specify. Instead, it seems to have a fondness for rounding the height and width to multiples of 16. But all that matters is that the recording area is close to the right size, since, again, I use the handy border that it draws around the area — and not the exact numbers I have specified — to position the windows I&#8217;m recording.</p>
<p>To make positioning windows in the recorded area easier, I tend to make their content slightly oversized. When running KeyJnote, for example, I use:</p>
<pre>keyjnote -f -g 724x532 python-before-eggs.pdf</pre>
<p>This gives me a few pixels of leeway within which to position the window without its inner edges showing in the recording. Similarly, I create my xterms with quite wide margins using the <tt>-b</tt> option, then drag the corners around until I like how much text is showing in the presentation area.</p>
<pre>xterm -fa inconsolata -fs 16 -b 32</pre>
<p>The fact that I only record an area 720 pixels wide leaves some space available toward the right side of my monitor, where I can place things like a narrow text editor with notes about what I want to say, which tends to make my screencast smoother than if I am making up words as I go along.</p>
<h3>Editing the presentation</h3>
<p>After recording my first presentation, I tried every single movie editor that I could find for Linux, and finally concluded that none of them could edit Ogg/Theora videos. They either failed to recognize the file format, or would crash during editing, or produce garbled output. The format does seem to be rather obscure outside the Free Software world, so I tried converting my video to more popular formats before editing it — and found that many of the same problems still arose!</p>
<p>I have concluded that the movie editors available under Linux are simply not prepared for the challenges of editing highly compressed video formats. When dealing with compressed video, merely displaying a given frame when the user clicks on it can be a lot of work — one must first rewind to the most recent keyframe, then apply the series of changes encoded in the subsequent frames. Obviously, even the simplest editing can make complete hash of the existing sequence of keyframes and updates. After doing even simple edits, I found that I could no longer even click somewhere on my recording and have a coherent image come up in the movie editor.</p>
<p>After hours of experimentation and research, I have adopted the Digital Video (DV) format for all of my editing. The DV format was designed with editing in mind: each frame is independently compressed. This makes it a very easy format for a program to handle as you select frames, cut out segments of video, and paste them back in somewhere else.</p>
<p>Although the DV format can only support a few fixed screen sizes, whose dimensions and aspect ratios were determined by the ancient properties of broadcast television, its NTSC size of 720×480 is plenty large enough to capture the detail in a typical screencast — particularly if you are going to be mixing it down to the size supported by a video-sharing site like YouTube or Google Video.</p>
<p>As I mentioned at the beginning of this article, always use mencoder from the <a href="http://www.mplayerhq.hu/">MPlayer</a> project for converting video. To create an editable DV file from the <tt>out.ogv</tt> produced by recordmydesktop, I use the command:</p>
<pre>mencoder out.ogv -ovc libdv -oac pcm \
 -vf scale=720:480 -o editme.dv</pre>
<p>This command also goes ahead and converts the square pixels off of your screen into pixels with the proper shape for the DV format.</p>
<p>Do be prepared for the fact that the DV format results in recordings that are absolutely enormous. Plan on the file consuming about a gigabyte for every four minutes of video, and simply consider this the cost of having every single frame randomly accessible during the editing process.</p>
<p>Which video editor should you use? I lack the time to produce a full review of each option. Instead, I will heartily recommend that you use <a href="http://heroinewarrior.com/cinelerra.php3">Cinelerra</a>, for three reasons:</p>
<ul>
<li>Cinelerra is a “non-linear” video editor, which means that it shows you a time-line picture of your presentation, including your audio track. It&#8217;s the audio track that&#8217;s especially important! Each of your words shows up as a visible bump in the volume, which makes it really easy to put sentences back together again if, while recording, you made a mistake, paused, and then repeated the last few words again to get them correct.
<li>Cinelerra does not actually alter your source video file. Each time you save your project, it just saves a tiny <tt>project.xml</tt> file listing the pieces of video and audio that you&#8217;ve clipped together on its timeline. This means that it&#8217;s not wasting effort trying to modify your multi-gigabyte DV file; instead, it&#8217;s just remembering which frames of the DV file should be rendered after all of your cutting and pasting are complete.
<li>Because Cinelerra doesn&#8217;t save any information inside of your video file, you can actually just delete the DV file when you&#8217;re done using Cinelerra! If you want the ability to do more editing in the future, just keep around your original Ogg/Theora file and the <tt>project.xml</tt> generated from Cinelerra, and you can always re-generate the DV file (with the command given above) and then re-run Cinelerra.
</ul>
<p>One hint: when Cinelerra starts, not only will its timeline window appear, but also a window for recording video off of a live camera. Close the recording window, which won&#8217;t help you during editing, and use the “Windows” pull-down menu to open a “Compositor” window instead. It is the Compositor window that will let you see your presentation&#8217;s video as you edit.</p>
<p>When you are done editing and are ready to have Cinelerra “render” the result to a new movie file, you are given a choice of output formats. I found that saving to yet another Ogg/Theora file gave the best results.</p>
<h3>Mixing back down</h3>
<p>Finally, before you submit your screencast to Google Video, or YouTube, or wherever, there are three final goals to be accomplished:</p>
<ul>
<li>Convert it into a popular format that the hosting service will appreciate. Though Google Video can now process Ogg/Theora files, it seems to put ugly margins around them. I found that submitting the same data as an AVI file produced much more attractive results. (Not that Google Video has terribly good image quality either way!)
<li>Adjust the resolution. Typically, you will want to reduce it from 720 pixels across to something more modest.
<li>Finally, in my case the volume always needs to be adjusted; my microphone is very quiet. So, I ask for the volume to be increased so that my voice hovers around half of full volume. Listen to your result, and change this number to suit your own taste.
</ul>
<p>All three of these final goals are accomplished with a single command line:</p>
<pre>
mencoder cinelerra.ogg -vf scale=640:480 \
 -af volnorm=1:0.5 -ovc lavc -oac twolame \
 -o final.avi
</pre>
<p>The <tt>final.avi</tt> file is now ready to be posted on the Web!</p>
<p>I hope this helps someone through the frustrations of preparing a screencast themselves. I myself will be looking for more screencast topics in the near future, so that I can use all of this advice again myself. Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://rhodesmill.org/brandon/2008/how-to-produce-a-linux-screencast/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Presentations on Buildout and KSS</title>
		<link>http://rhodesmill.org/brandon/2008/presentations-on-buildout-and-kss/</link>
		<comments>http://rhodesmill.org/brandon/2008/presentations-on-buildout-and-kss/#comments</comments>
		<pubDate>Sun, 24 Feb 2008 04:29:13 +0000</pubDate>
		<dc:creator>Brandon Craig Rhodes</dc:creator>
		
		<category><![CDATA[Computing]]></category>

		<category><![CDATA[Grok]]></category>

		<category><![CDATA[Python]]></category>

		<category><![CDATA[Zope]]></category>

		<guid isPermaLink="false">http://rhodesmill.org/brandon/2008/presentations-on-buildout-and-kss/</guid>
		<description><![CDATA[  After several frustrating weeks learning how to create, edit, and publish a screencast under Linux (about which I will write a separate post), I have now published screencasts of both presentations that I gave at the PyAtl meetup in January. I opened with a talk about the import statement, and where Python packages lived [...] ]]></description>
			<content:encoded><![CDATA[<p> After several frustrating weeks learning how to create, edit, and publish a screencast under Linux (about which I will write a separate post), I have now published screencasts of both presentations that I gave at the PyAtl meetup in January. I opened with a talk about the <tt>import</tt> statement, and where Python packages lived before egg files were invented:</p>
<div class="movietitle"><a href="http://video.google.com/videoplay?docid=5996823626349389448"><b>Python Before Eggs</b></a></p>
<p><embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=5996823626349389448&#038;hl=en" flashvars=""> </embed></p>
</div>
<p>The audience seemed most interested in the last section of the talk, where I discuss three techiques for debugging problems with Python&#8217;s <tt>import</tt> statement; fast-forward to around 3:00 if you want to catch that part by itself.</p>
<p>Next, Jeremy Jones spoke about eggs, Noah Gift <a href="http://www.blog.noahgift.com/virtualenv.pdf">introduced virtualenv</a>, and, finally, I got back up to talk about buildout. This was probably <b>my own favorite</b> among the recent presentations I have given, and it&#8217;s the one I&#8217;ve worked hardest to adapt to a competent screencast:</p>
<div class="movietitle"><a href="http://video.google.com/videoplay?docid=3428163188647461098&#038;hl=en"><b>Introduction to Buildout</b></a></p>
<p><embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=3428163188647461098&#038;hl=en" flashvars=""> </embed></p>
</div>
<p>I have prepared a supplement to the above screencast that <a href="/brandon/buildout">gives additional hints and tips about using buildout</a>, as well as a link to the source code of the module that I use as my example.</p>
<p>Finally, if you&#8217;re ready to see something a little less polished — something that instead of being a screencast is actually a film of me talking in front of a live audience, and gesturing and jumping around — I filled a vacant lightning-talk slot at our February PyAtl meeting with an impromptu introduction to <a href="http://kssproject.org/">Kinetic Style Sheets</a> (KSS), using an example application that was still sitting on my laptop after at a Georgia Tech developer&#8217;s luncheon earlier that week:</p>
<div class="movietitle"><a href="http://video.google.com/videoplay?docid=3829442611478268688"><b>Introduction to KSS</b></a></p>
<p><embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=3829442611478268688&#038;hl=en" flashvars=""> </embed></p>
</div>
<p>Now I can finally turn my attention to preparing for my upcoming talk at PyCon 2008 in Chicago! I will be talking about the basic “adapter” design pattern, and how a framework like Zope 3 can facilitate its use. Stay tuned for more information!</p>
]]></content:encoded>
			<wfw:commentRss>http://rhodesmill.org/brandon/2008/presentations-on-buildout-and-kss/feed/</wfw:commentRss>
		</item>
		<item>
		<title>New PyEphem release: 3.7.2.2</title>
		<link>http://rhodesmill.org/brandon/2007/new-pyephem-release-3722/</link>
		<comments>http://rhodesmill.org/brandon/2007/new-pyephem-release-3722/#comments</comments>
		<pubDate>Tue, 11 Dec 2007 14:42:07 +0000</pubDate>
		<dc:creator>Brandon Craig Rhodes</dc:creator>
		
		<category><![CDATA[Computing]]></category>

		<category><![CDATA[PyEphem]]></category>

		<guid isPermaLink="false">http://rhodesmill.org/brandon/2007/new-pyephem-release-3722/</guid>
		<description><![CDATA[  On Sunday afternoon I released a new version of PyEphem, which is available from the Python Package Index as version 3.7.2.2!  I want to thank the users who spurred its development&#160;— in particular, John Duchek of the Astronomical Society of Eastern Missouri encouraged me both to create the new moon-phase functions, and, as [...] ]]></description>
			<content:encoded><![CDATA[<p> On Sunday afternoon I released a new version of <a href="http://rhodesmill.org/pyephem/">PyEphem</a>, which is available from the Python Package Index as <a href="http://pypi.python.org/pypi/pyephem/3.7.2.2">version 3.7.2.2</a>!  I want to thank the users who spurred its development&nbsp;— in particular, <a href="http://asemonline.org/archives/category/members-pages/john-ducheks-pages/">John Duchek</a> of the Astronomical Society of Eastern Missouri encouraged me both to create the new moon-phase functions, and, as I <a href="http://rhodesmill.org/brandon/2007/pyephem-available-for-windows/">announced</a> several weeks ago, to finally make PyEphem available in binary form for Windows.  Thanks, John!</p>
<p>PyEphem now also includes a small database of world cities, so that people living near one can simply call <tt>ephem.city(&#8217;Boston&#8217;)</tt> to get their longitude, latitude, and elevation, rather than having to look up the numbers themselves.</p>
]]></content:encoded>
			<wfw:commentRss>http://rhodesmill.org/brandon/2007/new-pyephem-release-3722/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A database symbol for GraphViz</title>
		<link>http://rhodesmill.org/brandon/2007/a-database-symbol-for-graphviz/</link>
		<comments>http://rhodesmill.org/brandon/2007/a-database-symbol-for-graphviz/#comments</comments>
		<pubDate>Fri, 23 Nov 2007 15:12:37 +0000</pubDate>
		<dc:creator>Brandon Craig Rhodes</dc:creator>
		
		<category><![CDATA[Computing]]></category>

		<category><![CDATA[Web Notes]]></category>

		<guid isPermaLink="false">http://rhodesmill.org/brandon/2007/a-database-symbol-for-graphviz/</guid>
		<description><![CDATA[ 
Download the source for my GraphViz database symbol featured in this article: DatabaseShape.ps

I have started using the GraphViz application, which accepts a list of nodes and arrows, and figures out how to attractively arrange them in a diagram. For example, you can very nearly produce this output:

by supplying this rather modest input file to GraphViz [...] ]]></description>
			<content:encoded><![CDATA[<blockquote>
<b>Download the source for my GraphViz database symbol featured in this article:</b> <a href="/brandon/static/2007-11/DatabaseShape.ps">DatabaseShape.ps</a>
</p></blockquote>
<p>I have started using the <a href="http://www.graphviz.org/">GraphViz</a> application, which accepts a list of nodes and arrows, and figures out how to attractively arrange them in a diagram. For example, you can very nearly produce this output:</p>
<p><img src="/brandon/static/2007-11/graphviz-with-database" /></p>
<p>by supplying this rather modest input file to GraphViz (most of whose length comes from my wanting particular colors)::</p>
<pre>
 digraph Application {
    rankdir=LR;
    node [shape=box,style=filled,fillcolor="#C0D0C0"];
    subgraph clusterClient {
       label=&#8221;Client&#8221;; style=filled; bgcolor=&#8221;#D0C0A0&#8243;;
       &#8220;Browser&#8221;;
    };
    subgraph clusterServer {
       label=&#8221;Server&#8221;; style=filled; bgcolor=&#8221;#D0C0A0&#8243;;
       &#8220;App&#8221;;
       &#8220;Database&#8221; [shape=DatabaseShape,peripheries=0];
    };
    &#8220;Browser&#8221; -> &#8220;App&#8221; [label="HTTP"];
    &#8220;App&#8221; -> &#8220;Database&#8221; [label="SQL"];
 }
</pre>
<p>I used the words “very nearly” because, in fact, GraphViz only knows how to draw simple shapes like rectangles, and is ignorant of the standard cylinder-shaped database symbol that I have used here by asking for a <tt>DatabaseShape</tt>. Submitting the above code to GraphViz will, normally, produce three nodes that are all rectangles. To teach it about the database shape, I had to write some PostScript.</p>
<p><span id="more-9"></span></p>
<p>The PostScript language is a beautifully compact version of the venerable FORTH language, and operates more or less like a Hewlett-Packard reverse Polish notation calculator hooked up to a sleeker version of the turtle from Logo. A program typically places numbers on the stack, perhaps invokes some mathematical operators on them, and finally invokes a graphics operation which uses those numbers as coordinates. For example, consider this code:</p>
<pre>
x1 x0 sub 2 div y0 lineto
</pre>
<p>This means, “place the value of the variable <i>x1</i> on the stack, then the value of <i>x0</i>, and then <i>subtract</i> to remove them from the stack and leave their difference there instead; then place the number <i>2</i> on the stack and <i>divide</i> so that only half of the previous result remains; then place the value of <i>y0</i> on the stack; and, finally, invoke the command <i>lineto</i> which removes the bottom two numbers from the stack and interprets them as the coordinates of a point to which it then draws a line.” In Python the same expression would be:</p>
<pre>
lineto((x1 - x0) / 2, y0)
</pre>
<p>Even small PostScript programs like my <a href="/brandon/static/2007-11/DatabaseShape.ps">DatabaseShape.ps</a> tend to wind up using a dozen or more different coordinates, so I always have to work first with pencil and paper to sketch the shape and define the variable names for my coordinates before then turning to my keyboard to write the code. It makes me remember my childhood, drawing things on graph paper before writing a BASIC program to draw the same shape on the screen.</p>
<p>One annoyance with using a user-defined shape like this with GraphViz is that one is restricted to using only its PostScript output mode, which means having to use an additional command to turn the PostScript into PDF or PNG or some other format. For example, if the example GraphViz code that I quoted above is placed in a <tt>sample.dot</tt> file, then to generate a PDF of the graph one must perform two steps:</p>
<pre>
$ dot -Tps2 -l DatabaseShape.ps sample.dot -o sample.ps
$ ps2pdf sample.ps sample.pdf
</pre>
<p>But since all the system diagrams that I need to produce at work will need to have databases in them, I&#8217;m just happy that I&#8217;ve worked out how to display the shape at all.</p>
]]></content:encoded>
			<wfw:commentRss>http://rhodesmill.org/brandon/2007/a-database-symbol-for-graphviz/feed/</wfw:commentRss>
		</item>
		<item>
		<title>My November Grok Presentation</title>
		<link>http://rhodesmill.org/brandon/2007/my-november-grok-presentation/</link>
		<comments>http://rhodesmill.org/brandon/2007/my-november-grok-presentation/#comments</comments>
		<pubDate>Sat, 10 Nov 2007 00:06:24 +0000</pubDate>
		<dc:creator>Brandon Craig Rhodes</dc:creator>
		
		<category><![CDATA[Computing]]></category>

		<category><![CDATA[Grok]]></category>

		<category><![CDATA[Python]]></category>

		<category><![CDATA[Zope]]></category>

		<guid isPermaLink="false">http://rhodesmill.org/brandon/2007/my-november-grok-presentation/</guid>
		<description><![CDATA[  In this post, I provide the slides and examples from a recent talk that I gave to some fellow software developers at Georgia Tech. Many of them were not familiar with web frameworks, and I wanted to introduce them to two common concepts: the idea of “convention over configuration,” and the practice of passing [...] ]]></description>
			<content:encoded><![CDATA[<p> In this post, I provide the slides and examples from a recent talk that I gave to some fellow software developers at Georgia Tech. Many of them were not familiar with web frameworks, and I wanted to introduce them to two common concepts: the idea of “convention over configuration,” and the practice of passing inert data structures to a page template rather than letting it access live objects directly.</p>
<p>But because I am also really enjoying my work with the new Python web framework <a href="http://grok.zope.org/">Grok</a>, I decided to make it the centerpiece of my presentation<span id="more-8"></span> and illustrate the more general principles of web development by showing how Grok works. I also gave the talk a week later at an Atlanta Plone gathering, where I knew the interest would be more on what makes Grok unique.</p>
<p>When I was asked for a copy of my slides, I realized that my presentation style — which involves showing several slides, moving to my editor and web browser for some actual programming, then diving back into my slides — leaves the PDF of the presentation perhaps not making as much sense by itself as it might otherwise:</p>
<blockquote><p><a href="http://rhodesmill.org/brandon/static/2007-11/grok-slides.pdf">Click here to download the PDF of my presentation</a></p></blockquote>
<p>Hence, this post. Here I take the reader through the aspects of my talk that failed to make it on to the slides, showing both the command-line operations and the coding that illustrated and made sense of the presentation itself.</p>
<h2><a id="creating-a-grok-instance" name="creating-a-grok-instance">Creating a Grok Instance</a></h2>
<p>After some initial slides introducing the idea of “convention over configuration,” my presentation introduces Grok itself — making good use, I think, of the symbolic value of his club — and then announces, “Let&#8217;s create a Grok instance!” This is the point at which I bring up a command prompt and show the audience how easy <tt>grokproject</tt> makes it to start a new project:</p>
<pre>
$ grokproject MyApp
$ ./MyApp/bin/zopectl fg
</pre>
<p>After <tt>zopectl</tt> has finished starting up, I point my web browser at <tt>http://localhost:8080/</tt>, and then suffer a silent moment of frustration about the fact the web page that appears is <em>not</em> simply the welcome message from the new Grok app. Instead, the “admin interface” comes up, and insists on being fed an application instance name before allowing me to proceed. I choose <tt>lotr</tt> as the name, then show the audience that <tt>http://localhost:8080/lotr</tt> is where the new application lives.</p>
<p>Before continuing with my slides, I visit the directory <tt>MyApp/src/MyApp</tt> and give the audience brief glimpses of both <tt>app.py</tt> and the <tt>app_templates</tt> directory. This introduces three items which will be critical as the slides resume: the <tt>MyApp</tt> object, the <tt>Index</tt> view, and the <tt>index.pt</tt> page template. With these three items pointed out, I am ready to proceed with my slides and discuss how the object, view, and page template together form Grok&#8217;s “Threefold Way” of making objects available on the web.</p>
<h2><a id="the-actual-example" name="the-actual-example">The Actual Example</a></h2>
<p>Only a few slides later, the time arrives for a more sophisticated example. The presentation exaggerates when it instructs me to “go add some models and further views to your application.” I do not, in fact, make the audience watch me write code, but present them with a finished and working example that I prepare before the presentation. You can create it for yourself by putting this file in place of the one <tt>grokproject</tt> created:</p>
<ul>
<li><a href="http://rhodesmill.org/brandon/static/2007-11/app.py">app.py</a></li>
</ul>
<p>and then putting these four files in <tt>app_templates</tt>:</p>
<ul>
<li><a href="http://rhodesmill.org/brandon/static/2007-11/index.pt">index.pt</a></li>
<li><a href="http://rhodesmill.org/brandon/static/2007-11/contents.pt">contents.pt</a></li>
<li><a href="http://rhodesmill.org/brandon/static/2007-11/battleindex.pt">battleindex.pt</a></li>
<li><a href="http://rhodesmill.org/brandon/static/2007-11/characterindex.pt">characterindex.pt</a></li>
</ul>
<p>The resulting application, though tiny, was probably too complex for my target audience — many eyes, I noticed, glazed over when seeing Zope Page Templates for the first time — but four views is really barely enough to illustrate both that you can have multiple views on the same object (<tt>MyApp</tt> has both an <tt>/index</tt> and a <tt>/contents</tt>), and that several objects can have views with the same name (<tt>Battle</tt> and <tt>Character</tt> have different <tt>/index</tt> views). The example also shows clearly that if you declare four views, you need to write four page templates to go with them.</p>
<p>I emphasize for the audience that most of the 56 lines of <tt>app.py</tt> are concerned with creating the violence-themed object model; only the fifteen lines at the bottom are interesting Grok code, creating four very slender views. This is where I point out “convention over configuration” at work: all of the page templates get discovered without having to be named, and <tt>grok.name()</tt> only has to be employed when we want the view&#8217;s URL name to differ from the name of the class.</p>
<p>After demonstrating that the application does, in fact, work, we return to the slides and start examining the relationship between page templates and their views.</p>
<h2><a id="moving-to-a-push-model" name="moving-to-a-push-model">Moving to a “push” model</a></h2>
<p>In the presentation I distinguish between “muscular views” and “muscular templates”; perhaps I should have used instead the more conventional idea of templates that “pull” data versus those to which data are “pushed.”</p>
<p>When I reach the slide that reminds me to, “show them your anemic View classes,” I return to my editor and point out that, in the example application, each view has almost no purpose but to associate a particular object class with a particular page template. There is very little information in a declaration like:</p>
<pre>
class CharacterIndex(grok.View):
    grok.context(Character)
    grok.name('index')
</pre>
<p>Whereas there is plenty going on in a template like <tt>characterindex.pt</tt>; every TAL reference it makes is either to the raw <tt>context</tt> object itself, or an object it reaches through the context! Take a look:</p>
<pre>
&lt;h1&gt;The Character:
&lt;span tal:content=&quot;context/name&quot;&gt;Name&lt;/span&gt;&lt;/h1&gt;
This character fought in several battles.
&lt;ul&gt;
  &lt;li tal:repeat=&quot;battle context/battles&quot;&gt;
    &lt;a tal:attributes=&quot;href python: view.url(battle)&quot;
       tal:content=&quot;battle/name&quot;&gt;Name&lt;/a&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>The slides then continue, pointing out that this makes for very quick coding at the cost of several disadvantages. When the fourth and final intermission arrives (“go make your CharacterIndex View more muscular”), I return to the window where my editor has <tt>app.py</tt> open and rewrite the <tt>CharacterIndex</tt> to look more like this:</p>
<pre>
class CharacterIndex(grok.View):
    grok.context(Character)
    grok.name('index')
    def namespace(self):
        return {
            'character_name': self.context.name,
            'battles': [
                { 'name': battle.name,
                   'url': self.url(battle) }
                for battle in self.context.battles
                ],
            }
</pre>
<p>Note what this does: it takes all of the work that the page template was doing in order to fetch the character&#8217;s name, and the names and URLs of the battles in which the character fought, and performs that access in pure Python and in exactly once place. The values in the dictionary that is being passed — <tt>character_name</tt> and <tt>battle_info</tt> — are, if you will examine them carefully, composed of nothing but primitive Python types! They consist solely of lists and dictionaries containing strings. They contain no objects for the template to browse at its leisure; instead, every bit of pertinent data in our objects is reduced to harmless data structures which cannot be used to affect the original objects in any way. This means that the <tt>characterindex.pt</tt> template can be rewritten both more safely, and also more simply:</p>
<pre>
&lt;html&gt;&lt;body&gt;
  &lt;h1&gt;The Character:
  &lt;span tal:content=&quot;character_name&quot;&gt;Name&lt;/span&gt;&lt;/h1&gt;
  This character fought in several battles.
  &lt;ul&gt;
    &lt;li tal:repeat=&quot;battle battles&quot;&gt;
      &lt;a tal:attributes=&quot;href battle/url&quot;
         tal:content=&quot;battle/name&quot;&gt;Name&lt;/a&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a href=&quot;index&quot;&gt;Return home&lt;/a&gt;
&lt;/body&gt;&lt;/html&gt;
</pre>
<p>And after showing the audience that the rewritten view and the rewritten page template work together, I return to my slides and — finally! — conclude my presentation.</p>
<p>The presentation seemed to weigh in at around forty minutes. Next time, I think I will tackle fewer concepts at once. But I do like making lots of use of the picture of the cave man, and his club.</p>
]]></content:encoded>
			<wfw:commentRss>http://rhodesmill.org/brandon/2007/my-november-grok-presentation/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PyEphem available for Windows!</title>
		<link>http://rhodesmill.org/brandon/2007/pyephem-available-for-windows/</link>
		<comments>http://rhodesmill.org/brandon/2007/pyephem-available-for-windows/#comments</comments>
		<pubDate>Fri, 09 Nov 2007 16:10:25 +0000</pubDate>
		<dc:creator>Brandon Craig Rhodes</dc:creator>
		
		<category><![CDATA[Computing]]></category>

		<category><![CDATA[PyEphem]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://rhodesmill.org/brandon/2007/pyephem-available-for-windows/</guid>
		<description><![CDATA[  Over the years I have received many requests from frustrated Windows users, asking for a Windows-native version of my PyEphem astronomy library for Python. For most Windows users, an attempt to build the extension ends abruptly with the terrible and famous message:
error: Python was built with version 7.1 of Visual Studio, and extensions need [...] ]]></description>
			<content:encoded><![CDATA[<p> Over the years I have received many requests from frustrated Windows users, asking for a Windows-native version of my <a href="http://rhodesmill.org/pyephem/">PyEphem</a> astronomy library for Python. For most Windows users, an attempt to build the extension ends abruptly with the terrible and famous message:</p>
<blockquote><p><tt>error: Python was built with version 7.1 of Visual Studio, and extensions need to be built with the same version of the compiler, but it isn&#8217;t installed.</tt></p></blockquote>
<p>And, as I myself do not have Visual Studio on the small Windows machine that I deign to own for the sake of my photo printer, I have never been able to offer my users much help. But earlier this year, a helpful PyEphem user named Jeff Kowalczyk emailed me a link to Philip von Weitershausen&#8217;s post <a href="http://www.z3lab.org/sections/blogs/philipp-weitershausen/2007_07_26_cheap-binary-windows">“Cheap binary Windows eggs”</a>, which describes a method for building Python extensions using a freely available compiler.</p>
<p><span id="more-7"></span></p>
<p>Aside from the difficulty that the Python setuptools ignored the <tt>pydistutils.cfg</tt> file he recommended, making it necessary for me to name the compiler on the command line, his instructions produced a PyEphem windows egg with only a few steps:</p>
<ul>
<li>I installed <a href="http://www.python.org/download/windows/">Python for Windows</a>.</li>
<li>I installed the <a href="http://cheeseshop.python.org/pypi/setuptools/">setuptools package</a> using its Windows <tt class="docutils literal"><span class="pre">.exe</span></tt> installer (scroll down the page to find it).</li>
<li>I installed the <a href="http://www.mingw.org/">MinGW compiler</a>.</li>
<li>I installed <a href="http://gnuwin32.sourceforge.net/packages/libarchive.htm">LibArchive for Windows</a>.</li>
<li>I added to my Windows <tt class="docutils literal"><span class="pre">Path</span></tt>:
<pre>C:\Python25;C:\MingW\bin;C:\Program Files\GnuWin32\bin</pre>
</li>
<li>I downloaded the <a href="http://rhodesmill.org/pyephem/">PyEphem</a> source archive.</li>
<li>I brought up a command window and ran:
<pre>
C:\dev&gt; bsdtar -xf pyephem-3.7.2.1.tar.gz
C:\dev&gt; cd pyephem-3.7.2.1
C:\dev\pyephem-3.7.2.1&gt; python setup.py build --compiler=mingw32
C:\dev\pyephem-3.7.2.1&gt; python setup.py bdist_egg
</pre>
</li>
<li>I uploaded the egg in the <tt>dist</tt> directory to the Cheese Shop.</li>
</ul>
<p>Windows users will now find my Windows binary eggs on the <a href="http://pypi.python.org/pypi/pyephem/">Cheese Shop PyEphem entry</a>!</p>
<p>Always keep in mind that behind a small triumph like this one for a Free Software developer like myself stands a great mountain-mass of work by hundreds of others in the community. In this case one helpful user lead to one informative blog post which lead to a solid and available tool&nbsp;— MinGW&nbsp;— that is a descendant of the GCC compiler Richard Stallman himself started writing over twenty years ago! All of which allowed the delivery, to a new (and closed) platform, of my Python interface to <a href="http://www.clearskyinstitute.com/xephem/index.html">astronomy routines</a> which <a href="http://www.clearskyinstitute.com/resumes/ecdowney/resume.html">Elwood Charles Downey</a> has been maintaining for more than a quarter-century.</p>
]]></content:encoded>
			<wfw:commentRss>http://rhodesmill.org/brandon/2007/pyephem-available-for-windows/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Check!</title>
		<link>http://rhodesmill.org/brandon/2007/facebook-chess/</link>
		<comments>http://rhodesmill.org/brandon/2007/facebook-chess/#comments</comments>
		<pubDate>Fri, 02 Nov 2007 04:46:20 +0000</pubDate>
		<dc:creator>Brandon Craig Rhodes</dc:creator>
		
		<category><![CDATA[Web Notes]]></category>

		<guid isPermaLink="false">http://rhodesmill.org/blog/2007/facebook-chess/</guid>
		<description><![CDATA[  I treated my Facebook account as little more than a curiosity, browsing occasionally for friends of my youth, until discovering the Chess Application!
Online chess relieves the game of two horrors for me, of which I had not even been aware until I noticed them during this first online game because of their absence: the [...] ]]></description>
			<content:encoded><![CDATA[<p> I treated my Facebook account as little more than a curiosity, browsing occasionally for friends of my youth, until discovering the <a href="http://apps.facebook.com/chessfb/">Chess Application</a>!</p>
<p>Online chess relieves the game of two horrors for me, of which I had not even been aware until I noticed them during this first online game because of their absence: the horror of a waiting opponent, and the curse of having to wait for them in turn!  It turns out that, for a novice like myself who can take upwards of a half-hour to even begin to appreciate the complexity of a given position, to play a live game is only to be rushed through a series of bad decisions.  But now, over morning coffee, I can ponder the board for as long as I wish, and can therefore begin — just begin — to glimpse the beauty of the complex possibilies that each move offers.  And then, my move complete, I can go about my day without being fixed, inactive, in a chair while my opponent weighs his decision.</p>
<p>I will have to thank <a href="http://git.facebook.com/profile.php?id=12822177">Ilan</a> for telling me about this — maybe even by playing him in person sometime, like he <i>originally</i> asked!</p>
]]></content:encoded>
			<wfw:commentRss>http://rhodesmill.org/brandon/2007/facebook-chess/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
