<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3029438816324283001</id><updated>2012-02-16T10:36:08.453Z</updated><category term='linux'/><category term='xml'/><category term='javascript'/><category term='pylibftdi'/><category term='books'/><category term='programming'/><category term='synth'/><category term='mandelbrot'/><category term='parenting'/><category term='games'/><category term='pogoplug'/><category term='midi'/><category term='website'/><category term='http'/><category term='bash'/><category term='eeepc'/><category term='c'/><category term='microchip'/><category term='python'/><category term='twitter'/><category term='mac'/><category term='canvas'/><category term='pic'/><category term='testing'/><category term='automation'/><category term='ftdi'/><category term='c++'/><category term='dspic'/><category term='stl'/><title type='text'>Coded Structure</title><subtitle type='html'>Thoughts on programming, systems, structure and Truth...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>29</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-6217466536839436112</id><published>2012-01-29T00:37:00.000Z</published><updated>2012-01-29T00:41:43.356Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><title type='text'>Linux Laziness (or: editing text files made twice as easy)</title><content type='html'>&lt;p&gt;It's been far too long since I wrote anything on this blog, so I'm easing myself back into it with what I've found to be a nice shortcut over the last few months. It uses one of my favourite POSIX tricks - symlinks to executables, together with behaviour based on the original symlink's name - the 'zeroth' argument to the executable.&lt;/p&gt;&lt;p&gt;As someone who identifies fully - and then some - with this xkcd comic: &lt;a target="_blank" href="http://xkcd.com/974/"&gt;The General Problem&lt;/a&gt;, I would really rather not have to type commands which require options. I like aliases, preferably one or two characters long, and I would prefer to write one long word than a short word with an option or two. The mental effort of typing a single word to do a specific action is exactly what I want.&lt;/p&gt;&lt;p&gt;Which leads me to the problem. Text files are great. I am (or was) regularly opening editors, making notes, and saving them somewhere random. The problem is that, like standards, there quickly become too many of them. Which one to use? How to keep track of them? The problem is that the action 'edit my notes file' has to be split into two: a 'verb' (edit), and an 'object' (that particular file). Now you might think I'm irredeemably lazy, but that's twice as many things to remember - or type - as I'd like. I could just add an alias to .bash_aliases, but that's no fun, and while I could have a bunch of them, if I wanted to do anything more complex, I'd be repeating myself too much. Laziness, remember? Got to solve 'The General Problem', and then never have to worry about the specifics ever again :-)&lt;/p&gt;&lt;p&gt;One of my fun projects many moons ago was about adding '&lt;code&gt;--xml&lt;/code&gt;' options to ordinary posix commands (&lt;a href="http://blog.codedstructure.net/2011/04/xmlcmd-adding-xml-option-one-command-at.html"&gt;xmlcmd&lt;/a&gt; - because XML may have serious backing in the enterprise, but needs all the help it can get to make this 'the year of XML on the Linux desktop'), and in it I create symlinks from &lt;code&gt;~/bin/&lt;em&gt;name-of-posix-command&lt;/em&gt;&lt;/code&gt; to a Python script which then looks up and runs the original command (using the Python &lt;a href=" http://pypi.python.org/pypi/which/1.1.0"&gt;which&lt;/a&gt; package), before encoding that command's output into XML to be returned to the user. So basically:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Symlinks in a path early in $PATH to a common script&lt;/li&gt;&lt;li&gt;Use of &lt;code&gt;argv[0]&lt;/code&gt; / &lt;code&gt;$0&lt;/code&gt; in that script to know from which command it was called, and act accordingly.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;(And &lt;code&gt;which ls&lt;/code&gt; on all my computers still shows $HOME/bin/ls, even though I hardly ever use the &lt;code&gt;--xml&lt;/code&gt; option - isn't transparency nice?)&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Applying these techniques to the rather simpler - yet more useful - task of editing files, and jumping to the punchline, I have this in &lt;code&gt;~/bin/editfile&lt;/code&gt;:&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/bin/bash&lt;br /&gt;EDITFILE_DIR=~/Dropbox/editfile&lt;br /&gt;mkdir -p $EDITFILE_DIR  # ensure this exists&lt;br /&gt;TARGET_PATH=$EDITFILE_DIR/$(basename $0).txt&lt;br /&gt;&lt;br /&gt;case $1 in&lt;br /&gt;    '-a')&lt;br /&gt;        # append command arguments to file and exit&lt;br /&gt;        shift  # don't include the '-a'&lt;br /&gt;        echo "$*" &gt;&gt; $TARGET_PATH&lt;br /&gt;        ;;&lt;br /&gt;    '-l')&lt;br /&gt;        # list file and exit&lt;br /&gt;        cat $TARGET_PATH&lt;br /&gt;        ;;&lt;br /&gt;    *)&lt;br /&gt;        # Determine editor to use&lt;br /&gt;        if [[ -n "${EDITOR}" ]] ; then&lt;br /&gt;            EDIT=$EDITOR&lt;br /&gt;        elif $(which gedit) ; then&lt;br /&gt;            EDIT="gedit -b"  # default fallback if present&lt;br /&gt;        else&lt;br /&gt;            EDIT="vim"       # fallback if no gedit there&lt;br /&gt;        fi&lt;br /&gt;&lt;br /&gt;        # Edit it...&lt;br /&gt;        $EDIT $TARGET_PATH&lt;br /&gt;        ;;&lt;br /&gt;esac&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And this:&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;$ ls -l ~/bin&lt;br /&gt;-rwxr-xr-x  1 ben  staff    714 28 Jan 23:55 editfile&lt;br /&gt;lrwxr-xr-x  1 ben  staff      8 19 Dec 22:13 notes -&gt; editfile&lt;br /&gt;lrwxr-xr-x  1 ben  staff      8 19 Dec 22:50 report -&gt; editfile&lt;br /&gt;lrwxr-xr-x  1 ben  staff      8 19 Dec 22:50 todo -&gt; editfile&lt;br /&gt;lrwxr-xr-x  1 ben  staff      8 19 Dec 22:50 track -&gt; editfile&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This has been developed from the much simpler starting point which looked something like this:&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;gedit ~/$(basename $0)&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The result of this is that I can type '&lt;code&gt;notes&lt;/code&gt;' from anywhere on my system, and up will pop my editor with the notes file, which happens to be something on Dropbox, and therefore available on all my computers. I can add as many extra files for different purposes as I like, and they all act in the same way. The files themselves aren't tied into any particular system, and even have helpful '.txt' extensions on the 'actual' files. And since there's a single script behind all of these, they all inherit the 'extras', such as '&lt;code&gt;-l&lt;/code&gt;' to list the file, and '&lt;code&gt;-a&lt;/code&gt;' to add a line, and I can add extra features and commands, and only have to do it once.&lt;/p&gt;&lt;p&gt;But the main point of all of this is that I've turned a verb + object into a more specific verb, and as long as the first verb is something like 'edit this text file', then I've solved The General Problem too. It might have taken a while longer than &lt;code&gt;'alias notes="vim ~/Dropbox/editfile/notes.txt"'&lt;/code&gt;, but that wouldn't have been half as fun. And if you haven't looked at the &lt;a target="_blank" href="http://xkcd.com/974/"&gt;xkcd comic&lt;/a&gt; I linked to earlier, you should now... :-)&lt;/p&gt;&lt;p&gt;I feel the need for a '&lt;code&gt;today&lt;/code&gt;' action, and while I'm at it I should add a todo:&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;$ (cd ~/bin; ln -s editfile today)&lt;br /&gt;$ todo -a blog post about recently released pylibftdi 0.9&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-6217466536839436112?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/6217466536839436112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2012/01/linux-laziness-or-editing-text-files.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/6217466536839436112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/6217466536839436112'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2012/01/linux-laziness-or-editing-text-files.html' title='Linux Laziness (or: editing text files made twice as easy)'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-7293649263343900895</id><published>2011-07-18T23:35:00.002+01:00</published><updated>2011-07-18T23:40:12.282+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='automation'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>HTTP or it doesn't exist.</title><content type='html'>&lt;p&gt;This is my 'or it doesn't exist' blog post&lt;a href="#bpb-hode1"&gt;[1]&lt;/a&gt;&lt;a href="#bpb-hode2"&gt;[2]&lt;/a&gt;&lt;a href="#bpb-hode3"&gt;[3]&lt;/a&gt;. I think everyone should have one ;-)&lt;/p&gt;&lt;p&gt;A big chunk of my life is processing electronic information. Since I would like it to be a (slightly) smaller chunk of my life, I want to automate as much as possible. Now ideally, I don't want a massive disconnect between what I have to do as a human processor of information and what I need to tell a computer to do to do that job done without my help. Because it's easier that way.&lt;/p&gt;&lt;p&gt;So when I hear that the information I need to process is in some spreadsheet or other on a Windows share, it makes me a little sad. When I hear that it is available via a sensible REST interface in a sensible format, my heart leaps for joy just a little.&lt;/p&gt;&lt;p&gt;With something like Python's standard library (and third-party package) support for HTTP (&lt;a href="http://docs.python-requests.org/en/latest/index.html"&gt;requests&lt;/a&gt;), XML (&lt;a href="http://docs.python.org/library/xml.etree.elementtree.html"&gt;ElementTree&lt;/a&gt;) and &lt;a href="http://docs.python.org/library/json.html"&gt;JSON&lt;/a&gt;, I should be able to get my computer to do most of the manual data processing tasks which involve 'documents' of some form or other.&lt;/p&gt;&lt;p&gt;In a previous job I worked at convincing anyone who would listen that 'XML over HTTP' was the best thing since sliced bread. With appropriate XSLT and CSS links, the same data source (i.e. URI) could be happily consumed by both man and machine. Admittedly most of the information was highly structured data - wire protocols and the like, but it still needed to be understandable by real people and real programs.&lt;/p&gt;&lt;p&gt;I'm not an XML expert, but I think I 'get' it. I never understood why it needed so much baggage though, and can't say I'm sad that the whole web services thing seems to be quietly drifting into the background - though maybe it was always trying to.&lt;/p&gt;&lt;p&gt;A lot changes in web technology in a short time, and XML is no longer 'cool', so I won't be quite as passionate about 'XML over HTTP' as I once was. For short fragments it is far more verbose than JSON, though I'd argue that for longer documents, XML's added expressiveness makes the verbosity worth it. Maybe it was ever thus, but whenever two technologies have even the slightest overlap, there seems to be a territorial defensiveness which makes the thought of using both in one project seem somewhat radical. So while I've used JSON much more than XML in the last couple of years, I've not turned against it. If done right (Apple, what were you thinking with plist files!?) - it is great. Compared to JSON-like representations, the ability to have attributes for every node in the tree is a whole new dimension in making a data source more awesome or usable (or terribly broken and rubbish). I've seen too many XML documents where either everything is an attribute or nothing is, but it's not exactly rocket science.&lt;/p&gt;&lt;p&gt;Things I liked about XML:&lt;dl&gt;&lt;dt&gt;Simplicity&lt;/dt&gt;&lt;dd&gt;I like to think I could write a parser for XML 1.0 without too much effort. If it's not well formed, stop. Except for trivial whitespace normalisation etc, there is a one-to-one mapping of structure to serialisation. Compare that with the mess of HTML parsers. While HTML5 might now specify how errored documents should be parsed (i.e. what the resulting DOM should be), I suspect that a HTML5 -&gt; DOM parser is a far more complex beast.&lt;/dd&gt;&lt;dt&gt;Names! Sensible Names!&lt;/dt&gt;&lt;dd&gt;Because HTML is limited in its domain, it has a fixed (though growing thanks to the living standard&lt;a href="#bpb-hode4"&gt;[4]&lt;/a&gt; which is HTML) set of tags. When another domain is imposed on top of that, the &lt;code&gt;class&lt;/code&gt; attribute tends to get pressed into service in a ugly and overloaded way. By allowing top-level tags to be domain-specific, we can make the document abstraction more 'square'&lt;a href="#bpb-hode5"&gt;[5]&lt;/a&gt;.&lt;/dd&gt;&lt;dt&gt;Attributes&lt;/dt&gt;&lt;dd&gt;Attributes allow metadata to be attached to document nodes. Just as a lower-level language is fully capable of creating a solution to any given problem, having 'zero mental cost' abstractions (such as the data structures provided by high-level languages) enables new ways of thinking about problems. In the same way, having attributes on data nodes doesn't give us anything we couldn't implement without them, but it provides another abstraction which I've found invaluable and missed when using or creating JSON data sources.&lt;/dd&gt;&lt;/dl&gt;&lt;p&gt;What does make me slightly(!) sad though is the practical demise of XHTML and any priority that browsers might give to processing XML. There is now a many-to-one mapping of markup to DOM, and pre HTML5 (and still in practice for the foreseeable future considering browser idiosyncrasies and bugs) - a many-to-many mapping. It wouldn't surprise me if XSLT transform support eventually disappeared from browsers.&lt;/p&gt;&lt;p&gt;Maybe there's a bit of elitism here - if you can't code well-formed markup and some decent XSLT (preferably with lots of convoluted functional programming thrown in) - then frankly 'get of my lawn!'. I love the new features in HTML(5), but part of me wishes that there was an implied background 'X' unquestionably preceding that, for all things. The success of the web is that it broke out of that mould. But in doing that it has compromised the formalisms which machines demand and require. Is the dream of the machine-readable semantic web getting further away - even as cool and accessible (and standards compliant - at last) web content finally looks like it might possibly start to achieve its goal? Is it too much (and too late) to dream of 'data' (rather than ramblings like this one) being available in the same form for both the human viewer and the computer automaton?&lt;/p&gt;&lt;p&gt;I'm prepared to be realistic and accept where we've come to. It's not all bad, and the speed with which technology is changing has never been faster. It's an exciting time to wield electronic information, and we've got the tools to move forward from inaccessible files stored on closed, disconnected systems. So where I used to say 'XML over HTTP', my new mantra shall now be 'HTTP or it doesn't exist'. At least for a while.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a name="bpb-hode1"&gt;&lt;a href="http://lukeplant.me.uk/blog/posts/docs-or-it-doesnt-exist/"&gt;[1] http://lukeplant.me.uk/blog/posts/docs-or-it-doesnt-exist/&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="bpb-hode2"&gt;&lt;a href="http://blog.wearpants.org/elitism-and-the-importance-of-pypi"&gt;[2] http://blog.wearpants.org/elitism-and-the-importance-of-pypi&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="bpb-hode3"&gt;&lt;a href="http://epc.buffalo.edu/authors/goldsmith/if_it_doesnt_exist.html"&gt;[3] http://epc.buffalo.edu/authors/goldsmith/if_it_doesnt_exist.html&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="bpb-hode4"&gt;&lt;a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/"&gt;[4] http://www.whatwg.org/specs/web-apps/current-work/multipage/&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="bpb-hode5"&gt;&lt;a href="http://codedstructure.net/articles/square_abstractions.html"&gt;[5] http://codedstructure.net/articles/square_abstractions.html&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-7293649263343900895?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/7293649263343900895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2011/07/http-or-it-doesnt-exist.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/7293649263343900895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/7293649263343900895'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2011/07/http-or-it-doesnt-exist.html' title='HTTP or it doesn&apos;t exist.'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-7083427061588539941</id><published>2011-06-05T22:51:00.000+01:00</published><updated>2011-06-05T22:51:51.726+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pogoplug'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='pylibftdi'/><title type='text'>Bugs: they hide where you're not looking</title><content type='html'>&lt;p&gt;I bought a new &lt;a href="http://www.pogoplug.com/"&gt;Pogoplug&lt;/a&gt; over the weekend (only £50 new at PC World), and after being genuinely impressed by the Pogoplug software, decided it was far too easy and put &lt;a href="http://plugapps.com/"&gt;PlugApps&lt;/a&gt; Linux on it. These 'plug' type devices are fairly amazing - cheap, very low power (measured mine at just under 4 watts, with only a single USB flash stick), but with a decent 1.2GHz ARM processor. I'm already thinking my &lt;em&gt;next&lt;/em&gt; computer might be another 'plug.&lt;/p&gt;&lt;p&gt;After hacking for I while (&lt;em&gt;why won't my printer work?&lt;/em&gt;), I decided to check whether my &lt;a href="http://pypi.python.org/pypi/pylibftdi"&gt;pylibftdi&lt;/a&gt; package worked on it. To my shock, a quick '&lt;code&gt;pacman -S libftdi; pip install pylibftdi&lt;/code&gt;', installed fine, and I could open a device connection to a FTDI device! But then things got worse. Trying to run &lt;code&gt;examples/lcd.py&lt;/code&gt; failed with an exception in &lt;code&gt;BitBangDevice&lt;/code&gt;, and I quickly realised that the API changes I'd done in 0.8 to make device access more 'file-like' had broken things in &lt;code&gt;BitBangDriver&lt;/code&gt;. I was slightly sad that I'd released something where the &lt;em&gt;examples&lt;/em&gt; didn't even work, and part of the whole reason the package might be useful to people (the abstraction over bit-bang device operation) was broken.&lt;/p&gt;&lt;p&gt;&lt;code&gt;pylibftdi&lt;/code&gt; is fairly simple, and basically consists of &lt;code&gt;Driver&lt;/code&gt;, &lt;code&gt;Device&lt;/code&gt;, and &lt;code&gt;BitBangDevice&lt;/code&gt; classes. Most of the interesting is in the &lt;code&gt;Device&lt;/code&gt; class - so this is where I started when I finally got round to adding some tests for the 0.8 release. Having achieved reasonable coverage (though shamefully less than the 100% Uncle Bob demands), I considered my initial testing 'done'. I knew there was more to add later, and had (and still have) full intentions to 'get around to it'.&lt;/p&gt;&lt;div style="clear:both;border:1px solid transparent"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-nxvYjfwNQP8/Tevyaa4iBeI/AAAAAAAAACk/BkA-hUZYstI/s1600/pogo_pylibftdi.jpg" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="320" width="302" src="http://1.bp.blogspot.com/-nxvYjfwNQP8/Tevyaa4iBeI/AAAAAAAAACk/BkA-hUZYstI/s320/pogo_pylibftdi.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;What I failed to anticipate has the unintended side-effect of writing tests. In the same way teachers might teach how to pass an exam rather than the depth and breadth of a subject, once tests exist, the purpose can simply be to pass them. Old manual acceptance tests get ignored as the 'old way' of doing things. Ideally of course this isn't a problem, because full test cases exist for every feature and code-path in the system, but that was very far from the case here. So somehow, my standard acceptance test (do the example programs still work) got omitted, in preference for 'there are tests now, so it must be better! And the tests pass!'&lt;/p&gt;&lt;/div&gt;&lt;p&gt;So beware - a little testing can be a dangerous thing. The bugs hide where you're not looking for them. This is great motivation for achieving full test coverage, for automating acceptance testing (as well as unit / component level testing) so far as possible, and for being humble when it comes to writing tests. My motivations for writing them in the first place were two-fold: the feeling it was 'what I should do', and the idea that at some future point when I added or refactored things later I could be confident I hadn't broken things. I had no thought that the software was already broken; that I &lt;em&gt;needed&lt;/em&gt; tests.&lt;/p&gt;&lt;p&gt;Anyway, &lt;a href="http://pypi.python.org/pypi/pylibftdi"&gt;pylibftdi&lt;/a&gt; 0.8.1 is now out, with trivial but important fixes and lots more tests.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-7083427061588539941?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/7083427061588539941/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2011/06/bugs-they-hide-where-youre-not-looking.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/7083427061588539941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/7083427061588539941'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2011/06/bugs-they-hide-where-youre-not-looking.html' title='Bugs: they hide where you&apos;re not looking'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-nxvYjfwNQP8/Tevyaa4iBeI/AAAAAAAAACk/BkA-hUZYstI/s72-c/pogo_pylibftdi.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-5000472392559102641</id><published>2011-05-07T22:57:00.001+01:00</published><updated>2011-05-07T23:01:57.415+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ftdi'/><category scheme='http://www.blogger.com/atom/ns#' term='pylibftdi'/><title type='text'>pylibftdi 0.8 released; testing, coverage, and mocking</title><content type='html'>&lt;p&gt;&lt;a href="http://pypi.python.org/pypi/pylibftdi"&gt;pylibftdi&lt;/a&gt; is a file-like wrapper to &lt;a href="http://www.ftdichip.com/Products/Modules/DevelopmentModules.htm"&gt;FTDI USB devices&lt;/a&gt; such as the UB232R (a USB&amp;lt;-&amp;gt;serial converter) and the UM245R (8 bit parallel I/O).&lt;/p&gt;&lt;p&gt;No big changes for the 0.8 release, but a couple of new things:&lt;ul&gt;&lt;li&gt;ability to specify the device identifier in the &lt;code&gt;Device(&lt;em&gt;[device_id]&lt;/em&gt;)&lt;/code&gt; constructor as either a serial number (as previously), or a device description. So can now specify &lt;code&gt;Device('UB232R')&lt;/code&gt;, and the first attached UB232R device will be opened. The code initially tries to open by serial number, and if that fails will try to open by description, which I'm fairly confident will be useful rather than annoying :-)&lt;/li&gt;&lt;li&gt;more file-like API functions (&lt;code&gt;flush&lt;/code&gt;, &lt;code&gt;readline()&lt;/code&gt;/&lt;code&gt;readlines()&lt;/code&gt;/&lt;code&gt;writelines()&lt;/code&gt;, iterating over lines). These probably only make sense for text over serial lines, but that's a use-case worth supporting, considering pylibftdi already has unicode support.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;As well as that, I finally got round to adding some tests, and discovered something wonderful: checking &lt;strong&gt;test coverage&lt;/strong&gt; isn't just practical icing on the cake to make sure things are tested well, but is a powerful and effective &lt;strong&gt;motivation&lt;/strong&gt; for writing tests. I'm using &lt;a href="http://nedbatchelder.com/code/coverage/"&gt;coverage&lt;/a&gt;, and have to say it's one of those things I wish I had got round to sooner.&lt;/p&gt;&lt;p&gt;Speaking of which, at some point I'll probably end up saying the same about &lt;a href="http://www.voidspace.org.uk/python/mock/"&gt;Mock&lt;/a&gt;, which I've read around and know I should probably start using, but it's just so easy in Python to knock up something like this:&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;fn_log = []&lt;br /&gt;class SimpleMock(object):&lt;br /&gt;    """&lt;br /&gt;    This is a simple mock plugin for fdll which logs any calls&lt;br /&gt;    made through it to fn_log, which is currently rather ugly&lt;br /&gt;    global state.&lt;br /&gt;    """&lt;br /&gt;    def __init__(self, name="&amp;lt;base&amp;gt;"):&lt;br /&gt;        self.__name = name&lt;br /&gt;&lt;br /&gt;    def __getattr__(self, key):&lt;br /&gt;        # This makes me smile :)&lt;br /&gt;        return self.__dict__.get(key, SimpleMock(key))&lt;br /&gt;&lt;br /&gt;    def __call__(self, *o, **k):&lt;br /&gt;        fn_log.append(self.__name)&lt;br /&gt;        # most fdll calls return 0 for success&lt;br /&gt;        return 0&lt;br /&gt;&lt;br /&gt;def get_calls(fn):&lt;br /&gt;    "return the called function names which the fdll mock object made"&lt;br /&gt;    del fn_log[:]&lt;br /&gt;    fn()&lt;br /&gt;    return fn_log&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Sometimes I think Python makes 'clever' things like that too easy, and is perhaps the reason that although in the Python &lt;em&gt;language&lt;/em&gt; there is only-one-way-to-do-it, in the Python ecosystem there is perhaps a tendency to reinvent the wheel over and over again. Because it's easy - and it's fun.&lt;/p&gt;&lt;p&gt;As always code is at &lt;a href="http://bitbucket.org/codedstructure/pylibftdi"&gt;bitbucket&lt;/a&gt;. For the next release (0.9) I'm planning to add more tests and docs (which are rather scarce), as well as one or two of the other things I've got planned (possible D2XX support, or at least some notes on libftdi on Windows, more examples &amp; protocol adapters, maybe even a web interface for 8 bit IO...)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-5000472392559102641?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/5000472392559102641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2011/05/pylibftdi-08-released-testing-coverage.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/5000472392559102641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/5000472392559102641'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2011/05/pylibftdi-08-released-testing-coverage.html' title='pylibftdi 0.8 released; testing, coverage, and mocking'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-8786959295267580281</id><published>2011-04-18T22:56:00.001+01:00</published><updated>2011-05-07T23:08:54.014+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='canvas'/><title type='text'>piefull - a simple javascript &amp; canvas visualisation tool</title><content type='html'>&lt;p&gt;OK, so calling &lt;a href="http://code.codedstructure.net/piefull"&gt;&lt;strong&gt;&lt;code&gt;piefull&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; a visualisation tool is going a bit over the top, but it is a tool, and it does help with visualisation. It does one thing and one thing only - plot pie-charts indicating a single value. And it's even more restricted than that - the value it plots needs to be a percentage value.&lt;/p&gt;&lt;p&gt;The main use cases for this are things like task completion status (project and outliner applications, test coverage, etc) or resource allocation (disk space, CPU usage).&lt;/p&gt;&lt;p&gt;By choosing contrasting colours (these are configurable in &lt;strong&gt;&lt;code&gt;piefull&lt;/code&gt;&lt;/strong&gt;), the the overall outlook can be ascertained by a glance from a distance. By default the charts it generates are fairly small - 24px - which allows them to be used in-line in text, or as entries in tables. The general approach is derived from the sparklines example given in David Flanagan's &lt;a href="http://oreilly.com/catalog/0636920016045"&gt;Canvas Pocket Reference&lt;/a&gt; - replacing some textual data with a pictorial equivalent in the hope(!) it will be more quickly understandable. Of course this approach also lends itself well to graceful degradation, as the data is already there in the document itself.&lt;/p&gt;&lt;p&gt;There are plenty of other pie-chart generators - after all it's a fairly trivial thing to write with HTML5 canvas elements. But most of these tend to be fairly complex, with lots of options. I needed something where a fixed size display could represent a single value clearly, and &lt;strong&gt;&lt;code&gt;piefull&lt;/code&gt;&lt;/strong&gt; is the result.&lt;/p&gt;&lt;script&gt;var piefull={selector:'.piefull',yescol:'#00F',nocol:'#0F0',size:24,PERCENT_RE:/(-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)%?/i,START_ANGLE:(2*Math.PI)*0.75,main:function(selector,size,yescol,nocol){var that=this;if(typeof document.querySelectorAll==='undefined'){return;}var _selector=selector||this.selector;var _piesize=size||this.size;var _yescol=yescol||this.yescol;var _nocol=nocol||this.nocol;var _drawArc=function(ctx,arclen,full){ctx.beginPath();ctx.moveTo(_piesize/2,_piesize/2);ctx.arc(_piesize/2,_piesize/2,_piesize/2,that.START_ANGLE,that.START_ANGLE+arclen,!full);ctx.fillStyle=full?_yescol:_nocol;ctx.fill();ctx.closePath();};var pies=document.querySelectorAll(_selector);for(var i=0;i&lt;pies.length;i++){var pie=pies[i];var valueText=pie.textContent||pie.innerText;var percent_match=that.PERCENT_RE.exec(valueText);if(percent_match!==null){var value=percent_match[0];var arclen=(2*Math.PI)*parseFloat(value)/100;var canvas=document.createElement('canvas');var attr=pie.getAttribute('class');if(attr){canvas.setAttribute('class',attr);}attr=pie.getAttribute('id');if(attr){canvas.setAttribute('id',attr);}pie.parentNode.replaceChild(canvas,pie);canvas.setAttribute('title',valueText);canvas.width=_piesize;canvas.height=_piesize;if(typeof canvas.getContext==='undefined'){canvas=window.G_vmlCanvasManager.initElement(canvas);}var ctx=canvas.getContext('2d');_drawArc(ctx,arclen,true);_drawArc(ctx,arclen,false);}}}};&lt;/script&gt;&lt;script&gt;window.addEventListener('load', (function() { piefull.main("table.piefull td div"); piefull.main(); }));&lt;/script&gt;&lt;style&gt;table.piefull-example td {  padding: 0 5px 0 5px;}&lt;/style&gt;&lt;p&gt;Basically &lt;strong&gt;&lt;code&gt;piefull&lt;/code&gt;&lt;/strong&gt; turns this:&lt;/p&gt;        &lt;table class="piefull-example"&gt;            &lt;tr&gt;                &lt;td&gt;&lt;div&gt;10%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;20%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;33%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;20%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;10%&lt;/div&gt;&lt;/td&gt;            &lt;/tr&gt;            &lt;tr&gt;                &lt;td&gt;&lt;div&gt;18%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;55%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;33%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;23%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;12%&lt;/div&gt;&lt;/td&gt;            &lt;/tr&gt;            &lt;tr&gt;                &lt;td&gt;&lt;div&gt;14%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;35%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;40%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;21%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;11%&lt;/div&gt;&lt;/td&gt;            &lt;/tr&gt;            &lt;tr&gt;                &lt;td&gt;&lt;div&gt;12%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;29%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;14%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;11%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;5%&lt;/div&gt;&lt;/td&gt;            &lt;/tr&gt;            &lt;tr&gt;                &lt;td&gt;&lt;div&gt;12%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;17%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;10%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;9%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;5%&lt;/div&gt;&lt;/td&gt;            &lt;/tr&gt;        &lt;/table&gt;&lt;p&gt;(which looks like this in code:)&lt;/p&gt;&lt;pre class="prettyprint lang-html"&gt;&lt;br /&gt;&amp;lt;table class="piefull"&gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&lt;br /&gt;       &amp;lt;td&amp;gt;&amp;lt;div&amp;gt;10%&amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;       ...&lt;br /&gt;       &amp;lt;td&amp;gt;&amp;lt;div&amp;gt;5%&amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;/table&gt;                 &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;into this:&lt;/p&gt;        &lt;table class="piefull-example piefull"&gt;            &lt;tr&gt;                &lt;td&gt;&lt;div&gt;10%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;20%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;33%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;20%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;10%&lt;/div&gt;&lt;/td&gt;            &lt;/tr&gt;            &lt;tr&gt;                &lt;td&gt;&lt;div&gt;18%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;55%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;33%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;23%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;12%&lt;/div&gt;&lt;/td&gt;            &lt;/tr&gt;            &lt;tr&gt;                &lt;td&gt;&lt;div&gt;14%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;35%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;40%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;21%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;11%&lt;/div&gt;&lt;/td&gt;            &lt;/tr&gt;            &lt;tr&gt;                &lt;td&gt;&lt;div&gt;12%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;29%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;14%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;11%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;5%&lt;/div&gt;&lt;/td&gt;            &lt;/tr&gt;            &lt;tr&gt;                &lt;td&gt;&lt;div&gt;12%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;17%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;10%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;9%&lt;/div&gt;&lt;/td&gt;                &lt;td&gt;&lt;div&gt;5%&lt;/div&gt;&lt;/td&gt;            &lt;/tr&gt;        &lt;/table&gt;&lt;p&gt;by doing this:&lt;/p&gt;&lt;pre class="prettyprint lang-html"&gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;  window.onload = (function() { piefull.main("table.piefull td div"); });&lt;br /&gt;&amp;lt/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;where &lt;code&gt;'table.piefull td div'&lt;/code&gt; is a selector passed to &lt;code&gt;querySelectorAll()&lt;/code&gt; to locate elements which will be replaced by little canvas piecharts. The contents of the selected elements are matched against a regular expression looking for a percentage value to extract (generally speaking, the first number), and the element is replaced with a canvas element displaying that value. The &lt;code&gt;class&lt;/code&gt;es and &lt;code&gt;id&lt;/code&gt; of the original element are preserved in the new element, allowing sensible CSS styling, and the canvas &lt;code&gt;title&lt;/code&gt; takes on the text which it has replaced. As well as the selector, there are a (small) number of other parameters - size, 'yes' and 'no' colours. A value of e.g. 10 will display a 10% pie-segment in the 'yes' colour - the remainder will be the 'no' colour. (Like this: &lt;span class="piefull"&gt;10%&lt;/span&gt;.) These are all optional - even the selector defaults to &lt;code&gt;'.piefull'&lt;/code&gt;, which works great for a small number of spans or divs in some prose:&lt;/p&gt;In other news, at least &lt;span class="piefull"&gt;66%&lt;/span&gt; of statistics are made up. No, wait - it should be a little higher now.&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; If you're viewing this on IE8 or below, this probably makes no sense, as I've not included excanvas here. It is supported for IE8 with &lt;a href="http://code.google.com/p/explorercanvas/"&gt;excanvas&lt;/a&gt; (but not less than IE8). One gotcha with IE is that block-level elements such as canvas don't work inside &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; elements. But you know you want to get a better browser... And why not get one &lt;a href="http://www.mozilla.com/firefox/"&gt;with&lt;/a&gt; &lt;a href="http://www.google.com/chrome"&gt;webgl&lt;/a&gt; &lt;a href="http://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation"&gt;support&lt;/a&gt; while you're at it?&lt;p&gt;The code for &lt;strong&gt;&lt;code&gt;piefull&lt;/code&gt;&lt;/strong&gt; can be found &lt;a href="http://code.codedstructure.net/piefull"&gt;here&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-8786959295267580281?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/8786959295267580281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2011/04/piefull-simple-javascript-canvas.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/8786959295267580281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/8786959295267580281'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2011/04/piefull-simple-javascript-canvas.html' title='piefull - a simple javascript &amp; canvas visualisation tool'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-958670565489417370</id><published>2011-04-06T23:37:00.001+01:00</published><updated>2011-04-06T23:39:45.025+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>xmlcmd: adding an --xml option, one command at a time</title><content type='html'>&lt;p&gt;In my &lt;a href="http://blog.codedstructure.net/2011/03/xpath-is-to-xml-as-regex-is-to-text.html"&gt;last post&lt;/a&gt;, I wrote some thoughts on how using the text based meta-language&lt;a href="#ref_1"&gt;[1]&lt;/a&gt; of regular expressions to filter and manipulate structured data from UNIX commands was not fully exploiting the jigsaw-puzzle approach of 'the unix philosophy'&lt;a href="#ref_2"&gt;[2]&lt;/a&gt;, and that XPath (and by implication XML) provided an alternative where structured data on the command line was concerned.&lt;a href="#ref_3"&gt;[3]&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I also mentioned how great things could be if, like subversion, every POSIX command line tool had an --xml switch which could output XML. (There are many programs with XML output, but the main POSIX ones&lt;a href="#ref_4"&gt;[4]&lt;/a&gt; don't have this as an option)&lt;/p&gt;&lt;h3&gt;Here's one I made earlier&lt;/h3&gt;&lt;p&gt;I was always aware of the danger of overstating the case, but sometimes that can be helpful. Or at least fun. And I'd already started prototyping something which looked fun, dangerous, and potentially useful. This is intended to be illustrative rather than a serious suggestion, but there might be many other cases where the concepts can be used more seriously.&lt;/p&gt;&lt;h3&gt;1. Add a path&lt;/h3&gt;&lt;p&gt;There isn't any magic to what we're doing in adding --xml options, and we're not touching the original programs. We're just using the fact that the PATH in POSIX operating systems contains an &lt;em&gt;ordered list&lt;/em&gt; of entries, and we're simply inserting a 'hook' early on in the path which can catch and redirect certain formats of command, while transparently forwarding others.&lt;/p&gt;&lt;p&gt;I tend to have a ~/bin directory on my path anyway (keeping good care that it is only writable by myself) - so I'm already set, but if not, you'll need a directory which appears first on the PATH.&lt;pre class="prettyprint lang-sh"&gt;&lt;br /&gt;ben$ mkdir -p ~/bin&lt;br /&gt;&lt;/pre&gt;add that path to the start of your login path (e.g. in .bashrc or .bash_profile):&lt;pre class="prettyprint lang-sh"&gt;&lt;br /&gt;export PATH=$HOME/bin:$PATH&lt;br /&gt;&lt;/pre&gt;Once that is done, anything in that directory will be run in preference to anything else. Put an 'ls' file in there something like the following:&lt;pre class="prettyprint"&gt;&lt;br /&gt;#!/usr/bin/env python&lt;br /&gt;print("These are not the files you're looking for")&lt;br /&gt;&lt;/pre&gt;make it executable (&lt;code&gt;chmod +x ~/bin/ls&lt;/code&gt;) and you won't be able to run '&lt;code&gt;ls&lt;/code&gt;' anymore. Except you &lt;em&gt;are&lt;/em&gt; running it, it's just a different &lt;code&gt;ls&lt;/code&gt;, and not doing anything particularly helpful. You can always run the original ls with a fully specified path (or try using &lt;code&gt;$(whereis ls)&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;Two more things make this potentially useful:&lt;ul&gt;&lt;li&gt;Finding the next program on the PATH, which would have been run if something else hadn't sneaked in first&lt;/li&gt;&lt;li&gt;Selectively running either this 'original' program or some different code based on relevant criteria (e.g. existence of &lt;code&gt;--xml&lt;/code&gt; in the command line options)&lt;/li&gt;&lt;/ul&gt;and the following makes things practical:&lt;ul&gt;&lt;li&gt;Making the two things above easily reusable for any command.&lt;/ul&gt;&lt;/p&gt;&lt;h3&gt;2. The magic of args[0]&lt;/h3&gt;&lt;p&gt;Most of the time most programs ignore args[0] - the program's own name. But what if args[0] could be treated as a command line option, just like all the others? What makes this possible is having multiple symbolic links to a single program. args[0] is then the name of the original symlink by which the process was called, so although the same program is ultimately running, it can determine in what way it was called. It can therefore change its own operation. This technique is used in the &lt;a href="http://www.busybox.net/about.html"&gt;busybox&lt;/a&gt; project to implement a generous number of commands in a single executable.&lt;/p&gt;&lt;h3&gt;3. Introducing xmlcmd&lt;/h3&gt;&lt;p&gt;&lt;a href="http://pypi.python.org/pypi/xmlcmd"&gt;xmlcmd&lt;/a&gt; is a Python package which supports this terrible corruption of POSIX as it should always be. The main xmlcmd module code is fairly straightforward, and is shown below. This finds the original program (which would have been run if we weren't first on the path), and then either &lt;code&gt;exec&lt;/code&gt;s that (if no --xml option is provided), or runs some Python code in an dynamically imported Python module (_xyz from the xmlcmd package, where xyz is the 'original' command name) if --xml is present.&lt;/p&gt;&lt;p&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;#!/usr/bin/python&lt;br /&gt;"""&lt;br /&gt;xmlcmd.py - support for adding an --xml option to various commands&lt;br /&gt;&lt;br /&gt;Ben Bass 2011. (Public Domain)&lt;br /&gt;"""&lt;br /&gt;&lt;br /&gt;import sys&lt;br /&gt;import os&lt;br /&gt;import which  # from PyPI 'which' package&lt;br /&gt;&lt;br /&gt;def process_cmd(cmd_name, args, orig_cmd_path):&lt;br /&gt;    """&lt;br /&gt;    import and call the main() function from the module&lt;br /&gt;    xmlcmd._{cmd}&lt;br /&gt;    """&lt;br /&gt;    module = __import__('xmlcmd._%s' % cmd_name,&lt;br /&gt;                        fromlist=['_%s' % cmd_name])&lt;br /&gt;    raise SystemExit(module.main(args, orig_cmd_path))&lt;br /&gt;&lt;br /&gt;def main(args=None):&lt;br /&gt;    """&lt;br /&gt;    run system command from sys.argv[:], where sys.argv[0]&lt;br /&gt;    implies the real command to run (e.g. via symlinks to us)&lt;br /&gt;    """&lt;br /&gt;    if args is None:&lt;br /&gt;        args = sys.argv&lt;br /&gt;&lt;br /&gt;    # args[0] will be a full path - we only want the command name&lt;br /&gt;    cmd_name = os.path.basename(args[0])&lt;br /&gt;    if cmd_name.startswith('xmlcmd'):&lt;br /&gt;        raise SystemExit('xmlcmd should not be called directly')&lt;br /&gt;&lt;br /&gt;    # get the command which would have run if we hadn't sneaked&lt;br /&gt;    # ahead of it in the $PATH&lt;br /&gt;    cmd_path_gen = which.whichgen(cmd_name)&lt;br /&gt;    cmd_path_gen.next()   # skip first match (us)&lt;br /&gt;    orig_cmd_path = cmd_path_gen.next()&lt;br /&gt;&lt;br /&gt;    if '--xml' in args:&lt;br /&gt;        args.remove('--xml')&lt;br /&gt;        # forward to our xmlized version...&lt;br /&gt;        process_cmd(cmd_name, args, orig_cmd_path)&lt;br /&gt;    else:&lt;br /&gt;        # execv *replaces* this process, so it has no idea it&lt;br /&gt;        # wasn't called directly. Total transparency.&lt;br /&gt;        os.execv(orig_cmd_path, args)&lt;br /&gt;&lt;br /&gt;if __name__ == '__main__':&lt;br /&gt;    main()&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;h3&gt;4. The implementations&lt;/h3&gt;&lt;p&gt;The real work is all handled in the _{cmd} modules of course, so admittedly we've really only moved the problem around a bit. But the point of this exercise is about the ease with which we can add these new entry points into existing systems. Nothing slows down in any noticeable way, and it would be easy to extend an entire class of commands, one at a time, by nothing more than adding a Python module and creating a symlink.&lt;/p&gt;&lt;p&gt;For reference, the &lt;code&gt;main()&lt;/code&gt; function from _ls.py looks something like this:&lt;pre class="prettyprint"&gt;&lt;br /&gt;def main(args=None, orig_cmd_path=None):&lt;br /&gt;    """very basic xml directory listing"""&lt;br /&gt;    if len(args) &gt; 1:&lt;br /&gt;        target_dir = args[-1]&lt;br /&gt;        if not os.path.isdir(target_dir):&lt;br /&gt;            raise SystemExit('%s is not a directory' % (target_dir,))&lt;br /&gt;    else:&lt;br /&gt;        target_dir = os.getcwd()&lt;br /&gt;&lt;br /&gt;    root = ET.Element('directory', name=target_dir)&lt;br /&gt;    for fn in os.listdir(target_dir):&lt;br /&gt;        stat = os.stat(os.path.join(target_dir, fn))&lt;br /&gt;        f_el = ET.SubElement(root, 'file', mtime=str(stat.st_mtime))&lt;br /&gt;        ET.SubElement(f_el, 'name').text = fn&lt;br /&gt;        ET.SubElement(f_el, 'size').text = str(stat.st_size)&lt;br /&gt;    ET.ElementTree(root).write(sys.stdout, 'utf-8')&lt;br /&gt;    sys.stdout.write('\n')&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;h3&gt;5. Example&lt;/h3&gt;&lt;p&gt;&lt;pre class="prettyprint lang-sh"&gt;&lt;br /&gt;ben$ sudo pip install which xmlcmd&lt;br /&gt;&lt;/pre&gt;(yup, it's on &lt;a href="http://pypi.python.org/pypi/xmlcmd"&gt;PyPI&lt;/a&gt;) will install the xmlcmd Python package (and the 'which' dependency), and an xmlcmd wrapper script which should end up on the path. With that done, you can now create the magic symlinks:&lt;pre class="prettyprint lang-sh"&gt;&lt;br /&gt;ben$ ln -sf $(which xmlcmd) ~/bin/ls&lt;br /&gt;ben$ ln -sf $(which xmlcmd) ~/bin/ps&lt;br /&gt;&lt;/pre&gt;And now, assuming things are working properly (a quick &lt;code&gt;hash -r&lt;/code&gt;/&lt;code&gt;rehash&lt;/code&gt; can't hurt), you should now be able to do wonderful things like this:&lt;pre class="prettyprint lang-sh"&gt;&lt;br /&gt;ben$ ps --xml aux | xpath '//process/command/text()[../../cpu &gt; 2.5]'&lt;br /&gt;&lt;/pre&gt;which in this case displays the command name of all processes currently taking more than 2.5% of the CPU. Sure the XPath isn't exactly elegant. But the point is that &lt;em&gt;patterns&lt;/em&gt; of this micro-language would be shared between tasks, and manipulating structured data on the UNIX command line would become as easy as text manipulation is now.&lt;/p&gt;&lt;h3&gt;Here's some they made earlier...&lt;/h3&gt;&lt;p&gt;Having said and done all that, a few searches later (for 'posix commands' in this case) brought up &lt;a href="http://www.xmlsh.org"&gt;xmlsh.org&lt;/a&gt;, which seems to do some very similar things.&lt;/p&gt;&lt;p&gt;I also found (via &lt;a href="#ref_2"&gt;[2]&lt;/a&gt;) &lt;a href="http://xmltk.sourceforge.net/"&gt;xmltk&lt;/a&gt;, which at first glance seems to have beaten me to these ideas by about 9 years... :-)&lt;/p&gt;&lt;h4&gt;Notes&lt;/h4&gt;&lt;dl&gt;&lt;dt&gt;&lt;a name="ref_1"&gt;[1]&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;'Regular expressions are notations for describing patterns of text and, in effect, make up a special-purpose language for pattern matching.' Brian Kerninghan, Beautiful Code (ed. Andy Oram &amp; Greg Wilson, O'Reilly Media Inc).&lt;/dd&gt;&lt;dt&gt;&lt;a name="ref_2"&gt;[2]&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;&lt;a href="http://www.catb.org/~esr/writings/taoup/"&gt;The Art of Unix Programming&lt;/a&gt;, Eric S. Raymond. Especially the 'Rule of Composition'; see Chapter 1. (Note this book also praises text of course...)&lt;/dd&gt;&lt;dt&gt;&lt;a name="ref_3"&gt;[3]&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;What a pointlessly long sentence.&lt;/dd&gt;&lt;dt&gt;&lt;a name="ref_4"&gt;[4]&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;POSIX 2 (Commands and Utilities) covers these, e.g. see reference &lt;a href="http://refspecs.freestandards.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic/command.html"&gt;here&lt;/a&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-958670565489417370?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/958670565489417370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2011/04/xmlcmd-adding-xml-option-one-command-at.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/958670565489417370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/958670565489417370'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2011/04/xmlcmd-adding-xml-option-one-command-at.html' title='xmlcmd: adding an --xml option, one command at a time'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-8250522343840503034</id><published>2011-03-21T21:29:00.001Z</published><updated>2011-03-21T21:40:44.572Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>XPath is to XML as regex is to text</title><content type='html'>&lt;p&gt;Anyone who has been a developer for a while gets familiar with &lt;i&gt;regular expressions&lt;/i&gt;. They eat text for breakfast, and spit out desired answers. For all their cryptic terseness, they are at least in part reusable, and are based on only a handful (or two...) of rules. 'regexes' are a domain-specific micro-language for searching and filtering text.&lt;/p&gt;&lt;p&gt;But once we get outside of text, what is there?&lt;/p&gt;&lt;p&gt;With XML, we have XPath. I had one of those light-bulb realisations recently that what regexes are to text, XPath is to XML. And it made me think:&lt;p&gt;&lt;p&gt;&lt;em&gt;Why would I want to use a data substrate which doesn't have such a tool?&lt;/em&gt;&lt;/p&gt;&lt;p&gt;What I mean is this; text has regex. XML has XPath. RDBMS have SQL. Markup language of the day has... oh, it doesn't. Not really, in the sense of a standardised domain-specific micro-language. Regular expressions, XPath and SQL have history and mindshare. They 'work' specifically because they are DSLs, rather than high-level code. (OK, SQL is pushing it further than I'd like here, but it's still a DSL. Just not a micro-sized one.) To me, this is a problem which many 'NoSQL' tools have. I want the features of them, but CouchDB wants me to write map-reduce functions in JavaScript. MongoDB wants me to use a JSON-based query language. There is no commonality; no reuse; no &lt;i&gt;lingua franca&lt;/i&gt; which will let me abstract the processing concepts away from the tools. Perhaps that will come in time for more data-representations (&lt;a href="http://mypatterns.free.fr/"&gt;this&lt;/a&gt; seems to be an attempt for JSON, for example), but there is a significant barrier before such a tool gains widespread acceptance as a common abstraction across an entire data layer.&lt;/p&gt;&lt;h3&gt;Pipelines and Data Processing&lt;/h3&gt;&lt;p&gt;The 'UNIX philosophy' of connecting together a number of single-purpose programs to accomplish larger tasks is one of the keys to its power. These tools can be plugged together in ways which the original creators may never have thought of. Tools such as sed and awk are often employed as regex-based filters to command pipelines. I wish more tools had XML output options, because the tools we use in our pipelines often output &lt;em&gt;structured&lt;/em&gt; data in textual format, often in tabular form. Tables are great for human consumption (provided they are modest in size), but when we start getting empty columns, cells flowing onto multiple lines, and other inconsistencies, it becomes a pain to parse. How great things could be if every tool following subversion's lead and had an --xml option:&lt;/p&gt;&lt;p&gt;&lt;pre&gt;svn diff -r $(svn log --stop-on-copy --xml | xpath -q -e '//log/logentry[last()]/@revision' | cut -d '"' -f 2):HEAD&lt;/pre&gt;(This command does a diff from a branch base to the most recent revision. &amp;nbsp;It still does some basic text processing, because the end result of XPath expressions are still text nodes).&lt;/p&gt;&lt;p&gt;Just imagine if POSIX defined an XML schema for each relevant command, and mandated an --xml option. Life would be so much easier. In many environments, data is structured but we still represent it as text. The pipeline philosophy might be nice, but it isn't exploited to the full when we need to write convoluted awk scripts and inscrutable regular expressions (or worse, Perl ;) ) to try and untangle the structure from the text. Consider something straightforward like the output of 'mount' on a *nix box. On my Mac it looks like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ben$ mount&lt;br /&gt;/dev/disk0s2 on / (hfs, local, journaled)&lt;br /&gt;devfs on /dev (devfs, local, nobrowse)&lt;br /&gt;map -hosts on /net (autofs, nosuid, automounted, nobrowse)&lt;br /&gt;map auto_home on /home (autofs, automounted, nobrowse)&lt;br /&gt;/dev/disk1s1 on /Volumes/My Book (msdos, local, nodev, nosuid, noowners)&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is structured data, but getting the information out of that text blob would not be trivial, and would probably take many minutes of trial and error with regexes to get something reasonable. And the crucial thing is that you couldn't be sure it would always work. Plug a new device in which gets mounted in some new and interesting way, and who is to say that the new output of mount won't suddenly break your hand-crafted regex? That's where XML shines. Adding new information doesn't change anything in the old information. The way to access it doesn't change. Nothing breaks in the face of extension. Compare this to something like CSV, where the insertion of an extra column means all the indices from that column onwards need to change in every producer and consumer of the data.&lt;/p&gt;&lt;h3&gt;XML and the Web&lt;/h3&gt;&lt;p&gt;I'm somewhat saddened that XHTML didn't win outright in the last decade, and that XML on the web never really took off. I spent months at a previous job trying to convince everyone that 'XML-over-HTTP' was the best thing since sliced bread. A single source of data, which could be consumed by man (via XSLT &amp;amp; CSS in the browser) and machine alike. Just think how much energy the likes of Google could save if our web content didn't focus almost entirely on human consumption and discriminate against machines ;-)&lt;/p&gt;&lt;p&gt;One interesting thing which has happened as XML-on-the-web has declined is the increase in use of CSS selectors, first via frameworks such as Sizzle (used in jQuery), and later in the standard &lt;code&gt;querySelectorAll&lt;/code&gt; DOM method. There is clearly a need for these DSL micro-languages, and as the 'CSS selector' DSL shows, they can quickly establish themselves if there is a clear need and sufficient backing from the community. Also apparent is that existing solutions can be usurped - users could do virtually everything CSS selectors could do (and far more besides) with XPath, but that didn't happen. Simplicity won here.  But just because XPath was (arguably) wrong for Web development, doesn't mean it is wrong everywhere, and I contend that there are places where we have over-simplified, forcing regular expressions and text manipulation to (and beyond) breaking point, when XML processing would make things simpler everywhere.&lt;/p&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;p&gt;In terms of practicalities, if I had ever spent too long in the world of Java, I would probably see XML as an unwelcome and persistent pest. But living in the happier climes of Python-ville, I have access to the wonderful ElementTree API, via both &lt;a href="http://docs.python.org/library/xml.etree.elementtree.html"&gt;ElementTree&lt;/a&gt; itself (included in the standard library) and &lt;a href="http://lxml.de/"&gt;lxml&lt;/a&gt;.&lt;/p&gt;Both of these support XPath as well as high-level abstractions of XML documents to and from lists and dictionaries. With ElementTree, XML access from Python is (almost) as easy as JSON access from JavaScript. And with technologies like XPath and XSLT available, I think it's worth it.&lt;/p&gt;&lt;p&gt;As a final thought, I've just had a quick glance through Greg Wilson's excellent &lt;a href="http://www.amazon.co.uk/gp/product/0974514071/ref=as_li_ss_tl?ie=UTF8&amp;tag=codedstruc-21&amp;linkCode=as2&amp;camp=1634&amp;creative=19450&amp;creativeASIN=0974514071"&gt;Data Crunching&lt;/a&gt;&lt;img src="http://www.assoc-amazon.co.uk/e/ir?t=&amp;l=as2&amp;o=2&amp;a=0974514071" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;, which contains chapters on Text, Regular Expressions, Binary data (rather a short ad-hoc chapter), XML, and Relational Databases. Perhaps the 'binary data' chapter is short because there simply aren't many patterns available. There is no language to describe unabstracted data. And perhaps when we consider the data layer we should be using, we should think not only of features and performance, but also the power, expressiveness, and concision of the languages available to reason about the information. Perhaps too often we settle for a lowest common denominator solution (text) when a higher level one might be more powerful, especially if we don't have to give up on the concepts of fine-grained interoperability which micro-DSLs such as XPath give us.&lt;/p&gt;&lt;p&gt;&lt;em&gt;To be continued...&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-8250522343840503034?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/8250522343840503034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2011/03/xpath-is-to-xml-as-regex-is-to-text.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/8250522343840503034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/8250522343840503034'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2011/03/xpath-is-to-xml-as-regex-is-to-text.html' title='XPath is to XML as regex is to text'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-1210455087121295111</id><published>2011-02-20T00:16:00.000Z</published><updated>2011-02-20T00:16:06.693Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Concurrent Queue.get() with timeouts eats CPU</title><content type='html'>&lt;h4&gt;...or how adding a timeout can make your program suffer&lt;/h4&gt;&lt;p&gt;Call me lazy, but I like threads. Or at least I like the programming model they provide. I very rarely use explicit locks, and find the combination of threads and queues a great mental abstraction of parallel processing. Often though, the abstraction is so &lt;a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html"&gt;leaky&lt;/a&gt; that it gets me annoyed. Here is a case in point...&lt;/p&gt;&lt;p&gt;I noticed this problem in a Python process which sits in a loop doing &lt;code&gt;readline()&lt;/code&gt; on a file object and dispatching the incoming lines to different worker threads to do some various asynchronous actions. With no input on the source file, the process was still taking 5% CPU. I would have expected next-to-nothing, since everything should have been blocking.&lt;/p&gt;&lt;p&gt;&lt;code&gt;strace -fc -p $PID&lt;/code&gt; showed that the process was anything but idle though, and after further investigation, I found the culprit.&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;i&gt;Concurrent &lt;code&gt;Queue.get()&lt;/code&gt; with timeouts eats CPU.&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;A test case for this is the following Python (2 &amp; 3) code.  It intentionally doesn't do anything, simply starting &lt;code&gt;&lt;i&gt;WORKER&lt;/i&gt;&lt;/code&gt; threads, each of which performs a blocking &lt;code&gt;Queue.get&lt;/code&gt;. The main thread simply waits for a newline on stdin. I wouldn't expect this to take any significant CPU time - in theory all the threads are blocked - either waiting on stdin input, or on something to be available in the various worker queues (which nothing ever gets sent to).&lt;/p&gt;&lt;pre class="prettyprint lang-py"&gt;&lt;br /&gt;import threading, sys, time&lt;br /&gt;try: import queue&lt;br /&gt;except ImportError: import Queue as queue&lt;br /&gt;&lt;br /&gt;WORKERS = 100&lt;br /&gt;&lt;br /&gt;class Worker(threading.Thread):&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.queue = queue.Queue()&lt;br /&gt;        threading.Thread.__init__(self)&lt;br /&gt;        self.daemon = True&lt;br /&gt;&lt;br /&gt;    def run(self):&lt;br /&gt;        while True:&lt;br /&gt;            next_item = self.queue.get()&lt;br /&gt;            print(next_item)&lt;br /&gt;&lt;br /&gt;def test():&lt;br /&gt;    w_set = set()&lt;br /&gt;    for i in range(WORKERS):&lt;br /&gt;        new_w = Worker()&lt;br /&gt;        new_w.start()&lt;br /&gt;        w_set.add(new_w)&lt;br /&gt;&lt;br /&gt;    print('Running: Press Enter to finish')&lt;br /&gt;    sys.stdin.readline()&lt;br /&gt;&lt;br /&gt;if __name__ == '__main__':&lt;br /&gt;    test()&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Sure enough, running and monitoring this shows 0% CPU usage, but WORKER+1 threads in use (I'm using OS X's Activity Monitor at the moment).&lt;/p&gt;&lt;p&gt;But let's suppose we want to change the worker threads to wake up occasionally to do some background activity. No problem: provide a &lt;code&gt;timeout&lt;/code&gt; on the &lt;code&gt;Queue.get()&lt;/code&gt;:&lt;/p&gt;&lt;pre class="prettyprint lang-py"&gt;&lt;br /&gt;class TimeoutWorker(Worker):&lt;br /&gt;    def run(self):&lt;br /&gt;        while True:&lt;br /&gt;            try:&lt;br /&gt;                next_item = self.queue.get(&lt;i style="font-weight:bold"&gt;timeout=1&lt;/i&gt;)&lt;br /&gt;            except queue.Empty:&lt;br /&gt;                # do whatever background check needs doing&lt;br /&gt;                pass&lt;br /&gt;            else:&lt;br /&gt;                print(next_item)&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;OK, so now the threads can wake up occasionally and perform whatever activity they want.&lt;/p&gt;&lt;h4&gt;Except...&lt;/h4&gt;&lt;p&gt;CPU usage just went up from ~0% to 10%. Increasing &lt;code&gt;WORKERS&lt;/code&gt; shows that the CPU load of this program which still does nothing (the queues never get anything put in them) is proportional to the number of threads (95% at 1000 worker threads). I'm not inclined to look further than assuming this is some artifact of the GIL (pthread activity seems to be the culprit).&lt;/p&gt;&lt;p&gt;This is fairly independent of the length of the timeout. For very short timeouts, I'd expect CPU usage to go up, as the worker thread is spending more time doing work rather than being blocked. But there is no noticeable difference between &lt;code&gt;timeout=10&lt;/code&gt; and &lt;code&gt;timeout=sys.maxint&lt;/code&gt;. In the latter case, the &lt;code&gt;get()&lt;/code&gt; is never plausibly going to timeout, but the same high-CPU behaviour still occurs.&lt;/p&gt;&lt;h4&gt;Fixing the code&lt;/h4&gt;&lt;p&gt;I'm not inclined to delve deep into CPython to look at what &lt;code&gt;Queue.get()&lt;/code&gt; is doing under the hood. It's clearly something very different depending on whether it has a timeout or not. For now I'm content to fix the code to eliminate the situations where these problems can occur. Hopefully the fact that I've written this will keep me aware of this potential issue and I'll manage to avoid it in future :)&lt;/p&gt;&lt;p&gt;The code where I found this issue was using a 1 second timeout to continually check the while condition and exit if required. This was easily fixed with sending a poison-pill of None into the queue rather than setting a flag on the thread instance, and checking for this once we've got a next_item. This is cleaner anyway, allowing immediate thread termination and the use of timeout-less &lt;code&gt;get()&lt;/code&gt;.  For more complex cases where some background activity is required in the worker threads, it might make more sense to keep all threads using timeout-less &lt;code&gt;Queue.get()&lt;/code&gt;s and have a separate thread sending sentinel values into each queue according to some schedule, which cause the background activity to be run.&lt;/p&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;&lt;p&gt;It seems fairly unintuitive that simply adding a timeout to a &lt;code&gt;Queue.get()&lt;/code&gt; can totally change the CPU characteristics of a multi-threaded program. Perhaps this could be documented and explained. But then in CPython it seems many threading issues are &lt;a href="http://www.dabeaz.com/GIL/"&gt;entirely unintuitive&lt;/a&gt;. The scientific part of my brain won't stop thinking threads are wonderful, but the engineering part is becoming increasingly sceptical about threads and enamoured with &lt;a href="http://www.dabeaz.com/coroutines/"&gt;coroutines&lt;/a&gt;, especially with &lt;a href="http://www.python.org/dev/peps/pep-0380/"&gt;PEP 380&lt;/a&gt; on the horizon.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-1210455087121295111?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/1210455087121295111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2011/02/concurrent-queueget-with-timeouts-eats.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/1210455087121295111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/1210455087121295111'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2011/02/concurrent-queueget-with-timeouts-eats.html' title='Concurrent Queue.get() with timeouts eats CPU'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-3603888404755164264</id><published>2011-02-09T22:42:00.000Z</published><updated>2011-02-09T22:42:05.285Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ftdi'/><category scheme='http://www.blogger.com/atom/ns#' term='pylibftdi'/><title type='text'>pylibftdi 0.7 - multiple device support</title><content type='html'>&lt;p&gt;pylibftdi has always been about minimalism, which means that if you wanted to do something it didn't support, things got tricky. One of it's glaring deficiencies until now was that it only supported a single FTDI device - if you had multiple devices plugged in, it would pick one - seemingly - at random.&lt;/p&gt;&lt;p&gt;With pylibftdi 0.7, that has finally changed, and devices can now be opened by name. Or at least by serial number, which is nearly as good. A new example script (which I've just remembered is hideously raw and lacks any tidying up at all) &lt;code&gt;examples/list_devices.py&lt;/code&gt; in the source distribution will enumerate the attached devices, displaying the manufacturer (which should be FTDI in all cases), description, and serial number.&lt;/p&gt;&lt;p&gt;The API has changed slightly to cope with this; whereas previously there was just a single &lt;code&gt;Driver&lt;/code&gt; class, now the primary interface is the &lt;code&gt;Device&lt;/code&gt; class.  &lt;code&gt;Driver&lt;/code&gt; still exists, and holds the CDLL reference, as well as supporting device enumeration and providing backwards compatibility.&lt;/p&gt;&lt;p&gt;(As an aside, using ftdi_usb_find_all was (not) fun - it sets a pointer to pointer which is then used to traverse a linked list. Trivial in C, an hour of frustration in ctypes. Anyway, I got there in the end).&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; from pylibftdi import Device&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; import time&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; &lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; # make some noise&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; with Device('FTE4FFVQ', mode='b') as midi_dev:&lt;br /&gt;...     midi_dev.baudrate = 31250&lt;br /&gt;...     for count in range(3):&lt;br /&gt;...         midi_dev.write(b'\x90\x3f\x7f')&lt;br /&gt;...         time.sleep(0.5)&lt;br /&gt;...         midi_dev.write(b'\x90\x3f\x00')&lt;br /&gt;...         time.sleep(0.25)&lt;br /&gt;... &lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Both &lt;code&gt;Device()&lt;/code&gt; and &lt;code&gt;BitBangDevice&lt;/code&gt; take device_id as the (optional) first parameter to select the target device. If porting from an earlier version, one of the first changes is probably to use named parameters for options when instantiating these classes. My intention is that device_id will always be the first parameter, but the order and number of subsequent parameters could change.&lt;/p&gt;&lt;p&gt;Another change is that Devices are now opened implicitly on instantiation unless told not to (see the docstrings). Previously the Driver class only opened automatically when used as a context manager.  There is no harm in opening devices multiple times though - subsequent &lt;code&gt;open()&lt;/code&gt;s have no effect.&lt;/p&gt;&lt;p&gt;I've also finally figured out that I need to set long_description in setup.py to get documentation to appear on the PyPI front page. After all, without docs, &lt;a href="http://lukeplant.me.uk/blog/posts/docs-or-it-doesnt-exist/"&gt;it doesn't exist&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;It's only been a few days since 0.6, but I wanted to get this release out - I think it is a big improvement since 0.5, and It'll probably be a while till the next release. In the mean time, I'll try and get a vaguely useful example going - which will probably involve MIDI and an LCD...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-3603888404755164264?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/3603888404755164264/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2011/02/pylibftdi-07-multiple-device-support.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/3603888404755164264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/3603888404755164264'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2011/02/pylibftdi-07-multiple-device-support.html' title='pylibftdi 0.7 - multiple device support'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-1593867374625977512</id><published>2011-02-06T20:09:00.000Z</published><updated>2011-02-06T20:09:52.761Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ftdi'/><category scheme='http://www.blogger.com/atom/ns#' term='pylibftdi'/><title type='text'>pylibftdi 0.6 released: now with Python 3 goodness</title><content type='html'>&lt;p&gt;&lt;a href="http://pypi.python.org/pypi/pylibftdi/"&gt;&lt;b&gt;pylibftdi&lt;/a&gt; 0.6&lt;/b&gt; has been out the door and onto PyPI for the last few days, but I'm only just getting round to blogging about it. It's basically some minor work for Python 3 compatibility - the same code now works on both Python 2 (2.6/2.7) and Python 3.  This means support for Python 2.5 has been dropped (due to use of &lt;code&gt;bytearray&lt;/code&gt;/&lt;code&gt;bytes&lt;/code&gt; types). I can always add it back in if people shout.&lt;/p&gt;&lt;p&gt;Other than trivially fixing a print statement to be a function call, the main change required was the expected bytes/string issue. The driver also gains a couple of parameters; &lt;code&gt;mode = 't'&lt;/code&gt; ('t':text, 'b':binary) and &lt;code&gt;encoding = 'latin1'&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;In binary mode (the default - so no user code changes are required for this release), read() and write() take and return instances of type &lt;code&gt;bytes&lt;/code&gt;. For text mode, &lt;code&gt;write()&lt;/code&gt; will take either &lt;code&gt;bytes&lt;/code&gt;/&lt;code&gt;bytearray&lt;/code&gt;, or a string which it will encode with the given driver encoding, and &lt;code&gt;read()&lt;/code&gt; will return a string. I've set the default to be &lt;code&gt;latin1&lt;/code&gt; rather than using &lt;code&gt;utf-8&lt;/code&gt; as it is an equivalence mapping over the first 256 code points.&lt;/p&gt;&lt;h4&gt;Coming soon...&lt;/h4&gt;&lt;p&gt;I've started work on 0.7 - the main feature of which is support for multiple devices. I had a few problems getting the right ctypes incantations to follow the linked-list which ftdi_usb_find_all sets, but that's sorted now. The bigger issue is that it really needs a split between driver and device, which could cause the API to change. I'm thinking of various ways to keep existing code working, and will probably go for something like:&lt;ul&gt;&lt;li&gt;&lt;b&gt;0.7&lt;/b&gt; - set pylibftdi.SUPPORT_MULTIPLE to True to use new API / support multiple devices&lt;/li&gt;&lt;li&gt;&lt;b&gt;0.8&lt;/b&gt; - set pylibftdi.SUPPORT_MULTIPLE to False to use old API / only support a single device / get a deprecation warning&lt;/li&gt;&lt;li&gt;&lt;b&gt;0.9&lt;/b&gt; - SUPPORT_MULTIPLE no longer used; old API disappears.&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;So &lt;b&gt;0.7&lt;/b&gt; is all about multiple device support, &lt;b&gt;0.8&lt;/b&gt; will probably be support for Windows (supporting D2XX, for example), and &lt;b&gt;0.9&lt;/b&gt; (or maybe just &lt;b&gt;1.0&lt;/b&gt;) will be a tidy-up / bug-fix / improve docs release. In parallel with all of this I'm writing some test code which will gradually bring this side of things up-to-standard. I'm not allowing myself to do a 1.0 release without decent testing &amp; docs. All that will probably take a two months; I only get a couple of hours a week looking at this. But it could be sooner - or later.&lt;/p&gt;&lt;p&gt;pylibftdi 0.7 should be out in within a week or so, and I'll elaborate more then, hence the lack of any examples here. I'm on the case!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-1593867374625977512?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/1593867374625977512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2011/02/pylibftdi-06-released-now-with-python-3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/1593867374625977512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/1593867374625977512'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2011/02/pylibftdi-06-released-now-with-python-3.html' title='pylibftdi 0.6 released: now with Python 3 goodness'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-2119232420562953223</id><published>2010-12-31T17:28:00.000Z</published><updated>2010-12-31T17:28:19.823Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>HTTP 'streaming' from Python generators</title><content type='html'>&lt;p&gt;One of the more annoying things about HTTP is that it wants to send things in complete chunks: you ask for an object with a particular URL, and some point later you get that object.  There isn't a lot you can do (at least from JavaScript) until the complete resource has loaded.For more fine grained control, it's a bit annoying.&lt;/p&gt;&lt;p&gt;Of course web sockets will solve all of this (&lt;a href="http://hacks.mozilla.org/2010/12/websockets-disabled-in-firefox-4/"&gt;maybe&lt;/a&gt;) once the spec has gone through the mill a few more times.  But in the mean-time there is often an impedance mismatch between how we'd like to be able to do things on the server-side and how we are forced to do them because of the way HTTP works.&lt;/p&gt;&lt;p&gt;The following is an example of one way to manage splitting things up.  It allows Python generators to be used on the server side and sends an update to the client on every yield, with the client doing &lt;a href="http://en.wikipedia.org/wiki/Comet_(programming)"&gt;long-polling&lt;/a&gt; to get the data. This shouldn't be confused with CherryPy's support for yield streaming single responses back to the server (&lt;a href="http://www.cherrypy.org/wiki/ReturnVsYield"&gt;which is discouraged&lt;/a&gt;) - the yield functionality is hijacked for other purposes if the method decorator is applied. Also note that this is only of any help for clients which can use AJAX to repeatedly poll the generator.&lt;/p&gt;&lt;h4&gt;Example&lt;/h4&gt;&lt;p&gt;Let's suppose that we want to generate a large (or infinite) volume of data and send it to a web client. It could be a long text document served line-by-line. But let's use the sequence of prime numbers (because &lt;a href="http://www.imdb.com/title/tt0118884/"&gt;that's good enough for aliens&lt;/a&gt;). We want to send it to the client, and have it processed as it arrives.  The principle is to use a generator on the server side rather than a basic request function, but wrap that in something which translates the generator into a sequence of responses, each serving one chunk of the response.&lt;/p&gt;&lt;p&gt;Server implementation using CherryPy - note the json_yield decorator.&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;import cherrypy&lt;br /&gt;&lt;br /&gt;class PrimeGen(object):&lt;br /&gt;    @cherrypy.expose&lt;br /&gt;    def index(self):&lt;br /&gt;        return INDEX_HTML # see below&lt;br /&gt;&lt;br /&gt;    @cherrypy.expose&lt;br /&gt;    @json_yield   # see below&lt;br /&gt;    def prime(self):&lt;br /&gt;        # this isn't supposed to be efficient.&lt;br /&gt;        probe = 1&lt;br /&gt;        while True:&lt;br /&gt;           for i in range(2, probe):&lt;br /&gt;               if probe % i == 0:&lt;br /&gt;                   break&lt;br /&gt;           else:&lt;br /&gt;               yield probe&lt;br /&gt;           probe += 2&lt;br /&gt;&lt;br /&gt;cherrypy.quickstart(PrimeGen)&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The thing which turns this generator into something usable with long-polling is the following 'json_yield' decorator.&lt;/p&gt;&lt;p&gt;Because we might want more than one such generator on the server (not to mention generator instances from multiple clients), we need a key - passed in from the client - which associates a particular client with the generator instance. This isn't really handled in this example, see the source file download at the end of the post for that.&lt;/p&gt;&lt;p&gt;The major win is that the client doesn't have to store a 'next-index' or anything else. State is stored implicitly in the Python generator on the server side. Both client and server code should be simpler. Of course this goes against &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;REST&lt;/a&gt; principles, where one of the fundamental tenets is that state should be stored only on the Client. But there is a place for everything.&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;import functools&lt;br /&gt;import json&lt;br /&gt;&lt;br /&gt;def json_yield(fn):&lt;br /&gt;    # each application of this decorator has its own id&lt;br /&gt;    json_yield._fn_id += 1&lt;br /&gt;&lt;br /&gt;    # put it into the local scope so our internal function&lt;br /&gt;    # can use it properly&lt;br /&gt;    fn_id = json_yield._fn_id&lt;br /&gt;&lt;br /&gt;    @functools.wraps(fn)&lt;br /&gt;    def _(self, key, *o, **k):&lt;br /&gt;        """&lt;br /&gt;        key should be unique to a session.&lt;br /&gt;        Multiple overlapping calls with the same &lt;br /&gt;        key should not happen (will result in&lt;br /&gt;        ValueError: generator already executing)&lt;br /&gt;        """&lt;br /&gt;&lt;br /&gt;        # create generator if it hasn't already been&lt;br /&gt;        if (fn_id,key) not in json_yield._gen_dict:&lt;br /&gt;            new_gen = fn(self, *o, **k)&lt;br /&gt;            json_yield._gen_dict[(fn_id,key)] = new_gen&lt;br /&gt;&lt;br /&gt;        # get next result from generator&lt;br /&gt;        try:&lt;br /&gt;           # get, assuming there is more.&lt;br /&gt;           gen = json_yield._gen_dict[(fn_id, key)]&lt;br /&gt;           content = gen.next()&lt;br /&gt;           # send it&lt;br /&gt;           return json.dumps({'state': 'ready',&lt;br /&gt;                              'content':content})&lt;br /&gt;        except StopIteration:&lt;br /&gt;           # remove the generator object&lt;br /&gt;           del json_yield._gen_dict[(fn_id,key)]&lt;br /&gt;           # signal we are finished.&lt;br /&gt;           return json.dumps({'state': 'done',&lt;br /&gt;                              'content': None})&lt;br /&gt;    return _&lt;br /&gt;# some function data...&lt;br /&gt;json_yield._gen_dict = {}&lt;br /&gt;json_yield._fn_id = 0&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The HTML to go with this is basic long-polling, and separating out the state from the content.  Here I'm using jQuery:&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;INDEX_HTML = """&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;script src="http://code.jquery.com/jquery-1.4.4.min.js"&amp;gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;br /&gt;$(function() {&lt;br /&gt;&lt;br /&gt;  function update() {&lt;br /&gt;    $.getJSON('/prime?key=1', {}, function(data) {&lt;br /&gt;      if (data.state != 'done') {&lt;br /&gt;        $('#status').text(data.content);&lt;br /&gt;        //// alternative for appending:&lt;br /&gt;        // $('#status').append($('&lt;div&gt;'+data.content+'&lt;/div&gt;'));&lt;br /&gt;        setTimeout(update, 0);&lt;br /&gt;      }&lt;br /&gt;    });&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  update();&lt;br /&gt;});&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;div id="status"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;"""&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;Uses&lt;/h4&gt;&lt;p&gt;The example above is contrived, but there are plenty of possibilities if the json_yield decorator is extended in a number of ways. Long running server side processes can send status information back to the client with minimal hassle. Client-side processing of large text documents can begin before they have finished downloading. One issue is that a chunk of the data should be semantically understandable. Using things like this on binary files or XML (where it is only valid once the root element is closed) won't have sensible results.&lt;/p&gt;&lt;p&gt;There are plenty of possibilities in extending this; the decorator could accumulate the content (rather than the client) and send the entire results up-to-now back, or (given finite memory) some portion of it using a length-limited deque.  Additional meta-data (e.g. count of messages so far, or the session key) could be added to the JSON information sent to the client each poll.&lt;/p&gt;&lt;p&gt;&lt;i&gt;&lt;b&gt;Disclaimer:&lt;/b&gt; I've not done any research into how others do this, because coding is more fun than research. There are undoubtedly better ways of accomplishing similar goals. In particular there are issues with memory usage and timeouts which aren't handled with json_yield. Also note that the example is obviously silly - it would be much faster to compute the primes on the client.&lt;/i&gt;&lt;/p&gt;&lt;a href="http://bitbucket.org/codedstructure/json_yield"&gt;Download Files&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-2119232420562953223?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/2119232420562953223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/12/http-streaming-from-python-generators.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/2119232420562953223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/2119232420562953223'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/12/http-streaming-from-python-generators.html' title='HTTP &apos;streaming&apos; from Python generators'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-8100972653633153631</id><published>2010-12-16T22:27:00.000Z</published><updated>2010-12-16T22:27:18.386Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Compiling "Essential Mathematics for Games" sample code on Mac OSX 10.6 Snow Leopard</title><content type='html'>&lt;p&gt;Before getting into a spot of games programming I thought I would buy a book which covered a few of the relevant topics.  Wanting something a bit deeper and not likely to be outdated in the too-near future, I plumped for Van Verth and Bishop's &lt;a href="http://www.amazon.co.uk/gp/product/0123742978?ie=UTF8&amp;tag=codedstruc-21&amp;linkCode=as2&amp;camp=1634&amp;creative=19450&amp;creativeASIN=0123742978"&gt;Essential Mathematics for Games and Interactive Applications: A Programmer's Guide&lt;/a&gt;&lt;img src="http://www.assoc-amazon.co.uk/e/ir?t=codedstruc-21&amp;l=as2&amp;o=2&amp;a=0123742978" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;[Amazon Associates link].  Seems fairly good so far, mainly because it establishes &lt;i&gt;why&lt;/i&gt; a certain approach is most applicable, rather than just telling you 'the' way to do things.&lt;/p&gt;&lt;p&gt;Anyway, the point of this blog post is to share some minor modifications required to the code included on the CD (which seems not available on-line) to get it building on Mac OS X 10.6 (Snow Leopard). From the documentation it seems the code was tested against OS X 10.4 and 10.5.  It fails to build out-of-the-CD on 10.6, and I didn't find any updates on the website (&lt;a href="http://www.essentialmath.com/"&gt;www.essentialmath.com&lt;/a&gt;), but perhaps in time that will get updated.&lt;/p&gt;&lt;p&gt;Required changes are:&lt;ol&gt; &lt;li&gt;in common/MakefileCommon, change lines 15-17 from:&lt;pre class="prettyprint"&gt;&lt;br /&gt;ifeq ($(PLATFORM), OSX)&lt;br /&gt;  CFLAGS_EXT = -fvisibility-inlines-hidden&lt;br /&gt;endif&lt;br /&gt;&lt;/pre&gt;to&lt;pre class="prettyprint"&gt;&lt;br /&gt;ifeq ($(PLATFORM), OSX)&lt;br /&gt;  CFLAGS_EXT = -fvisibility-inlines-hidden &lt;strong&gt;-ffriend-injection&lt;/strong&gt;&lt;br /&gt;endif&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt; change the equivalent line 12 CFLAGS_EXT setting in Examples/MakefileExamples in the same way, i.e. adding &lt;code&gt;-ffriend-injection&lt;/code&gt;.  Presumably this is a requirement of a more recent version of GCC in Snow Leopard.&lt;/li&gt; &lt;li&gt;In common/Graphics/OGL/IvRendererOGL.cpp line 204, remove the GLvoid in the InitGL definition, i.e. change from &lt;pre class="prettyprint"&gt;&lt;br /&gt;int &lt;br /&gt;IvRendererOGL::InitGL(GLvoid)&lt;br /&gt;&lt;/pre&gt;to&lt;pre class="prettyprint"&gt;&lt;br /&gt;int &lt;br /&gt;IvRendererOGL::InitGL()&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;To build it (this is all in the relevant README files, as is the basic requirement of having the Mac Developer tools - i.e. XCode - installed):&lt;pre class="prettyprint"&gt;&lt;br /&gt;cd &lt;i&gt;&amp;lt;root of directory structure&amp;gt;&lt;/i&gt;&lt;br /&gt;chmod -R +w *  # only required once, files/directories copied from CD are read-only&lt;br /&gt;pushd common&lt;br /&gt;make PLATFORM=OSX&lt;br /&gt;popd&lt;br /&gt;pushd Examples&lt;br /&gt;make PLATFORM=OSX&lt;br /&gt;popd&lt;br /&gt;&lt;/pre&gt;And then the example executables are available under the relevant chapter/section directory as &lt;code&gt;./Example&lt;/code&gt;, e.g. &lt;code&gt;Examples/Ch13-Simulation/Simulation-02-Integration/Example&lt;/code&gt;. Note some of the examples seem to segfault if not started from the working directory...&lt;/p&gt;&lt;p&gt;Anyway, hope this helps someone.  Now, on to developing some games...!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-8100972653633153631?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/8100972653633153631/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/12/compiling-essential-mathematics-for.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/8100972653633153631'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/8100972653633153631'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/12/compiling-essential-mathematics-for.html' title='Compiling &quot;Essential Mathematics for Games&quot; sample code on Mac OSX 10.6 Snow Leopard'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-7470148089439001690</id><published>2010-11-25T23:16:00.000Z</published><updated>2010-11-25T23:16:34.253Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ftdi'/><category scheme='http://www.blogger.com/atom/ns#' term='pylibftdi'/><title type='text'>pylibftdi updated to 0.5</title><content type='html'>&lt;p&gt;I've done some tidying up of &lt;a href="http://pypi.python.org/pypi/pylibftdi"&gt;pylibftdi&lt;/a&gt;, fixing a few bugs, refactored the pylibftdi package to contain several modules instead of everything dumped in a __init__.py file, and generally made it a bit cleaner. It even has docstrings for most things now, and a test or two!&lt;/p&gt;&lt;p&gt;pylibftdi is a simple interface to &lt;a href="http://www.intra2net.com/en/developer/libftdi/"&gt;libftdi&lt;/a&gt;, which in turn allows accessing &lt;a href-"http://www.ftdichip.com/"&gt;FTDI&lt;/a&gt;'s range of USB parallel and serial chips.  See &lt;a href="http://codedstructure.blogspot.com/2010/09/announcing-pylibftdi-minimal-pythonic.html"&gt;here&lt;/a&gt; for more details, but very briefly, serial access is provided by a file-like (read/write) interface with a &lt;code&gt;baudrate&lt;/code&gt; property, and parallel access is provided by a pair of properties - &lt;code&gt;direction&lt;/code&gt; (data direction register) and &lt;code&gt;port&lt;/code&gt; (data IO register).&lt;/p&gt;&lt;p&gt;I haven't yet added any more examples, hopefully I'll get round to that in the next week or so. I have been using it as a MIDI interface though, which is fun - I'll get an appropriate example of that out in the next version, together with some diagrams / photos etc.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-7470148089439001690?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/7470148089439001690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/11/pylibftdi-updated-to-05.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/7470148089439001690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/7470148089439001690'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/11/pylibftdi-updated-to-05.html' title='pylibftdi updated to 0.5'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-4604169098853378900</id><published>2010-11-09T23:38:00.001Z</published><updated>2010-11-09T23:38:31.954Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='website'/><title type='text'>BlogPress, iPod, website</title><content type='html'>So this is the obligatory 'testing' post from BlogPress on my new-ish iPod touch 4th gen. &lt;br /&gt;&lt;br /&gt;I wish the battery life was better, but the retina display is &lt;b&gt;awesome&lt;/b&gt; for reading tiny text, making ebooks surprisingly practical. It's also far too easy to spend lots of money on the app store. One nice thing is that three fingered touch typing is just about doable in landscape mode - not a skill I anticipated learning!&lt;br /&gt;&lt;br /&gt;I've been spending lots of time recently on my website &lt;a target="_blank" href="http://codedstructure.net"&gt;codedstructure.net&lt;/a&gt;, and especially on a project for playing with / learning GLSL in the context of WebGL: &lt;a target="_blank" href="http://codedstructure.net/projects/webgl_shader_lab/"&gt;WebGL Shader Lab&lt;/a&gt;, which I'll write more about next time.&lt;br /&gt;&lt;br /&gt;If only iOS Safari supported WebGL...&lt;br /&gt;&lt;br /&gt;- Posted using BlogPress from my iPod&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-4604169098853378900?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/4604169098853378900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/11/blogpress-ipod-website.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/4604169098853378900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/4604169098853378900'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/11/blogpress-ipod-website.html' title='BlogPress, iPod, website'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-6843507924624643079</id><published>2010-10-04T22:27:00.000+01:00</published><updated>2010-10-04T22:27:59.292+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='synth'/><category scheme='http://www.blogger.com/atom/ns#' term='microchip'/><category scheme='http://www.blogger.com/atom/ns#' term='pic'/><category scheme='http://www.blogger.com/atom/ns#' term='dspic'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><category scheme='http://www.blogger.com/atom/ns#' term='eeepc'/><title type='text'>dsPIC33 (and PIC18) programming on my EEEPC at last</title><content type='html'>&lt;p&gt;I've got an EEEPC 701, and although it is annoying in some ways (small screen, limited SSD space), it's great for portability. One of my goals when I got it was to be able to use it to help developing various microcontroller projects I've got on the go, and I especially like that it doesn't take up lots of space on my (tiny) desk when I'm hacking around. It works great with &lt;a href="http://arduino.cc"&gt;Arduino&lt;/a&gt;, but I prefer PICs to be honest.  The issue with this is that Microchip (producers of PIC microcontrollers) want everyone to use MPLAB, which only works on Windows.  And even if it worked on my Linux-based EEEPC, it probably wouldn't be too great on a 7 inch screen. Anyway, being born before 1980 (but not by much!) I still prefer command lines to IDEs anyway.  My first development environment was &lt;a href="http://en.wikipedia.org/wiki/Debug_(command)"&gt;debug.com&lt;/a&gt; on MS-DOS, and it's never been bettered :-)&lt;/p&gt;&lt;p&gt;At some point I'll get round to changing the OS (Linux Mint looks like the front runner at the mo...), but for now it's still got the Xandros stock install (though I've removed unionfs).&lt;/p&gt;&lt;p&gt;Rather than mess around with getting the (GCC based) Microchip tools compiled on the machine, I'm using wine - both &lt;a href="http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&amp;amp;nodeId=1406&amp;amp;dDocName=en010014"&gt;C18&lt;/a&gt; and &lt;a href="http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&amp;amp;nodeId=1406&amp;amp;dDocName=en535363"&gt;C30&lt;/a&gt; install and work without any problems.&lt;/p&gt;&lt;p&gt;For actually burning the image onto the controller, I use and the perfectly-working-without-lots-of-hassle &lt;a href="http://www.microchip.com/pickit2"&gt;pk2cmd&lt;/a&gt; and the brilliant PicKit2, (which was so successful Microchip went and &lt;a href="http://www.youtube.com/watch?v=LjfIS65mwn8"&gt;broke it&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;The following gives the commands I use to build and download the target .hex file - I've only got a single .c file (&lt;a href="https://bitbucket.org/codedstructure/picmusic/src/tip/dspic_synth/DacMusic.c"&gt;this one&lt;/a&gt;) for input at the moment, and haven't even got a makefile together yet.  But getting this working took a couple of hours, so this is as much for reference as anything else...&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;# exit on errors&lt;br /&gt;set -e&lt;br /&gt;&lt;br /&gt;C30_BASE=/home/user/.wine/drive_c/Program\ Files/Microchip/MPLAB\ C30/&lt;br /&gt;&lt;br /&gt;echo "Building..."&lt;br /&gt;wine "${C30_BASE}/bin/bin/pic30-coff-gcc.exe" -o dac_music.coff -mcpu=33fj64gp802 -Wl,--script "${C30_BASE}/support/dsPIC33F/gld/p33FJ64GP802.gld" DacMusic.c&lt;br /&gt;&lt;br /&gt;echo "bin2hex..."&lt;br /&gt;wine "${C30_BASE}/bin/bin/pic30-coff-bin2hex.exe" dac_music.coff&lt;br /&gt;&lt;br /&gt;echo "burning..."&lt;br /&gt;pk2cmd -Pdspic33fj64GP802 -Fdac_music.hex -Q -M -R -T&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;For reference, I've also got a similar setup for something on the PIC18.  I've had this running from fairly soon after I got my EEEPC, and didn't have problems getting it up and running:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;code&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;# exit on errors&lt;br /&gt;set -e&lt;br /&gt;&lt;br /&gt;C18_BASE=/home/user/.wine/drive_c/MCC18&lt;br /&gt;&lt;br /&gt;echo "Compiling..."&lt;br /&gt;wine ${C18_BASE}/bin/mcc18-traditional.exe -ml -p=18f252 -k -Oi+ music.c&lt;br /&gt;&lt;br /&gt;echo "Linking..."&lt;br /&gt;wine ${C18_BASE}/bin/mplink.exe \\MCC18\\lkr\\18f252i.lkr /l\\MCC18\\lib /aINHX32 music.o&lt;br /&gt;&lt;br /&gt;echo "burning..."&lt;br /&gt;pk2cmd -P18f252 -Fa.hex -M -R -T&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At some point I'll turn them into makefiles, but for now - I can program tiny microcontrollers with my almost-as-tiny EEEPC. Which is nice and cosy.&lt;/p&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_UDifY5VVhnk/TKpCru3ndjI/AAAAAAAAABo/kIJDV2v98Ao/s1600/DSCN3429.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="http://3.bp.blogspot.com/_UDifY5VVhnk/TKpCru3ndjI/AAAAAAAAABo/kIJDV2v98Ao/s400/DSCN3429.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Some time soon I'll actually write a blog post or two about the projects I'm using this with - mostly synthesizers and other various things to do with MIDI.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-6843507924624643079?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/6843507924624643079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/10/dspic33-and-pic18-programming-on-my.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/6843507924624643079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/6843507924624643079'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/10/dspic33-and-pic18-programming-on-my.html' title='dsPIC33 (and PIC18) programming on my EEEPC at last'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_UDifY5VVhnk/TKpCru3ndjI/AAAAAAAAABo/kIJDV2v98Ao/s72-c/DSCN3429.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-1982457091910099514</id><published>2010-09-26T20:46:00.000+01:00</published><updated>2010-09-26T20:46:13.052+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><title type='text'>Non-evil SEO?</title><content type='html'>&lt;p&gt;I've always thought SEO was evil (in the non-theological sense!), but &lt;a href="http://promotejs.com/"&gt;this effort&lt;/a&gt; (via &lt;a href="http://twitter.com/rem"&gt;@rem&lt;/a&gt;) seems well worth supporting.  According to my Facebook page my favourite quote is 'It is amazing what you can accomplish if you do not care who gets the credit' - so said Harry Truman.  Perhaps amazing is overstating the goal, but maybe it could be paraphrased 'It is amazing what you can make Google do if it is actually helpful and not (directly) self-serving'.  I guess we'll find out...&lt;/p&gt;&lt;a href='https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function' title='JavaScript JS Documentation: JS Function apply, JavaScript Function apply, JS Function .apply, JavaScript Function .apply'&gt;&lt;img src='http://static.jsconf.us/promotejsvs.png' height='280' width='160' alt='JavaScript JS Documentation: JS Function apply, JavaScript Function apply, JS Function .apply, JavaScript Function .apply'/&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-1982457091910099514?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/1982457091910099514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/09/non-evil-seo.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/1982457091910099514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/1982457091910099514'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/09/non-evil-seo.html' title='Non-evil SEO?'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-5167714236160303796</id><published>2010-09-19T22:45:00.000+01:00</published><updated>2010-09-21T10:08:05.887+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ftdi'/><category scheme='http://www.blogger.com/atom/ns#' term='pylibftdi'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Announcing pylibftdi - a minimal Pythonic wrapper for libftdi</title><content type='html'>The playing-around I've done with FTDI devices seemed like a good opportunity to actually release something as open source, and so I present 'pylibftdi'.  Undoubtedly not the greatest, but right now most likely the latest FTDI-Python bridge in the rather large open source field.There are a few features I know I want to add to it (primarily support for multiple devices), but for a flavour of things:&lt;p&gt;&lt;em&gt;Toggling an LED or other device from pin D0&lt;/em&gt;&lt;pre class="prettyprint"&gt;&lt;code&gt;from pylibftdi import BitBangDriver&lt;br /&gt;import time&lt;br /&gt;&lt;br /&gt;with BitBangDriver() as bb:&lt;br /&gt;    while True:&lt;br /&gt;        bb.port ^= 1&lt;br /&gt;        time.sleep(0.5)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Sending a string to a serial terminal&lt;/em&gt;&lt;pre class="prettyprint"&gt;&lt;code&gt;from pylibftdi import Driver&lt;br /&gt;&lt;br /&gt;with Driver() as drv:&lt;br /&gt;    drv.baudrate = 19200&lt;br /&gt;    drv.write('Hello World!')&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;It's been tested on Linux (Ubuntu 10.10) and Mac OS X (10.6), with libftdi 0.17 and 0.18, but doesn't have any intended platform specific requirements other than having the libftdi library installed.The following goals for this project differentiate it from similar projects:&lt;ul&gt;&lt;li&gt;Fully supported on Linux and Mac OS X, using Intra2net's open source &lt;a href="http://www.intra2net.com/en/developer/libftdi/"&gt;libftdi driver&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Simple things are very simple, as the example above shows.  The basic functionality is made as simple as possible to use, with properties and context managers used where it makes sense.  Most other FTDI Python wrappers are 'just' low level bindings of the underlying API.&lt;/li&gt;&lt;li&gt;There will be an increasing library of examples showing interaction with various protocols and devices - note this is a goal, not yet an accomplishment, though there is an LCD example there.&lt;/li&gt;&lt;/ul&gt;&lt;a href="http://pypi.python.org/pypi/pylibftdi"&gt;pylibftdi&lt;/a&gt; is easy_installable (or equivalent) from PyPI, and the &lt;a href="http://bitbucket.org/codedstructure/pylibftdi"&gt;code&lt;/a&gt; is developed on bitbucket, where you can also raise tickets for problems and feature requests.&lt;p style="font-size:0.8em"&gt;For reference, other similar projects include &lt;a href="http://bleyer.org/pyusb/"&gt;PyUSB&lt;/a&gt;, &lt;a href="http://git.marcansoft.com/?p=pyftdi.git;a=summary"&gt;pyftdi&lt;/a&gt;, &lt;a href="http://packages.debian.org/unstable/python/python-ftdi"&gt;python-ftdi&lt;/a&gt;, and &lt;a href="http://pypi.python.org/pypi/ftd2xx"&gt;ftd2xx&lt;/a&gt;.  There are probably others...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-5167714236160303796?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/5167714236160303796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/09/announcing-pylibftdi-minimal-pythonic.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/5167714236160303796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/5167714236160303796'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/09/announcing-pylibftdi-minimal-pythonic.html' title='Announcing pylibftdi - a minimal Pythonic wrapper for libftdi'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-2409356798437452285</id><published>2010-08-30T20:10:00.003+01:00</published><updated>2011-02-02T22:57:40.999Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ftdi'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>libftdi on Mac OS X</title><content type='html'>&lt;p&gt;&lt;b&gt;Update 2011/02/02:&lt;/b&gt; In trying to port pylibftdi to Python3, I found that the libraries which get built following the instructions below are 64-bit. All well and good, but the Python3.1 installation on Mac OS X 10.6 is 32-bit only (unlike the Python2.6 install).&lt;/p&gt;&lt;p&gt;While it's &lt;a href="http://stackoverflow.com/questions/1455720/mac-osx-10-6-compiler-a-puzzling-experience-with-32-vs-64-bit"&gt;possible&lt;/a&gt; to get both 32-bit and 64-bit universal libraries, I haven't tried that yet. The solution to built 32-bit libraries was to use the following:&lt;/p&gt;&lt;p&gt;&lt;code&gt;CFLAGS="-arch i386" ./configure &amp;&amp; make &amp;&amp; sudo make install&lt;/code&gt;&lt;/p&gt;&lt;p&gt;(Note I omitted libusb and &lt;code&gt;sudo&lt;/code&gt; (for make install) in previous instructions - I've updated below).  I also found I needed to do:&lt;/p&gt;&lt;p&gt;&lt;code&gt;export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/&lt;/code&gt;&lt;/p&gt;prior to building libusb-compat - I can't remember if this was a problem or not the first time round. Anyway, hopefully I'll have pylibftdi working with Python3 soon.&lt;br /&gt;&lt;b&gt;End of Update&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I've not written much about my ftdi projects recently, so here's an update.I've played around with reading values from an encoder and outputting to a RGB LED with PWM, but both of these require a fairly high constant poll rate (or in the case of reading the encoder, ideally interrupt-on-change). The jitter is quite annoying, and decent PWM seems tricky, even when following FTDI's instructions (&lt;a href=http://www.ftdichip.com/Support/Documents/AppNotes/AN232B-03_D2XXDataThroughput.pdf"&gt;pdf link&lt;/a&gt;) for maxmising the buffer size.  There's always going to be a gap when one buffer has finished and the next starts.&lt;/p&gt;&lt;p&gt;On a different note, I'm now mostly using my new Mac mini, so I've spent a few moments getting things to work there. Prerequisites:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.libusb.org/"&gt;libusb&lt;/a&gt; (tested with &lt;a href="http://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.8/libusb-1.0.8.tar.bz2/download"&gt;version 1.0.8&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;&lt;a href="http://pkgconfig.freedesktop.org"&gt;pkg-config&lt;/a&gt; (tested with &lt;a href="http://pkgconfig.freedesktop.org/releases/pkg-config-0.25.tar.gz"&gt;version 0.25&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;&lt;a href="http://sourceforge.net/projects/libusb/files/libusb-compat-0.1/"&gt;libusb-compat&lt;/a&gt; (test with &lt;a href="http://sourceforge.net/projects/libusb/files/libusb-compat-0.1/libusb-compat-0.1.3/"&gt;version 0.1.3&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.intra2net.com/en/developer/libftdi/download.php"&gt;libftdi&lt;/a&gt; (tested with &lt;a href="http://www.intra2net.com/en/developer/libftdi/download/libftdi-0.18.tar.gz"&gt;version 0.18&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt;These should be installed in the order listed; for each file, download it, untar it (tar -xf &lt;i&gt;filename&lt;/i&gt;), then run '&lt;code&gt;./configure &amp;&amp; make &amp;&amp; sudo make install&lt;/code&gt;' in the new directory which tar has created.&lt;/p&gt;&lt;p&gt;On the Python side, there were a couple of issues when I tried to run the old code.  First was that the library could not be found at all.  This was due to the library extension (.so) being hardcoded.  For a cross-platform solution, it seems the best way is to use the following:&lt;pre class="prettyprint"&gt;&lt;br /&gt;from ctypes import *&lt;br /&gt;from ctypes.util import find_library&lt;br /&gt;&lt;br /&gt;dll = CDLL(find_library('ftdi'))&lt;br /&gt;&lt;/pre&gt;Rather than specifying 'libftdi.so', we have stripped off the 'lib' prefix and the .so extension.  The simple 'ftdi' string would be used if we were linking this library with gcc using the -l flag.  Try '&lt;code&gt;gcc -lftdi&lt;/code&gt;' and it should report only that it can't find &lt;code&gt;_main&lt;/code&gt;, not that the library is missing (try &lt;code&gt;gcc -lmadeupname&lt;/code&gt; and it should complain about being unable to find '&lt;code&gt;madeupname&lt;/code&gt;')&lt;/p&gt;&lt;p&gt;Once this was done, the program would some times run (especially under pdb, which lead me up the garden path of thinking it was a timing issue...), but other times would cause a segfault. This was tracked down to another hard-coded value - the size of the context structure.The following will report the size of the ftdi_context structure:&lt;pre class="prettyprint"&gt;&lt;br /&gt;echo -e '#include &lt;ftdi.h&gt;\nint main(){return sizeof(struct ftdi_context);}' | gcc -xc - &amp;&amp; (./a.out; echo $?)&lt;br /&gt;&lt;/pre&gt;This is somewhat fragile, as it will fail if the structure ever gets larger than 255 bytes, but this seems unlikely for the time being.  On this Mac this gives 112 bytes; on my Linux boxes it gives 84 - though they are running on the previous (0.17) version of libftdi.  There is also the issue that the Mac library is x86_64 (i.e. 64-bit), while the Linux libraries are 32-bit.&lt;/p&gt;&lt;p&gt;One solution, though not exactly a purist's, is to allocate far more memory than will be needed. It won't slow anything down, as only a pointer to the start of the block is passed around, and probably won't make a difference to the memory consumption as applications will always use whole numbers of pages (4KB minimum) anyway.  So for now, an allocation of 1KB seems a good solution.&lt;/p&gt;&lt;p&gt;The result of this is that the changes needed to the earlier code for compatibility with both Mac OS X and Linux are as follows:&lt;pre class="prettyprint"&gt;&lt;br /&gt;&lt;code&gt;...&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;from ctypes.util import find_library&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;def ftdi_start():&lt;br /&gt;    global ctx, fdll  # frown... :P&lt;br /&gt;    &lt;strong&gt;fdll = CDLL(find_library('libftdi'))&lt;br /&gt;    # size of ftdi_context varies&lt;br /&gt;    # seen 112 (x86_64, v0.18). 84 (i386, v0.17)&lt;br /&gt;    # over-allocate to 1KB.&lt;br /&gt;    ctx = create_string_buffer(1024)&lt;/strong&gt;&lt;br /&gt;    fdll.ftdi_init(byref(ctx))&lt;br /&gt;    fdll.ftdi_usb_open(byref(ctx), 0x0403, 0x6001)&lt;br /&gt;    fdll.ftdi_set_bitmode(byref(ctx), 0xFF, 0x01)&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;Me loves &lt;code&gt;os.name == 'posix'&lt;/code&gt; :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-2409356798437452285?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/2409356798437452285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/08/libftdi-on-mac-os-x.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/2409356798437452285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/2409356798437452285'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/08/libftdi-on-mac-os-x.html' title='libftdi on Mac OS X'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-7031800540478919786</id><published>2010-08-17T23:00:00.000+01:00</published><updated>2010-08-17T23:00:27.254+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='website'/><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><title type='text'>New website - codedstructure.net</title><content type='html'>&lt;p&gt;I've not got round to putting much on here for a while, but I have been busy, honest! I've finally got my own website after far too many years of not bothering: &lt;a href="http://codedstructure.net/"&gt;codedstructure.net&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I'm probably not the first to use scrolling like that, but I wasn't copying anyone and I think it's quite funky, especially the nice text shadows.  Me likes the way web development is going, after years of shunning it...&lt;/p&gt;&lt;p&gt;Oh, and while I'm at it, I've got a &lt;a href="http://twitter.com/codedstructure"&gt;twitter account&lt;/a&gt;, and hope to be churning out iPhone apps in the near future - though Objective C looks horribly like some terrible collision of Java and Smalltalk - in a bad way. Hope I can grow to like it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-7031800540478919786?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/7031800540478919786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/08/new-website-codedstructurenet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/7031800540478919786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/7031800540478919786'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/08/new-website-codedstructurenet.html' title='New website - codedstructure.net'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-4679489262087006841</id><published>2010-06-16T22:44:00.000+01:00</published><updated>2010-06-16T22:44:48.621+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ftdi'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>A Python LCD status display</title><content type='html'>This is the third in my &lt;a href="http://codedstructure.blogspot.com/search/label/ftdi"&gt;series&lt;/a&gt; of blog posts about doing IO with FTDI's Async BitBang mode on the UM245R / UM232R eval boards, and this time we're actually going to do something useful - have an LCD update with interesting system information.  The LCD in question is based on the ubiquitous HD44780 controller, which is interfaced to microcontrollers throughout the world...&lt;br /&gt;&lt;br /&gt;Anyway, with only 8 IO lines on the UM2xxR boards, we need to use the 4bit interface mode (two extra IO lines are needed beyond the 'data' path - one to act as a 'data-ready' strobe, and the other to select between 'data' and 'commands').  The wiring up is basically DB0-DB3 on the FTDI device going to D4-D7 on the LCD, with DB6 on the FTDI going to the 'RS' (register select) line on the LCD, and DB7 to the 'E' strobe.  If that makes no sense, then hopefully the photo makes things slightly clearer...&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_UDifY5VVhnk/TBlESITKGpI/AAAAAAAAAA0/tBQPUPtpJeo/s1600/DSCN3106.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_UDifY5VVhnk/TBlESITKGpI/AAAAAAAAAA0/tBQPUPtpJeo/s320/DSCN3106.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt; I've also got an LED backlight for my display, which makes it look a whole lot cooler :-)&lt;br /&gt;&lt;br /&gt;I'll present the code in chunks and try to explain it as I go along. First the initialisation and shutdown code, which are fundamentally unchanged from the previous examples, though they are now in functions to make them just a little tidier. (Note there is still no error checking here...)&lt;br /&gt;&lt;pre class="prettyprint" style="line-height: 1.1em;"&gt;"""&lt;br /&gt;Write a string (argv[1] if run from command line) to a HD44780&lt;br /&gt;LCD module connected via a FTDI UM232R/245R module&lt;br /&gt;&lt;br /&gt;example usage:&lt;br /&gt;&lt;br /&gt;# while true;&lt;br /&gt;&amp;gt;   do python lcd.py $( awk '{print $1}' /proc/loadavg);&lt;br /&gt;&amp;gt;   sleep 5;&lt;br /&gt;&amp;gt; done&lt;br /&gt;"""&lt;br /&gt;&lt;br /&gt;from ctypes import *&lt;br /&gt;import time, sys&lt;br /&gt;&lt;br /&gt;def ftdi_start():&lt;br /&gt;    global ctx, fdll  # frown... :P&lt;br /&gt;    fdll = CDLL('libftdi.so')&lt;br /&gt;    ctx = create_string_buffer(84)&lt;br /&gt;    fdll.ftdi_init(byref(ctx))&lt;br /&gt;    fdll.ftdi_usb_open(byref(ctx), 0x0403, 0x6001)&lt;br /&gt;    fdll.ftdi_set_bitmode(byref(ctx), 0xFF, 0x01)&lt;br /&gt;&lt;br /&gt;def ftdi_end():&lt;br /&gt;    fdll.ftdi_usb_close(byref(ctx))&lt;br /&gt;    fdll.ftdi_deinit(byref(ctx))&lt;br /&gt;&lt;/pre&gt;The following class is an abstraction of a bus - a collection of one (probably two, technically...) or more electrical lines which should be treated as a single unit.  The aim here is to be able to program in a similar style to the embedded programming on a microcontroller, where registers are typically memory mapped and writing to a bus is simply writing into a bitfield.  The parameters of this abstraction are the width of the bus (in bits), and the offset from the LSB of the entire port being accessed.  It also needs a reference to a driver which allows it to do the reading and writing to the port.  By using this as a descriptor, we can define buses within classes representing the various devices we are using; in this case the LCD.&lt;br /&gt;&lt;pre class="prettyprint" style="line-height: 1.1em;"&gt;class Bus(object):&lt;br /&gt;    """&lt;br /&gt;    This class is a descriptor for a bus of a given width starting&lt;br /&gt;    at a given offset (0 = LSB).  It needs a driver which does the&lt;br /&gt;    actual reading and writing - see FtdiDriver below&lt;br /&gt;    """&lt;br /&gt;    def __init__(self, driver, offset, width=1):&lt;br /&gt;        self.offset = offset&lt;br /&gt;        self.width = width&lt;br /&gt;        self._mask = ((1&amp;lt;&amp;lt;width)-1)&lt;br /&gt;        self.driver = driver&lt;br /&gt;&lt;br /&gt;    def __get__(self):&lt;br /&gt;        val = self.driver.read()&lt;br /&gt;        return (val &amp;gt;&amp;gt; offset) &amp;amp; self._mask&lt;br /&gt;&lt;br /&gt;    def __set__(self, obj, value):&lt;br /&gt;        value = value &amp;amp; self._mask&lt;br /&gt;        # in a multi-threaded environment, would&lt;br /&gt;        # want to ensure following was locked, eg&lt;br /&gt;        # by acquiring a driver lock&lt;br /&gt;        val = self.driver.latch()&lt;br /&gt;        val &amp;amp;= ~(self._mask &amp;lt;&amp;lt; self.offset)&lt;br /&gt;        val |= value &amp;lt;&amp;lt; self.offset&lt;br /&gt;        self.driver.write(val)&lt;br /&gt;&lt;/pre&gt;The following is the driver which will be used to do the actual data access.  Note the use of the latch to store the last value written to the port, which cannot generally be read from the device after having been written (Latch registers for the IO ports was a big advance for the PIC18F series over the earlier 16F series, which needed the application to store this separately in order to do read-modify-write operations properly on the IO ports).&lt;br /&gt;&lt;pre class="prettyprint" style="line-height: 1.1em;"&gt;class FtdiDriver(object):&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self._latch = 0&lt;br /&gt;&lt;br /&gt;    def read(self):&lt;br /&gt;        z = c_byte()&lt;br /&gt;        fdll.ftdi_read(byref(ctx), byref(z), 1)&lt;br /&gt;        return z.value&lt;br /&gt;&lt;br /&gt;    def latch(self):&lt;br /&gt;        return self._latch&lt;br /&gt;&lt;br /&gt;    def write(self, val):&lt;br /&gt;        self._latch = val&lt;br /&gt;        z = c_byte(val)&lt;br /&gt;        fdll.ftdi_write_data(byref(ctx), byref(z), 1)&lt;br /&gt;        # the following is a hack specifically to allow&lt;br /&gt;        # me to ignore all the timing constraints of the&lt;br /&gt;        # LCD.  For more advanced LCD usage, this wouldn't&lt;br /&gt;        # be acceptable...&lt;br /&gt;        time.sleep(0.005)&lt;br /&gt;&lt;/pre&gt;Now we've got a Bus class and a driver to use with it, we can define the LCD module interface.  I'm not going to cover the details of the interface, but the wikipedia &lt;a herf="http://en.wikipedia.org/wiki/HD44780_Character_LCD"&gt;HD44780&lt;/a&gt; page has some pointers.&lt;pre class="prettyprint" style="line-height: 1.1em;"&gt;# need to instantiate this in global context so LCD&lt;br /&gt;# class can be defined. Could tidy this up...&lt;br /&gt;ftdi_driver = FtdiDriver()&lt;br /&gt;&lt;br /&gt;class LCD(object):&lt;br /&gt;    """&lt;br /&gt;    The UM232R/245R is wired to the LCD as follows:&lt;br /&gt;       DB0..3 to LCD D4..D7 (pin 11..pin 14)&lt;br /&gt;       DB6 to LCD 'RS' (pin 4)&lt;br /&gt;       DB7 to LCD 'E' (pin 6)&lt;br /&gt;    """&lt;br /&gt;    data = Bus(ftdi_driver, 0, 4)&lt;br /&gt;    rs = Bus(ftdi_driver, 6)&lt;br /&gt;    e = Bus(ftdi_driver, 7)&lt;br /&gt;&lt;br /&gt;    def init_four_bit(self):&lt;br /&gt;        """&lt;br /&gt;        set the LCD's 4 bit mode, since we only have&lt;br /&gt;        8 data lines and need at least 2 to strobe&lt;br /&gt;        data into the module and select between data&lt;br /&gt;        and commands.&lt;br /&gt;        """&lt;br /&gt;        self.rs = 0&lt;br /&gt;        self.data = 3&lt;br /&gt;        self.e = 1; self.e = 0&lt;br /&gt;        self.e = 1; self.e = 0&lt;br /&gt;        self.e = 1; self.e = 0&lt;br /&gt;        self.data = 2&lt;br /&gt;        self.e = 1; self.e = 0&lt;br /&gt;&lt;br /&gt;    def _write_raw(self, rs, x):&lt;br /&gt;        # rs determines whether this is a command&lt;br /&gt;        # or a data byte. Write the data as two&lt;br /&gt;        # nibbles. Ahhh... nibbles. QBasic anyone?&lt;br /&gt;        self.rs = rs&lt;br /&gt;        self.data = x &amp;gt;&amp;gt; 4&lt;br /&gt;        self.e = 1; self.e = 0&lt;br /&gt;        self.data = x &amp;amp; 0x0F&lt;br /&gt;        self.e = 1; self.e = 0&lt;br /&gt;&lt;br /&gt;    def write_cmd(self, x):&lt;br /&gt;        self._write_raw(0, x)&lt;br /&gt;&lt;br /&gt;    def write_data(self, x):&lt;br /&gt;        self._write_raw(1, x)&lt;br /&gt;&lt;/pre&gt;All that remains is to initialise the FTDI device, initialise the LCD module, and write some data to it.&lt;pre class="prettyprint" style="line-height: 1.1em;"&gt;def display(string):&lt;br /&gt;    ftdi_start()&lt;br /&gt;&lt;br /&gt;    lcd = LCD()&lt;br /&gt;    lcd.init_four_bit()&lt;br /&gt;&lt;br /&gt;    # 001xxxxx - function set&lt;br /&gt;    lcd.write_cmd(0x20)&lt;br /&gt;    # 00000001 - clear display&lt;br /&gt;    lcd.write_cmd(0x01)&lt;br /&gt;    # 000001xx - entry mode set&lt;br /&gt;    # bit 1: inc(1)/dec(0)&lt;br /&gt;    # bit 0: shift display&lt;br /&gt;    lcd.write_cmd(0x06)&lt;br /&gt;    # 00001xxx - display config&lt;br /&gt;    # bit 2: display on&lt;br /&gt;    # bit 1: display cursor&lt;br /&gt;    # bit 0: blinking cursor&lt;br /&gt;    lcd.write_cmd(0x0C)&lt;br /&gt;&lt;br /&gt;    for i in string:&lt;br /&gt;        lcd.write_data(ord(i))&lt;br /&gt;&lt;br /&gt;    ftdi_end()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if __name__ == '__main__':&lt;br /&gt;    # note blatant lack of error checking...&lt;br /&gt;    display(sys.argv[1])&lt;br /&gt;&lt;/pre&gt;and there we have it; a slightly cumbersome but also slightly cool and slightly useful little display utility.  In the &lt;a href="http://catb.org/%7Eesr/writings/taoup/"&gt;spirit of UNIX programming&lt;/a&gt;, this only does one thing - display the command line argument on the LCD.  Obviously it needs major error handling if robustness is required...&lt;br /&gt;&lt;pre class="prettyprint"&gt;while true; do python lcd.py $( awk '{print $1}' /proc/loadavg); sleep 5; done&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_UDifY5VVhnk/TBlBGPbXqnI/AAAAAAAAAAs/Brlmz0uzZ2U/s1600/DSCN3110.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_UDifY5VVhnk/TBlBGPbXqnI/AAAAAAAAAAs/Brlmz0uzZ2U/s320/DSCN3110.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-4679489262087006841?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/4679489262087006841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/06/python-lcd-status-display.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/4679489262087006841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/4679489262087006841'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/06/python-lcd-status-display.html' title='A Python LCD status display'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_UDifY5VVhnk/TBlESITKGpI/AAAAAAAAAA0/tBQPUPtpJeo/s72-c/DSCN3106.JPG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-5590997343373023620</id><published>2010-06-08T21:39:00.000+01:00</published><updated>2010-06-08T21:39:59.651+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='mandelbrot'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='canvas'/><title type='text'>Mandelbrot Canvas...</title><content type='html'>&lt;p&gt;This &lt;a href="http://codedstructure.blogspot.com/p/mandelbrot-canvas.html"&gt;Mandelbrot Plotter&lt;/a&gt; is something I worked on a little while ago. One of the things I want to do in any language I'm learning is know how to get a pixel on a page. A long time ago it was function 0Ch of INT 10h, then memory mapped displays, and now the wonderful ImageData object underlying HTML5's Canvas element. It's so much more fun displaying a picture than 'Hello World' in text...&lt;/p&gt;&lt;p&gt;I'm also fascinated by fractals, and the Mandelbrot set in particular (since I sort-of understand the maths behind it). It makes me wonder whether it is an invention or a discovery, and just &lt;em&gt;why&lt;/em&gt; it is what it is - and whether other inscrutable patterns are just waiting to have some new visual representation cast a whole new light on them...&lt;/p&gt;&lt;p&gt;Of course with it being hosted (albeit slightly oddly on Blogger), I can now claim to have written a 'web app', for better or worse. Anyway, it's nice to be able to put random JavaScript up within Blogger...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-5590997343373023620?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/5590997343373023620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/06/mandelbrot-canvas.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/5590997343373023620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/5590997343373023620'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/06/mandelbrot-canvas.html' title='Mandelbrot Canvas...'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-747088777072410778</id><published>2010-05-27T21:29:00.000+01:00</published><updated>2010-05-27T21:29:38.799+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ftdi'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>Let there be LEDs</title><content type='html'>"In the beginning, [...] God said 'let there be light'".&lt;br /&gt;&lt;br /&gt;Some time later, Man discovered Gallium Arsenide, and eye-piercing LEDs have blighted us ever-since. &amp;nbsp;(Although they used to be quite dim, actually). &amp;nbsp;Nevertheless, the 'hello world' of the embedded world is to make an LED flash.&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://codedstructure.blogspot.com/2010/05/outside-world.html"&gt;part 1&lt;/a&gt; I 'covered' installation and test of the libftdi module, but the program didn't actually do anything. &amp;nbsp;The UM232R module is primarily a UART module (unlike the DLP USB245M, which is a FIFO), but as with most recent FTDI devices it supports a 'BitBang' mode. &amp;nbsp;BitBang is embedded jargon for running a protocol at the digital bit level, specifying in firmware at what point each of the (potentially many) IO lines goes high or low.&lt;br /&gt;&lt;br /&gt;To put these devices in to this mode, an API call is needed to the FTDI driver to establish this mode. &amp;nbsp;The ftdi_set_bitmode function takes three parameters; the FTDI control context (by reference), a direction bitmap, and a mode indicator (which should be 1 for async bitbang mode). &amp;nbsp;The interesting is the direction bitmap. &amp;nbsp;For each of the 8 IO lines, the corresponding bit in this mask can be a '1' to indicate an output, or a '0' for an input. &amp;nbsp;I'm starting with output, so...&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-c"&gt;if ((ret = ftdi_set_bitmode(&amp;amp;ftdic, 0xFF, 0x01)) &amp;lt; 0) {&lt;br /&gt;        fprintf(stderr, "unable to set bitmode\n");&lt;br /&gt;        return EXIT_FAILURE;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;(this fits into the 'DO STUFF HERE' part of the code from &lt;a href="http://codedstructure.blogspot.com/2010/05/outside-world.html"&gt;last time&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Once this is done, we can start writing things out to the data port.&lt;br /&gt;&lt;pre class="prettyprint lang-c"&gt;unsigned char x = 0;&lt;br /&gt;    while (1) {&lt;br /&gt;        ftdi_write_data(&amp;amp;ftdic, &amp;amp;x, 1);&lt;br /&gt;        x ^= 0xFF;      /* toggle all lines */&lt;br /&gt;        usleep(100000)  /* pause for 100ms  */&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is hackish - it never exits for a start - but it should enable an LED to flash!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_UDifY5VVhnk/S_mHxrh9VpI/AAAAAAAAAAk/DhEHFnIwr4Q/s1600/DSCN3115.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_UDifY5VVhnk/S_mHxrh9VpI/AAAAAAAAAAk/DhEHFnIwr4Q/s320/DSCN3115.JPG" /&gt;&lt;/a&gt;In terms of wiring things up, the 'GND' pin needs to go to the shorter leg of the LED (the cathode), and a data line (it doesn't matter which in this example, use DB0 to be safe) goes to the longer lead (anode).&amp;nbsp; A 1K resistor needs to be in either line to limit the current and prevent burning out the LED.  As supplied, the jumpers on the UM232R/UM245R module configure it to be self powered.  Anyway, it should look something like this, and the LED should be flashing at approx 5Hz.&lt;br /&gt;&lt;br /&gt;To do anything more interesting, let's move to Python. &amp;nbsp;This is where the fun begins - with ctypes.  I remember the first time I used ctypes, using puts from the C standard library on a Solaris machine, and the fact that it just worked. Occasionally there is a need to write the equivalent of a function prototype, but most of the time things are incredibly easy.&lt;br /&gt;&lt;br /&gt;First up: loading the shared library.  Lets guess its name - libftdi.so?&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-20)] on linux2&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; from ctypes import *&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; fdll = CDLL('libftdi.so')&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; fdll&lt;br /&gt;&amp;lt;CDLL 'libftdi.so', handle 81da028 at b7cfd4ac&amp;gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/pre&gt;&lt;br /&gt;So far so good :)  Next thing is this &lt;code&gt;ftdi_context&lt;/code&gt; struct which is referenced by each function in the C code.  It starts as an unpopulated structure, and presumably the first functions (init and usb_open) set it up as required.&amp;nbsp; While the D2XX interface just gives an integer handle, in libftdi we have to pass pointers to this structure around.&amp;nbsp; So, how do we define this in ctypes?&lt;br /&gt;First we need its size:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;#include "ftdi.h"&lt;br /&gt;#include "stdio.h"&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;    printf ("%d\n", sizeof(struct ftdi_context));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now compile and run...&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;/home/user/ftdi&amp;gt; gcc get_size.c&lt;br /&gt;/home/user/ftdi&amp;gt; ./a.out&lt;br /&gt;84&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, we need 84 bytes of storage for this context. ctypes will do that for us:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;&amp;gt;&amp;gt;&amp;gt; ftdic = create_string_buffer(84) &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Done that.  Now we can rattle it off: only two other things: first, where in C you give &amp;amp;var to give the address of a variable (e.g. as a parameter to a function taking *var), in Python with ctypes, it's byref(var). Second, to create a something which has existence in the C world, (e.g. so can have its address taken), there are a whole bunch of c_XXX functions - we'll use c_byte, which is equivalent to an unsigned char.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;from ctypes import *&lt;br /&gt;&lt;br /&gt;fdll = CDLL('libftdi.so')&lt;br /&gt;&lt;br /&gt;ftdic = create_string_buffer(84)&lt;br /&gt;&lt;br /&gt;fdll.ftdi_init(byref(ftdic))&lt;br /&gt;&lt;br /&gt;fdll.ftdi_usb_open(byref(ftdic), 0x0403, 0x6001)&lt;br /&gt;&lt;br /&gt;fdll.ftdi_set_bitmode(byref(ftdic), 0xFF, 0x01)&lt;br /&gt;&lt;br /&gt;import time&lt;br /&gt;x = c_byte(0)&lt;br /&gt;try:&lt;br /&gt;    while True:&lt;br /&gt;        fdll.ftdi_write_data(byref(ftdic), byref(x), 1)&lt;br /&gt;        time.sleep(0.1)&lt;br /&gt;        x.value ^= 0xFF # toggle all bits&lt;br /&gt;except KeyboardInterrupt:&lt;br /&gt;    pass&lt;br /&gt;&lt;br /&gt;fdll.ftdi_usb_close(byref(ftdic))&lt;br /&gt;&lt;br /&gt;fdll.ftdi_deinit(byref(ftdic))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And we're done!  It's surprising how easy it is to translate basic C code using libraries into Python using ctypes - normally it just works.&lt;br /&gt;&lt;br /&gt;Next time we'll look at interfacing to an LCD module...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-747088777072410778?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/747088777072410778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/05/let-there-be-leds.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/747088777072410778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/747088777072410778'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/05/let-there-be-leds.html' title='Let there be LEDs'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_UDifY5VVhnk/S_mHxrh9VpI/AAAAAAAAAAk/DhEHFnIwr4Q/s72-c/DSCN3115.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-8193119065668701251</id><published>2010-05-20T08:11:00.000+01:00</published><updated>2010-05-20T08:11:06.992+01:00</updated><title type='text'>Should I teach my children machine code?</title><content type='html'>I waited till primary school to read this book, but it seems that 'modern' kids can understand these things sooner - or at least Amazon thinks so...&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_UDifY5VVhnk/S_TgRPM5pEI/AAAAAAAAAAc/_xvmYeBsPIg/s1600/Screenshot-Amazon.co.uk:+lisa+watts:+Books+-+Mozilla+Firefox.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="104" src="http://4.bp.blogspot.com/_UDifY5VVhnk/S_TgRPM5pEI/AAAAAAAAAAc/_xvmYeBsPIg/s640/Screenshot-Amazon.co.uk:+lisa+watts:+Books+-+Mozilla+Firefox.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-8193119065668701251?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/8193119065668701251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/05/should-i-teach-my-children-machine-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/8193119065668701251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/8193119065668701251'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/05/should-i-teach-my-children-machine-code.html' title='Should I teach my children machine code?'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_UDifY5VVhnk/S_TgRPM5pEI/AAAAAAAAAAc/_xvmYeBsPIg/s72-c/Screenshot-Amazon.co.uk:+lisa+watts:+Books+-+Mozilla+Firefox.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-1640839367214348542</id><published>2010-05-18T21:05:00.000+01:00</published><updated>2010-05-18T21:06:31.997+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='ftdi'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>The outside world...</title><content type='html'>I'm going to do a series of blog posts on using FTDI devices to access the outside world. There are probably a dozen other similar series out there, so I hope I can introduce enough novelty to make it interesting&lt;br /&gt;&lt;br /&gt;I've been interested in low-level programming for as long as I've been programming (anyone else remember &lt;a href="http://www.amazon.co.uk/Machine-Code-Beginners-Computer-Electronics/dp/0860207358"&gt;this&lt;/a&gt; book? - yes, a "children's" book on Machine Code...)&lt;br /&gt;&lt;br /&gt;In terms of 'physical computing', things like &lt;a href="http://www.arduino.cc/"&gt;Arduino&lt;/a&gt; are really taking off at the moment, but I'm going to take a step back to the simplicity of simple digital IO based on the BitBang mode of FTDI's latest devices.&amp;nbsp; There are two reasons for this: firstly it came seem laborious writing two sets of software (for both the host computer and the target micro-controller), and secondly that even if the eventual application is going to be a standalone micro based system, it is still generally quicker to prototype things using only the host computer, avoiding the cross-compile and firmware upload cycle.&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_UDifY5VVhnk/S_LyfHPcKCI/AAAAAAAAAAM/5A09hjEzqDs/s1600/DSCN3093.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_UDifY5VVhnk/S_LyfHPcKCI/AAAAAAAAAAM/5A09hjEzqDs/s320/DSCN3093.JPG" /&gt;&lt;/a&gt;&lt;br /&gt;Hardware-wise, I'm using a &lt;a href="http://www.ftdichip.com/Products/EvaluationKits/UM232R.htm"&gt;FTDI UM232R&lt;/a&gt; (&lt;a href="http://uk.farnell.com/ftdi/um232r/evaluation-kit-usb-uart-ttl-ft232rl/dp/1146036?Ntt=um232r"&gt;Farnell link&lt;/a&gt;) device.&amp;nbsp; (I've also used one of &lt;a href="http://www.ftdichip.com/Products/EvaluationKits/DIPModules.htm#DLP-USB245M-G"&gt;these&lt;/a&gt;, and this either will be usable) This is a DIL module which plugs nicely into a breadboard which can be used to interface with stuff.&amp;nbsp; If you want to follow along, get a &lt;a href="http://www.maplin.co.uk/Module.aspx?ModuleNo=5195"&gt;breadboard&lt;/a&gt; to plug it into, some &lt;a href="http://www.maplin.co.uk/Search.aspx?criteria=LEDs&amp;amp;source=15"&gt;LEDs&lt;/a&gt;, 1Kohm &lt;a href="http://www.maplin.co.uk/Module.aspx?ModuleNo=341607"&gt;resistors&lt;/a&gt;, and some connecting wire (I like &lt;a href="http://www.maplin.co.uk/Module.aspx?ModuleNo=2013"&gt;these&lt;/a&gt;, but they are waaay over priced). &amp;nbsp;In a couple of posts I'll be using one of &lt;a href="http://www.maplin.co.uk/Module.aspx?ModuleNo=36389"&gt;these&lt;/a&gt; (N26AZ), too...&lt;br /&gt;&lt;br /&gt;On the software side, I'm using Linux on a EEEPC 701 (stock Xandros) with the libftdi drivers, compiled from source found &lt;a href="http://www.intra2net.com/en/developer/libftdi/"&gt;here&lt;/a&gt;.&amp;nbsp; The FTDI supplied drivers are similar and might be a better choice on Windows (not sure if libftdi works on Windows), but some of the function names and interfaces differ somewhat.&lt;br /&gt;&lt;br /&gt;First step is getting the &lt;a href="http://www.intra2net.com/en/developer/libftdi/documentation/"&gt;simple.c&lt;/a&gt; program compiled and working.&amp;nbsp; The program outline - slightly edited for length - looks something like this.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;/* see http://www.intra2net.com/en/developer/libftdi/documentation/ */ &lt;br /&gt;#include "stdio.h"&lt;br /&gt;#include "ftdi.h"&lt;br /&gt;&lt;br /&gt;int main(void)&lt;br /&gt;{&lt;br /&gt;    int ret;&lt;br /&gt;    struct ftdi_context ftdic;&lt;br /&gt;    if (ftdi_init(&amp;amp;ftdic) &amp;lt; 0) {&lt;br /&gt;        return EXIT_FAILURE;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if ((ret = ftdi_usb_open(&amp;amp;ftdic, 0x0403, 0x6001)) &amp;lt; 0) {&lt;br /&gt;        return EXIT_FAILURE;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /* DO STUFF HERE */&lt;br /&gt;&lt;br /&gt;    if ((ret = ftdi_usb_close(&amp;amp;ftdic)) &amp;lt; 0) {&lt;br /&gt;        return EXIT_FAILURE;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ftdi_deinit(&amp;amp;ftdic);&lt;br /&gt;&lt;br /&gt;    return EXIT_SUCCESS;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Compiling this (&lt;code&gt;gcc -o simple simple.c -lftdi&lt;/code&gt;) and running the resulting executable should not cause any errors, and should return a successful error code if a FTDI device is attached.&lt;br /&gt;&lt;br /&gt;This post is getting long enough for now, so I'll leave it at that.  Next time will be configuring bitbang mode, where we can use the device as a configurable 8-bit IO port, blinking lights, and the wonders of Python's ctypes module...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-1640839367214348542?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/1640839367214348542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/05/outside-world.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/1640839367214348542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/1640839367214348542'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/05/outside-world.html' title='The outside world...'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_UDifY5VVhnk/S_LyfHPcKCI/AAAAAAAAAAM/5A09hjEzqDs/s72-c/DSCN3093.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-9218186917583248927</id><published>2010-01-18T22:14:00.000Z</published><updated>2010-01-18T22:14:53.384Z</updated><title type='text'>The keyboard and the pen</title><content type='html'>When I was a teenager, I discovered something amazing.  A pen that made writing fun, desirable, and (almost) exciting. A Pilot V5. They never lasted long, but maybe that was because I'd actually write stuff with them. Time moved on, and I grew a penchant for nice Parker pens (&lt;a href="http://parkerpens.net/frontier.html"&gt;Frontier rollerball&lt;/a&gt; please...), except that I'd get one for Christmas and have lost it by my birthday only a month later, and need another one.  Anyways...  Moving on more than a few years, I've come to realise that having something which makes writing attractive is more than just a nice incidental thing, but an important consideration.&lt;br /&gt;&lt;br /&gt;At least for me, writing is a major way of organising and clarifying my thoughts, and I quite enjoy writing random streams of consciousness on a subject and later reviewing it to see if any interesting things are in there. If writing is fun, I'll do more of it, and having a decent writing instrument does make it fun.&lt;br /&gt;&lt;br /&gt;Nowadays, I don't use a pen much (and my handwriting seems to be getting worse from lack of practice), but I still use a writing instrument - my keyboard. And just as there is a great difference between a free biro and a decent pen, so there is with keyboards, if not more so. A decent keyboard makes 'writing' fun, and that is a good thing. My current choice is &lt;a href="http://www.amazon.co.uk/Apple-MB869B-A-Keyboard/dp/B001UHO7CE"&gt;a small Apple keyboard&lt;/a&gt; which is nice and portable, so I can plug it into whichever computer I happen to be using (it's even worth the annoyance of not having a delete key on a PC), and enjoy fine typing, perhaps even leading to some fine thoughts...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-9218186917583248927?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/9218186917583248927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2010/01/keyboard-and-pen.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/9218186917583248927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/9218186917583248927'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2010/01/keyboard-and-pen.html' title='The keyboard and the pen'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-1348372368745905377</id><published>2009-11-24T22:19:00.000Z</published><updated>2009-11-24T22:23:20.365Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>killing Python processes...</title><content type='html'>I'm playing with some midi based Python stuff at the moment, doing raw file access to /dev/midi1 (midisport uno), and most of the time it's just sitting on a file.read(1).  In Windows, the user can break into this with Ctrl-Break (Ctrl-C doesn't work on Windows or Linux), but there doesn't seem to be an equivalent to Ctrl-Break in the Linux world.  So it's Ctrl-Z to put it in the background, ps -a, find the program, then terminate it hastily with sudo kill -9. All of which is a bit excessive.  Rather than put something proper in there to terminate it (is select() the way to do these things on Linux?), I decided to get the wrong way a little less wrong.&lt;br /&gt;I now have a half-way house to getting it a bit simpler:&lt;br /&gt;&lt;pre&gt;alias killpy="sudo kill -9 \`ps -a | grep python | head -c 6\`"&lt;br /&gt;&lt;/pre&gt;And it's then just Ctrl-Z, killpy.  I'm sure this isn't the best way of doing things, but I like the fact that it does things the same way I do, but using pipes to communicate, instead of the eye-brain-hand-keyboard loop.  And it's the first time I've used the -c option on head (number of bytes to copy to stdout), so I've learnt something!&lt;br /&gt;&lt;br /&gt;Of course it doesn't work if there is more than one Python process, or whatever, and yes I do need the sudo and -9.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-1348372368745905377?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/1348372368745905377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2009/11/kill-python-process.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/1348372368745905377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/1348372368745905377'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2009/11/kill-python-process.html' title='killing Python processes...'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-7563505559185078815</id><published>2009-11-16T14:59:00.000Z</published><updated>2009-11-16T14:59:05.253Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='stl'/><title type='text'>Python lists aren't</title><content type='html'>Names are important, and doubly so in programming.  So when a programmer sees 'list', they think they know what that means, and similarly when they see 'array'.&lt;br /&gt;The fundamental difference would be something like this:&lt;br /&gt;&lt;br /&gt;array performance:&lt;br /&gt;random access - O(1)&lt;br /&gt;insertion / deletion of known element - O(n)&lt;br /&gt;&lt;br /&gt;list performance:&lt;br /&gt;random access - O(n)&lt;br /&gt;insertion / deletion of known element - O(1)&lt;br /&gt;&lt;br /&gt;The performance guarantees of a programming languages' data structures form part of the functional specification of that type, not just some incidental extra information. &lt;br /&gt;&lt;br /&gt;I bumped into this when using streams of bytes (represented as lists of integers each &amp;lt; 256) with the following codec-like code:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;def process(packet):&lt;br /&gt;    itemlen = work_out_length(packet)&lt;br /&gt;    item, packet = packet[:itemlen], packet[itemlen:]&lt;br /&gt;    # do something with item&lt;br /&gt;    return packet&lt;br /&gt;&lt;br /&gt;packet = &lt;i&gt;some data&lt;/i&gt;&lt;br /&gt;while packet:&lt;br /&gt;    packet = process(packet)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;which is equivalent to this...&lt;br /&gt;&lt;code&gt;&lt;pre&gt;a = &lt;i&gt;some data&lt;/i&gt;&lt;br /&gt;while a:&lt;br /&gt;    head, a = a[0], a[1:]&lt;br /&gt;    process(head)&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(The actual problem wasn't as easy to solve as the above case, as this assumes that the 'head' item is always a single byte; in reality it could be any number of bytes, and the packet would have to be streamed using multiple recursive loops like the above to process it. &amp;nbsp;But the fundamentals are the same.)&lt;br /&gt;&lt;br /&gt;Anyway, it all works fine until a large packet arrives. &amp;nbsp;And then the interactive program suddenly stops; what took on the order of a millisecond suddenly takes half-an-hour, which to any user looks like the program has crashed.&lt;br /&gt;&lt;br /&gt;This is a functional programming&amp;nbsp;idiom, but it just doesn't work with Python lists in the general case of large lists.&amp;nbsp;&amp;nbsp;&lt;i&gt;It didn't just slow it down, it completely broke it.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Solutions in this specific case are deques (collections.deque) or using iterators.  But that's for another time...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the C++ STL, part of the specification is a performance guarantee for each algorithm on each container type (&lt;a href="http://www.sgi.com/tech/stl/complexity.html"&gt;http://www.sgi.com/tech/stl/complexity.html&lt;/a&gt;). &amp;nbsp;In anything other than toy programs this information is critical, and they give the C++ developer an additional criteria in selecting the appropriate collection types. &amp;nbsp;It changes 'worse/better' into 'wrong/right'. &amp;nbsp;&lt;i&gt;'If [these specifications] are ignored [in an STL implementation], the performance of the resulting program will often render it useless.'&lt;/i&gt;&amp;nbsp;- from&amp;nbsp;previous&amp;nbsp;link. &amp;nbsp;The very separation of algorithms and data structures which the C++ STL enables (see the&amp;nbsp;&lt;a href="http://www.elementsofprogramming.com/"&gt;Elements of Programming&lt;/a&gt;&amp;nbsp;book for a up-to-date discussion of the underlying paradigm of the STL - without STL-specific code), makes possible the enumeration of performance guarantees (other than specifying it for every function in every types' API).  So while the Python documentation for lists warns that inserts and deletes at the beginning are O(n), this information isn't part of a coherent bigger picture which guides me to the right methods and data structures.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-7563505559185078815?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/7563505559185078815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2009/11/python-lists-arent.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/7563505559185078815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/7563505559185078815'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2009/11/python-lists-arent.html' title='Python lists aren&apos;t'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-2192811651819984023</id><published>2009-11-12T06:11:00.000Z</published><updated>2009-11-12T06:11:27.438Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='parenting'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>James Bond, Parenting, Refactoring</title><content type='html'>So it is 1:00 in the morning, and our youngest son wakes up screaming.  At 18 months it isn't always clear what the problem is, but with a bit of attention he soon settles.  Except the same thing happened an hour ago, though my wife got up then.  And, almost exactly an hour later, he wakes again, and does his 'muuuuu-meeeeee' type noises in-between crying.  Except I've woken up first, which sort of means it's my job to go to him, again...  And at this point I remember that vital software principle: &lt;i&gt;don't repeat youself (DRY)&lt;/i&gt;.  The tempting thing is to give him back his dummy, give him a cuddle, and within 2 minutes he could be back asleep - and in 3 so could I.  This is the bet I am making: there's a small chance he'll sleep through the rest of the night.  It's always possible.  But far more likely is that he'll wake again, and I won't get much sleep at all tonight.  Because if he woke 3 hours on the trot when he normally sleeps through without problem, there's probably a reason - maybe even a reason I could fix (bets on a dirty nappy?)  But I'm tired, and tiredness makes me even more lazy than usual, and... I hope he settles and I go back to bed.&lt;br /&gt;&lt;br /&gt;As in many areas of life, software developers continually have to make the choice between short-term ease against the risk of long-term disaster.  If the disaster was certain, the choice would be clear, if not easy.  But there is always the chance that it will never happen, and if the cost of averting that potential disaster is significant (e.g. lost business due to competition in time-to-market), it is no longer clear-cut.  But each time the risk is seen and ignored, the likelihood of getting it done right decreases.  If I get up at each hour from 1am till 5am to settle my son, am I really going to bother doing anything different at 6am?&lt;br /&gt;&lt;br /&gt;So what are we to do?  Recognise the need early, when the cost is least and the confidence of knowing that the potential disaster has already been averted can have the longest effect.  Make the commitment early, not counting the short-term effort as a cost, but as a decision well-made.&lt;br /&gt;&lt;br /&gt;I leave the quantitative analysis to Ian Fleming:&lt;br /&gt;'Once is happenstance, Twice is coincidence, The third time is enemy action'&lt;br /&gt;- Ian Fleming, Goldfinger&lt;br /&gt;&lt;br /&gt;Enemy action must be countered with force of will, or we shall be defeated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-2192811651819984023?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/2192811651819984023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2009/11/james-bond-parenting-refactoring.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/2192811651819984023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/2192811651819984023'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2009/11/james-bond-parenting-refactoring.html' title='James Bond, Parenting, Refactoring'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3029438816324283001.post-356690787622614156</id><published>2009-11-12T05:57:00.000Z</published><updated>2009-11-12T06:12:56.843Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Square Abstractions</title><content type='html'>Managing complexity is at the heart of Software Engineering, and abstraction is the tool by which we accomplish this. &amp;nbsp;But what do our abstractions look like, and how should we judge them?&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;Abstractions should be square.&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Or cubic. Possibly n-dimensional hypercubes. &amp;nbsp;But not rectangles. &amp;nbsp;And lines are right out. &amp;nbsp;G.A. Miller wrote a classic psychology paper in 1956 with the far-reaching conclusion that in uni-dimensional data-sets, humans have a typical classification capacity of between 2 and 3 bits - between 4 and 8 items. &amp;nbsp;His paper is titled 'The Magical Number Seven, Plus or Minus Two: Some Limits on our Capacity for Processing Information'. &amp;nbsp;How does this apply to software abstraction? It gives us a quantitive key to determining whether an abstraction (which implies a reduction in complexity) is of sufficient quality. &amp;nbsp;It also gives us a clue to resolving the issue of abstractions still retaining too much complexity: add another dimension.&lt;br /&gt;&lt;br /&gt;By square abstractions, I mean that a good set of abstractions in the software domain, from an arbitrarily complex starting point to the most understandable abstraction of that idea, should have approximately equal complexity in each dimension. &amp;nbsp;If the result is that each (and all, since we have decreed equality) dimension of abstraction is still too complex, we must re-dimension, refactor, and re-abstract.&lt;br /&gt;&lt;br /&gt;Soap bubbles form perfect spheres not just because they find it&amp;nbsp;aesthetically pleasing, but because they are most comfortable like that. &amp;nbsp;It takes the least effort. &amp;nbsp;In software we should similarly strive to find the solution which satisfies the constraints with the least energy. &amp;nbsp;Spheres might be nature's solution, but in software we tend to seek orthogonal abstractions - leading to squares, cubes, hypercubes, and so-on.&lt;br /&gt;&lt;br /&gt;Getting practical for a moment, remember that every program, library, and API is an abstraction. &amp;nbsp;An application containing a single 100,000 file (yes, really...) might be perfectly good internally, but is missing out on a key abstraction in terms of translation units, modules, whatever else maps to files. &amp;nbsp;So split it into one-hundred 1000&amp;nbsp;line files - we've added a dimension and reduced the maximum unidimensional complexity. &amp;nbsp;But we should continue - 100 is more than an order of magnitude greater than our magic 7 plus or minus 2. &amp;nbsp;Directories, packages, folders: another level of abstraction. &amp;nbsp;And because we are being square, we aim to have approximately 10 directories with 10 files in each. &amp;nbsp;&amp;nbsp;This stretches 7 +/-&amp;nbsp;2, but not sufficiently that any more abstraction would necessarily be helpful - adding a dimension has a cost too.&lt;br /&gt;Why 100 files of 1000 lines, and not 316 files of 316 lines? &amp;nbsp;Because not all abstractions have the same cost, and we can apply additional abstractions within those files. &amp;nbsp;Like, um, classes, methods and functions.&lt;br /&gt;&lt;br /&gt;So next time you (or I) think about adding that 100th method to our widget API, think about adding a new dimension instead.&amp;nbsp; And if it isn't obvious what that new dimension might be, then get creative and invent something new.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3029438816324283001-356690787622614156?l=blog.codedstructure.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.codedstructure.net/feeds/356690787622614156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.codedstructure.net/2009/11/square-abstractions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/356690787622614156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3029438816324283001/posts/default/356690787622614156'/><link rel='alternate' type='text/html' href='http://blog.codedstructure.net/2009/11/square-abstractions.html' title='Square Abstractions'/><author><name>Ben Bass</name><uri>http://www.blogger.com/profile/02283998269313171389</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
