<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;A0MBR384cSp7ImA9WxNUE0w.&quot;"><id>tag:blogger.com,1999:blog-8825992</id><updated>2009-11-04T01:24:16.139-06:00</updated><title>Electric Duncan</title><subtitle type="html">Scribbles of a Prydonian Renegade</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://oubiwann.blogspot.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>275</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/ElectricDuncan" type="application/atom+xml" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;DkMBQXg9fyp7ImA9WxNVFk8.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-6420207114447015861</id><published>2009-10-26T09:16:00.008-05:00</published><updated>2009-10-27T01:20:50.667-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-27T01:20:50.667-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="rrd" /><category scheme="http://www.blogger.com/atom/ns#" term="open source" /><category scheme="http://www.blogger.com/atom/ns#" term="games" /><category scheme="http://www.blogger.com/atom/ns#" term="rrdtool" /><category scheme="http://www.blogger.com/atom/ns#" term="cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="ec2" /><category scheme="http://www.blogger.com/atom/ns#" term="uls" /><category scheme="http://www.blogger.com/atom/ns#" term="spore" /><category scheme="http://www.blogger.com/atom/ns#" term="rtf" /><title>Recent Work on Various Open Source Projects</title><content type="html">&lt;div&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;Over the last few months, I've been doing lots of work on various open source projects. I've been so burried in them that I haven't blogged (or microblogged) much about them. So much has been happening, though, that I needed to take a break from the coding and communicate some of this :-)&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;txAWS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Over the last few months, &lt;a href="http://rbtcollins.wordpress.com/"&gt;Robert Collins&lt;/a&gt;, Thomas Herve, Jamshed Kakar and I have been putting lots of effort into improving cloud support in the async (Twisted) Python Amazon EC2 library. It's been a lot of fun to see that part of the library take shape and start getting production use from &lt;a href="http://canonical.com/landscape"&gt;Canonical&lt;/a&gt;. We have implemented the following functionality groups and their &lt;a href="http://docs.amazonwebservices.com/AWSEC2/2008-12-01/DeveloperGuide/"&gt;associated API&lt;/a&gt; methods:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Instances&lt;/li&gt;&lt;li&gt;Key Pairs&lt;/li&gt;&lt;li&gt;Security Groups&lt;/li&gt;&lt;li&gt;Elastic IPs&lt;/li&gt;&lt;li&gt;Availability Zones&lt;/li&gt;&lt;li&gt;EBS&lt;/li&gt;&lt;/ul&gt;There is a ticket for the following two groups of functionality, and branches in progress for both:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Images (&lt;a href="https://bugs.launchpad.net/txaws/+bug/461136"&gt;ticket #461136&lt;/a&gt; on &lt;a href="http://launchpad.net/"&gt;Launchpad&lt;/a&gt;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Image Attributes (&lt;a href="https://bugs.launchpad.net/txaws/+bug/461139"&gt;ticket #461139&lt;/a&gt; on &lt;a href="http://launchpad.net/"&gt;Launchpad&lt;/a&gt;)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Once those are merged, EC2 support in txAWS will be complete.&lt;br /&gt;&lt;br /&gt;As a bonus, we've added support for arbitrary endpoints and with that in place, have successfully tested &lt;span style="font-family:courier new;"&gt;txaws.ec2&lt;/span&gt; against &lt;a href="http://www.eucalyptus.com/open/"&gt;Eucalyptus&lt;/a&gt; clouds :-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;txJSON-RPC&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There's a new release of &lt;a href="https://launchpad.net/txjsonrpc"&gt;txJSON-RPC&lt;/a&gt; out now, downloadable from &lt;a href="http://pypi.python.org/pypi/txJSON-RPC/0.3"&gt;PyPI&lt;/a&gt;. Work on the next version has been a great deal of fun. What started out as a conversation on IRC with Terry Jones, ended up as spec-driven doctest work on trunk for implementing support for multiple versions of the JSON-RPC spec (pre-1.0, 1.0, and 2.0).&lt;br /&gt;&lt;br /&gt;With these changes in spec support, txJSON-RPC has really started to mature, and that's been fantastic. Even more, the jsonrpclib module that's included in txJSON-RPC (and can be used with non-Twisted projects) is getting spec version support as well.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SOOM in txULS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As some may know, one of my computing passions is &lt;a href="http://oubiwann.blogspot.com/2008/05/required-reading-ultra-large-systems.html?popular"&gt;ultra large-scale systems&lt;/a&gt;. After a phone conversation with Jamshed Kakar and some nice exchanges on the &lt;a href="http://www.python.org/community/sigs/current/"&gt;Python ULS-SIG&lt;/a&gt; mail &lt;a href="http://mail.python.org/pipermail/uls-sig/2009-September/thread.html"&gt;list&lt;/a&gt; with Alex Drahon, I started working on a set of coding experiments in self-organizing objects. The &lt;a href="https://docs.google.com/Doc?docid=0AVGwpdQOa6W2ZGd4bjdqM3BfNmNzbXI5NmNm&amp;amp;hl=en&amp;amp;pli=1"&gt;Google Doc&lt;/a&gt; informally outlines the various stages and goals.&lt;br /&gt;&lt;br /&gt;For now, the code is living in a &lt;a href="https://edge.launchpad.net/txuls/soom"&gt;txULS series&lt;/a&gt; on Launchpad. The reason for its inclusion in txULS is that ultimate goal of the SOOM (self-organizing object meshes) code is to produce an async API for building Twisted services that provide behaviours as outlined in the Google Doc (linked above).&lt;br /&gt;&lt;br /&gt;I would to emphasize the networking-library-agnostic nature of the ULS-SIG: Twisted comes up since I spend a lot of time with Twisted, but ever networking library is welcome. I'm personally interested in exploring (or watching other developers explore) various Stackless Python experiments in the ULS systems space.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;txSpore&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="https://launchpad.net/txspore"&gt;This project&lt;/a&gt; was a spontaneous effort resulting from an evening of code review when I first discovered the official &lt;a href="http://www.spore.com/comm/developer/python"&gt;Python API&lt;/a&gt; from EA/Maxis for the game Spore. It's been a blast and something that &lt;a href="http://radix.twistedmatrix.com/"&gt;Chris Armstrong&lt;/a&gt; and I have been working on together. The API is currently feature-complete, but Chris has some excellent ideas about improving usage as well as some additional API augmentations that will make life easier for game developers.&lt;br /&gt;&lt;br /&gt;Already more featureful and usable than the official Spore Python API, there are great things in store for this library. Chris has come up with several very cool demo ideas that take advantage of the new API and will push it to the limits. We're both pretty excited :-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Isomyr&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I love isometric games. I'm a freak for the classic look. One night about a month ago, Chris and I discovered &lt;a href="http://www.webalice.it/simon.gillespie/Isotope.html"&gt;Isotope&lt;/a&gt;, an isometric Python game engine by Simon Gillespie. It was last updated in 2005 at version 0.9, so I started working on a branch that could be released as 1.0. I never heard back from Simon after an inquiry for his permission to release as 1.0, so I forked the code to a new project: &lt;a href="https://launchpad.net/isomyr"&gt;Isomyr&lt;/a&gt;. I released the code rewrite work I had done to that point (plus some changes such as replacing some old code with Numpy) as &lt;a href="http://pypi.python.org/pypi/Isomyr/"&gt;0.1&lt;/a&gt;. At which point things just went nuts...&lt;br /&gt;&lt;br /&gt;Isomyr now has support for multiple worlds, customizable (per world) in-game time and calendars, and basic interactive fiction development. The latest chunk of code (that hasn't been pushed up to Launchpad yet) is adding support for general planetary simulation (e.g., axial title, varying daylight hours, seasons, and weather). As you might imagine, this has been a great deal of fun to work on!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PyRRD&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="https://launchpad.net/pyrrd"&gt;PyRRD&lt;/a&gt; has gotten some recent community love, with requests for a &lt;a href="http://groups.google.com/group/pyrrd-users"&gt;mail list&lt;/a&gt;, new developer-oritnted features, etc. Currently at version 0.0.7, the 0.1.0 release isn't to far away. Folks have been using trunk for a while, which added support for the RRDTool Python bindings back in March of this year. (PyRRD's focus has primarily been for users/developers who didn't have the RRDTool Python bindings installed).  In the next couple weeks or months, I expect that we'll be adding a few more features, and then preparing the new release.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PyRTF&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Another fixer-upper project, &lt;a href="https://launchpad.net/pyrtf"&gt;PyRTF&lt;/a&gt; (mirroed on Google code as &lt;a href="http://code.google.com/p/pyrtf-ng/"&gt;pyrtf-ng&lt;/a&gt;) has been on hiatus for a while, due to my diminished need to manipulate and interact with RTF files. However, a new developer has joined the project and the code-cleanup and unit test development now continues. Thanks &lt;span class="sprite person"&gt;Christian Simms!&lt;br /&gt;&lt;br /&gt;A while ago, Simon Cusack&lt;/span&gt; (&lt;span class="sprite person"&gt;the original author of &lt;a href="http://sourceforge.net/projects/pyrtf/"&gt;PyRTF&lt;/a&gt;) and I had some great discussions about the future development of PyRTF and his interest in merging the recent changes into trunk on SourceForge. I deferred on that action, wanting to wait until the code cleanup, unit tests, and API changes had been completed. With Christian's help, we may get there now :-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Wrap-up&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It's been about a year since I've been so active in open source development, and it feels &lt;span style="font-style: italic;"&gt;really&lt;/span&gt; good to be at it again :-) Being back in Colorado seems to have helped in subtle ways, but mostly it's been the increased interaction and interest from developers in the community that I can thank for my increased activity (and thus enjoyment). You guys are awesome. You're the reason for any code I produce.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-6420207114447015861?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/bXg69HFOUKI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/6420207114447015861/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=6420207114447015861" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/6420207114447015861?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/6420207114447015861?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/bXg69HFOUKI/recent-work-on-various-open-source.html" title="Recent Work on Various Open Source Projects" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/10/recent-work-on-various-open-source.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYCRXo4fip7ImA9WxNQEk0.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-5708442058182672922</id><published>2009-09-17T12:12:00.002-05:00</published><updated>2009-09-17T12:22:44.436-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-17T12:22:44.436-05:00</app:edited><title>PyCon 2010 Talks Neeed!</title><content type="html">&lt;div&gt;&lt;br /&gt;Hey folks,&lt;br /&gt;&lt;br /&gt;At my last count, we've only received 20 talks so far for PyCon 2010! There are only 14 days remaining for talk submissions... if you've had a great idea about a talk for PyCon, now's the time to make it happen!&lt;br /&gt;&lt;br /&gt;Below I've pasted some links that folks might find helpful. The first one has pretty much everything you need to know about submitting a talk for PyCon.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://us.pycon.org/2010/conference/proposals/"&gt;Proposal Submission Information &lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://us.pycon.org/2010/conference/helpforspeakers/"&gt;Help and Tips for Speakers&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-5708442058182672922?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/JUJU3VebQPM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/5708442058182672922/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=5708442058182672922" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5708442058182672922?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5708442058182672922?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/JUJU3VebQPM/pycon-2010-talks-neeed.html" title="PyCon 2010 Talks Neeed!" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/09/pycon-2010-talks-neeed.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04EQXsyfSp7ImA9WxNQEUs.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-9029394338732169097</id><published>2009-09-14T00:05:00.002-05:00</published><updated>2009-09-17T00:38:20.595-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-17T00:38:20.595-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="rest" /><category scheme="http://www.blogger.com/atom/ns#" term="games" /><category scheme="http://www.blogger.com/atom/ns#" term="services" /><category scheme="http://www.blogger.com/atom/ns#" term="twisted" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="spore" /><category scheme="http://www.blogger.com/atom/ns#" term="web" /><title>txSpore: Twisted Spore</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.flickr.com/photos/oubiwann/3918607932/sizes/o/"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 175px; height: 240px;" src="http://farm4.static.flickr.com/3422/3918607932_8fe9402c90_m.jpg" alt="" border="0" /&gt;&lt;/a&gt;I just had a delightful weekend of coding :-) I spent the past two days porting the &lt;a href="http://www.spore.com/comm/developer/python"&gt;Spore Python API&lt;/a&gt; to &lt;a href="http://twistedmatrix.com/"&gt;Twisted&lt;/a&gt;. You can now incorporate Spore data (from static XML as well as REST requests) into your non-blocking Python applications/games!&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This was a pretty easy task, really. The API just makes HTTP requests with &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;twisted.web.client.getPage&lt;/span&gt;. There was a little bit of work involved in creating object models for the XML, and some head-scratching for the error-catching &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;deferToThread&lt;/span&gt; unit test I tried to write (it's still buggy... need to figure that one out). Everything else was pretty much cake.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In fact, it was so much fun to kick back and write some playful code that I might overhaul the sync Python code as well and incorporate both into txSpore. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Do be aware, however, that the code still has some big improvements coming.  The first thing I want to hit is actually create a client object. Right now, the client module contains a series of functions (since state's not currently needed). However, I want to start doing some basic object caching in order to limit the number of requests made to &lt;a href="http://www.spore.com/"&gt;spore.com&lt;/a&gt; and increase the response time. That's the big item for 0.0.2. &lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt; 0.0.2 is now released!&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next I'd like to create some more demo apps that show off the API usage better. Right now, there's one demo (a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.tac&lt;/span&gt; file). All it does is ask for a user name, renders a user page, and then links to a user "Spore assets" page (that's the thumbnail image above).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One thing that might be fun to do is write a script that checks for the latest achievements and publishes them to various microblog/status sites with the Twisted PyngFM client :-)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There's a project page up on &lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt; for &lt;a href="https://launchpad.net/txspore"&gt;txSpore&lt;/a&gt;, and I've posted a &lt;a href="http://forum.spore.com/jforum/posts/list/42187.page"&gt;notice and some updates&lt;/a&gt; to the Spore developer forums. It's also been &lt;a href="http://pypi.python.org/pypi/txSpore/"&gt;published on PyPI&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enjoy!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-9029394338732169097?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/AmpmbCo8AMU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/9029394338732169097/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=9029394338732169097" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/9029394338732169097?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/9029394338732169097?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/AmpmbCo8AMU/txspore-twisted-spore.html" title="txSpore: Twisted Spore" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/09/txspore-twisted-spore.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIGR30-fyp7ImA9WxNRE0s.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-2245942595633363922</id><published>2009-09-07T17:47:00.004-05:00</published><updated>2009-09-07T18:02:06.357-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-07T18:02:06.357-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mac os x" /><category scheme="http://www.blogger.com/atom/ns#" term="mp3" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="windows" /><category scheme="http://www.blogger.com/atom/ns#" term="lame" /><category scheme="http://www.blogger.com/atom/ns#" term="mplayer" /><category scheme="http://www.blogger.com/atom/ns#" term="scripting" /><category scheme="http://www.blogger.com/atom/ns#" term="itunes" /><category scheme="http://www.blogger.com/atom/ns#" term="apple" /><title>Windows Media to MP3 Conversion for Mac OS X and Linux</title><content type="html">&lt;div&gt;&lt;br /&gt;For the past couple years, my girlfriend has been amazingly (astonishingly) patient about a whole slew of .wma files that we've got on the network drive... backups of her CD collection made when she was a Windows user. We managed to save them right before the computer died, but she hasn't been able to listen to them when she's booted into Ubuntu or Mac OS X.&lt;br /&gt;&lt;br /&gt;Late last month, after getting back from two weeks abroad, Marjorie said that she'd really like to have access to her music collection again (the CDs are cumbersome and stored away in boxes for our impending move back to Colorado). With that said, I did some digging around, and found some immediately helpful links (two years ago, a few google searches had turned up results that indicated too much effort was involved).&lt;br /&gt;&lt;br /&gt;I started out by trying a couple free Mac OS X GUI applications, but these ended up being quite horrible: either they did not offer the functionality I desired, they were buggy to the point of being unusable, or they rendered audio with unlistenable artifacts.&lt;br /&gt;&lt;br /&gt;In the end, I had to use &lt;a href="http://www.mplayerhq.hu/"&gt;mplayer&lt;/a&gt; and &lt;a href="http://lame.sourceforge.net/"&gt;lame&lt;/a&gt; in combination. After googling around and some trial and error, I discovered the combination of mplayer options that would successfully extract the audio data from .wma files and dump them as .wav files.&lt;br /&gt;&lt;br /&gt;I started with a shell script, but quickly changed to Python, since there were several locations for the .wma files, and none of them on nice paths.  I've used this script several times since then, when more .wma files were discovered, and have yet to encounter any issues in sound quality. Once nice-to-have would be to extract .wma metadata and save it in the new .mp3 files as id3 tags...&lt;br /&gt;&lt;br /&gt;Anyway, here's the code:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/usr/bin/python&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;subprocess&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# script configuration&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;darwin&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;MPLAYER_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;br /&gt;        &lt;span class="s"&gt;&amp;quot;/Applications/Non-Standard/Audio and Video&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class="s"&gt;&amp;quot;MPlayer OS X 2.app/Contents/Resources/mplayer.app/Contents/MacOS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="c"&gt;# lame was manually installed into /usr/bin&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;LAME_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/bin&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;linux2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;MPLAYER_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/usr/bin&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;LAME_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/bin&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;MPLAYER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MPLAYER_PATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;mplayer&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;LAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LAME_PATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;lame&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;DUMP_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;audiodump.wav&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;BACKUP_DIR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;wma&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;WORKING_DIR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/tmp&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_audio_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    Use mplayer to dump the audio contents of the .wma files as .wav files.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt; -nosound -vo null -vc dummy -af resample=44100 -aid 1 &amp;quot;&lt;/span&gt; &lt;br /&gt;               &lt;span class="s"&gt;&amp;quot;-ao pcm:waveheader &lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MPLAYER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;convert_wav_to_mp3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    Use lame to convert the .wav files to .mp3 files. Remove the raw .wav file&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    when done.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt; -b 256 -h &lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt; -o &lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unlink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;convert_wma_to_mp3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wma_filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    Given a .wma filename, get a filename for the new .mp3 file based on this,&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    convert the original to a .wav and then that to an .mp3 file.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;mp3_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;\.wma$&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;.mp3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wma_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;make_audio_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wma_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;convert_wav_to_mp3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DUMP_FILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mp3_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_wma_files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filenames&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    Given a list of filenames, check to see if any of them have the .wma file&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    extension. If so, return a true value; otherwise, a false one.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filenames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;.wma&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;convert_wma_files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    Walk a given file system directory and all its child directories in order&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    to find .wma files. If found, convert them to .mp3 files and backup the&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    originals.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subdirs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filenames&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# we don&amp;#39;t want to convert files that have already been converted&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;BACKUP_DIR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;continue&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# if there&amp;#39;s nothing to do, move on&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;has_wma_files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filenames&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;continue&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# define and create the backup dir, if it hasn&amp;#39;t been already&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;backup_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BACKUP_DIR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backup_dir&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backup_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filenames&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;            &lt;span class="c"&gt;# on mac os x samba shares, sometimes ._*.wma files are present;&lt;/span&gt;&lt;br /&gt;            &lt;span class="c"&gt;# skip these&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;                &lt;span class="k"&gt;continue&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;.wma&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;                &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Dumping audio for &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; ...&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;wma_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;wma_backup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backup_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;convert_wma_to_mp3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wma_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wma_filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wma_backup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WORKING_DIR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;convert_wma_files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Hope someone else finds this useful and their significant others don't have to wait 2 years for their music!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-2245942595633363922?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/djnGubz6-dY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/2245942595633363922/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=2245942595633363922" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/2245942595633363922?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/2245942595633363922?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/djnGubz6-dY/windows-media-to-mp3-conversion.html" title="Windows Media to MP3 Conversion for Mac OS X and Linux" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/09/windows-media-to-mp3-conversion.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUIHQnk_fCp7ImA9WxNRE0s.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-5533344872394339931</id><published>2009-09-07T17:20:00.003-05:00</published><updated>2009-09-07T17:45:33.744-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-07T17:45:33.744-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ping.fm" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="cgi twisted" /><category scheme="http://www.blogger.com/atom/ns#" term="scripting" /><title>Twisted Ping.fm Client</title><content type="html">&lt;div&gt;&lt;br /&gt;I just merged async (Twisted) support into the Python &lt;a href="http://ping.fm/"&gt;ping.fm&lt;/a&gt; library today and have just taken it for a test drive. I do love &lt;a href="http://twistedmatrix.com/"&gt;Twisted&lt;/a&gt; :-) The Twisted pyngfm API usage is identical to the synchronous API, with the usual exception of using deferreds and callbacks.&lt;br /&gt;&lt;br /&gt;Here's some example usage, the client I now use for command-line updates to Twitter, Identi.ca, Tumblr, Facebook, LinkedIn, Jaiku, and even Flickr (note that the keys are stored in an .ini-style config file):&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/usr/bin/python&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;ConfigParser&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SafeConfigParser&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;twisted.internet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;reactor&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pyngfm.client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PingFMAsyncClient&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;checkMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;140&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Message is too long! (&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; chars)&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getKeys&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;cred_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/etc/ping.fm.creds&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SafeConfigParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;cred_file&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;default&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;api-key&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;user_app_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;default&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;user-app-key&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_app_key&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pingIt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getErrorMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;finish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ignored&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;reactor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;pinger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PingFMAsyncClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;getKeys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;deferred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pinger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;status&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;deferred&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addErrback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;check_error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;deferred&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;check_result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;deferred&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addErrback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;check_error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;deferred&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finish&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;checkMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;pingIt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;reactor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There's another example in the &lt;a href="http://code.google.com/p/pyngfm/source/browse/trunk/README"&gt;README&lt;/a&gt; that iterates through the recents posts made to ping.fm. If you do manage to use it and come across any issues, be sure to &lt;a href="http://code.google.com/p/pyngfm/issues/list"&gt;file a ticket&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-5533344872394339931?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/UDL4gdUfevI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/5533344872394339931/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=5533344872394339931" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5533344872394339931?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5533344872394339931?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/UDL4gdUfevI/twisted-pingfm-client.html" title="Twisted Ping.fm Client" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/09/twisted-pingfm-client.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEMR34zfSp7ImA9WxJVGEk.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-9116460566170424019</id><published>2009-07-05T19:09:00.010-05:00</published><updated>2009-07-05T20:28:06.085-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-05T20:28:06.085-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="qa" /><category scheme="http://www.blogger.com/atom/ns#" term="human-resources" /><category scheme="http://www.blogger.com/atom/ns#" term="management" /><category scheme="http://www.blogger.com/atom/ns#" term="stross" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>Possible Directions in Human Resource Management</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;This afternoon, while having a nice soak in the tub, I got lost in a &lt;a href="http://en.wikipedia.org/wiki/Charles_Stross"&gt;Strossian&lt;/a&gt; reverie. Or perhaps it was more along the lines of one of his characters, rather than the author himself. Regardless, I was thinking about management styles in modern corporations... and ways in which one might improvise.&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I was only half paying attention, until the stream of thought actually started getting interesting. At which point I sat upright in the tub and started taking mental notes. Quickly showering off, I couldn't stop the flood of ideas, hoping to get to a written medium as soon as possible, lest they be forgotten.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I forget how the day-dreaming started... perhaps my usual: pick a random topic where I have some experience, and start playing with it. Run simulations and tweak parameters until there's nothing more to look at or some interesting permutation has popped up. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ah! Now I remember. I was thinking about the increasing importance of QA in software as more and more marketshare is gained. Not from the usual perspective ("we gotta make sure users don't see bugs, or our shit's gonna flop"), but rather as part of the original problem domain.  It's very common for open source projects to suffer from a lack of sex appeal when considering QA. QA is essential for success; just as important as the code itself. As such, there should be ways of making QA as interesting, engaging, understood, and respected as the act of programming.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That train of thought spawned a couple more pathways for exploration, but the one that ended up being the most interesting was pondering the QA-interest problem at a human resource management level. What would it take to get talented and skilled engineers who would normally gravitate towards some other field of expertise interested in QA instead? How flexible would a company have to be to start attracting for this and other positions as new needs arose due to new pressures? How could it do so by growing and adapting from the inside?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let's take these rather arbitrary initial conditions as part of a thought experiment following up on those questions:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;a company with a sufficient number of employees to support multiple departments&lt;br /&gt;&lt;/li&gt;&lt;li&gt;a highly intelligent, motivated workforce&lt;br /&gt;&lt;/li&gt;&lt;li&gt;flexible employees and teams, probably working in a distributed, remote environment&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Imagine with this sort of company that employees are not locked into teams, departments, divisions, etc. Let's say there is some mechanism which allows for an easy re-shuffling of talent throughout the company. For budgeting and reporting purposes, corporate structures would remain, but the individuals that performed specific tasks were granted much more expansive, organic freedoms when it came to projects and tasks.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From the individual's perspective, an employee could choose to work for and closely associate with whatever team they wanted to spend some time with, given of course, that this team could make use of the newly reallocated employee's particular skills and abilities. This is somewhat analogous to the geographical freedoms one has when working remotely: you can move anywhere in the world, to whichever time zone you prefer, whatever culture you want to enjoy, given that you can continue to work effectively. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Of course, checks and balances would have to be introduced. Otherwise, what's to prevent an employee from team-hopping, and never really getting any work done? Just playing social butterfly? Karma/experience points could be earned on per task, project, team, department, and division bases. Moving at any particular level to a different group would reset an employee's karma for that group and all other organizational units below it. For instance, changing to another department would zero out any team, project, and unfinished task karma that had been accumulated. Perhaps some of the patterns from role playing games could come in handy as sources of inspiration.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The ability to opt for a move could also be governed by an appropriate accumulation of karma points for a given organizational unit, to be determined at the discretion of that organizational unit. For example, hitting a certain karma "level" would allow one new movement opportunities. Obviously, in addition to having enough points, the target group would have to have a need and be willing to bring the requesting person on board.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Intuitively (i.e., without doing any research or checking sources), this feels like something modeled after biological systems, as opposed to the fairly static forms of systems organizations we currently see in many corporations. A company that was able to successfully implement such a human resource management approach could likely see additional, unexpected benefits. Biological systems tend to be well-suited to surviving shock, drastic changes, massive failures. We might see companies with longer-reaching vision, more innovation, less frequent employee turnover, and greater financial stability.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That aside, what appeals to me at a personal level is this: employees would be participating in their work at a new level. The management processes behind professional development would be opened up to them. Not only that, part of one's work would become a game with known rules and clearly defined markers for cumulative achievements. Rewards, though, would not be power-climbing, but rather lateral expansion and exploration. Deeper involvement in other areas of the company.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'd love to hear from folks who can recommend some good reading/research materials on this topic...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-9116460566170424019?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/qU-TMwsokGg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/9116460566170424019/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=9116460566170424019" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/9116460566170424019?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/9116460566170424019?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/qU-TMwsokGg/possible-directions-in-human-resource.html" title="Possible Directions in Human Resource Management" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/07/possible-directions-in-human-resource.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQNRn4_cSp7ImA9WxJWFUg.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-5433611678644581810</id><published>2009-06-20T22:01:00.006-05:00</published><updated>2009-06-20T23:09:57.049-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-20T23:09:57.049-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="icons" /><category scheme="http://www.blogger.com/atom/ns#" term="mac os x" /><category scheme="http://www.blogger.com/atom/ns#" term="hacks" /><category scheme="http://www.blogger.com/atom/ns#" term="command line" /><category scheme="http://www.blogger.com/atom/ns#" term="commands" /><category scheme="http://www.blogger.com/atom/ns#" term="apple" /><title>Mac OS X: Execute Shell Commands via Icon-Clicks</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm4.static.flickr.com/3393/3645070827_f425131ea6_o.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 240px; height: 167px;" src="http://farm4.static.flickr.com/3393/3645070827_de16ec1c9b_m.jpg" alt="" border="0" /&gt;&lt;/a&gt;My main development machine is a custom PowerBook running Ubuntu natively. I use it when I'm sitting on the couch, my office comfy chair, the futon, floor, etc. Every once in a while, though, I want to work at a desk from my 24" iMac. Just to mix it up a little. However, that box is my gaming and web-browsing machine: it runs Mac OS X and that's the way I want to keep it. So, if I'm going to do work on the iMac, I need to ssh into the machines that have the environments set up for development.&lt;br /&gt;&lt;br /&gt;In the course of an average day of writing code, I'll connect to anywhere from 1 to 5 remote machines open up 5-10 ssh sessions in a terminal to each machine. If I'm at the iMac, this get's tedious. Today, it got tedious enough for me to do somthing about it. Here's what I want: to click on a Terminal icon and have an ssh connection automatically established to the box I need to work on. This it pretty easy on Linux and Windows, but I had no idea how to accomplish this on a Mac until tonight.&lt;br /&gt;&lt;br /&gt;I thought I'd share my solution; others may like it... but I'm betting there are some pretty cool ways of doing this that didn't occur to me -- so feel free to share yours!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Profile Hack&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;From previous messing about with the &lt;span style="font-family:courier new;"&gt;open&lt;/span&gt; command, I knew I could open Terminal.app from the terminal:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;open -n &lt;span class="s2"&gt;"/Applications/Utilities/Terminal.app"&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;This got me part way there... if only I could dynamically execute a command upon login... so, yeah, I did something nasty:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;vi ~/.bash_profile&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;And then:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; ! -z &lt;span class="s2"&gt;"$REMOTE_CONNECTION"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;; &lt;span class="k"&gt;then&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;    &lt;/span&gt;ssh &lt;span class="nv"&gt;$REMOTE_CONNECTION&lt;/span&gt;&lt;br /&gt;&lt;span class="nv"&gt;    REMOTE_CONNECTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;.command Files&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I was stumped at that point, until some googling revealed a nifty trick I didn't know about:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a new file in your favorite editor, using the &lt;span style="font-family:courier new;"&gt;.command&lt;/span&gt; extension&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add the commands you want executed&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Save it and &lt;span style="font-family:courier new;"&gt;chmod 755&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Double-click it and enjoy&lt;/li&gt;&lt;/ul&gt;So here's what I added to &lt;span style="font-family:courier new;"&gt;rhosgobel.command&lt;/span&gt;:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;REMOTE_CONNECTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rhosgobel &lt;span class="se"&gt;\&lt;/span&gt;&lt;br /&gt;   open -n &lt;span class="s2"&gt;"/Applications/Utilities/Terminal.app"&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;The Obligatory Icon Tweak&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I then used the standard "Get Info" trick of icon copying: "Get Info" for Terminal.app, copy icon, "Get Info" for all my &lt;span style="font-family:courier new;"&gt;.command&lt;/span&gt; files, paste icon.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Usage&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm4.static.flickr.com/3381/3645070981_3a2dc3e58c_o.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: right; cursor: pointer; width: 240px; height: 115px;" src="http://farm4.static.flickr.com/3381/3645070981_edb963e877_m.jpg" alt="" border="0" /&gt;&lt;/a&gt;Now, I just click my "Shells" menu, choose the destination, and start working on that machine. A new window or new tab opened with that instance of Terminal.app will give me a new session to that server, without having to manually ssh into it -- this is even more convenient than having an icon to double-click!&lt;br /&gt;&lt;br /&gt;One bit of ugly I haven't figured out how to remove: when I open a shell to a remote server, there's another shell opened at the same time with a &lt;span style="font-family:courier new;"&gt;[Process completed]&lt;/span&gt; message.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-5433611678644581810?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/3UVtNvRO4tM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/5433611678644581810/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=5433611678644581810" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5433611678644581810?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5433611678644581810?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/3UVtNvRO4tM/mac-os-x-execute-shell-commands-via.html" title="Mac OS X: Execute Shell Commands via Icon-Clicks" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">8</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/06/mac-os-x-execute-shell-commands-via.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIHQnY8eyp7ImA9WxJWE0s.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-8018168738559081016</id><published>2009-06-18T12:40:00.006-05:00</published><updated>2009-06-18T16:28:53.873-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-18T16:28:53.873-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="txamqp-sinfonia" /><category scheme="http://www.blogger.com/atom/ns#" term="amqp" /><category scheme="http://www.blogger.com/atom/ns#" term="twisted" /><category scheme="http://www.blogger.com/atom/ns#" term="erlang" /><category scheme="http://www.blogger.com/atom/ns#" term="txamqp" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>A Sinfonia on Messaging with txAMQP, Part III</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A Sinfonia on Messaging:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp.html"&gt;The Voice of Business&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp-part.html"&gt;The Voice of Architecture&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp-part_18.html"&gt;A RabbitMQ and txAMQP Interlude&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Before we play our third voice in this three-part invention, we need to do some finger exercises. In particular, let's take a look at the concepts and tools we'll be using to implement and run our kilt store messaging scenario.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Messaging&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.rabbitmq.com/faq.html#background"&gt;RabbitMQ FAQ&lt;/a&gt; has this to say about messaging:&lt;br /&gt;&lt;b&gt; &lt;/b&gt;        &lt;blockquote&gt;Unlike databases which manage data at rest,        messaging is used to manage data in motion.  Use messaging to        communicate between and scale applications, within your enterprise,        across the web, or in the cloud.&lt;/blockquote&gt; Paraphasing Wikipedia's &lt;a href="http://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol"&gt;entry on AMQP&lt;/a&gt;:&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;The AMQ protocol is for managing the flow of messages across an enterprise's business systems. It is middleware to provide a point of rendezvous between backend systems, such as data stores and services, and front end systems such as end user applications.&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;AMQP  Essentials&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;AMQP is a protocol for middleware servers -- servers that accept, route, and buffer messages. The &lt;a href="http://jira.amqp.org/confluence/download/attachments/720900/amqp0-8.pdf?version=1"&gt;AMQP specification&lt;/a&gt; defines messaging server &lt;a href="http://www.lego.com/"&gt;LEGO&lt;/a&gt; blocks that can be combined in various ways and numbers, achieving any manner of messaging goals, whose final forms are as diverse as the combinations of the components.&lt;br /&gt;&lt;br /&gt;For the visually inclined, below is a simple diagram of the AMQ protocol. I've put multiple virtual hosts in the diagram to indicate support for multiple server "segments" (domains in the most general sense). There could just as easily be multiple exchanges and queues in each virtual host, as well. Likewise for publishers and consumers.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm4.static.flickr.com/3349/3634123474_298f4f3e6e_o.png"&gt;&lt;img style="border: 0pt none ; margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://farm4.static.flickr.com/3349/3634123474_62b988082d.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I highly recommend reading &lt;a href="http://jira.amqp.org/confluence/download/attachments/720900/amqp0-8.pdf?version=1"&gt;the spec&lt;/a&gt;: it is exceedingly clear at both intuitive and practical levels. To better understand the diagram above, be sure to read the definition of terms at the beginning as well as the subsections in 2.1 about the messaging queue and the exhange. Don't miss the message life-cycle section either -- you'll be reminded of circuitry diagrams and electronics kits, which is what AMQP really boils down to :-)&lt;br /&gt;&lt;br /&gt;The Advanced Messaging Queing Protocol specifies that the the protocol can be used to create exchanges, message queues, chain them together, and do all of this dynamically.  Any piece of code that has access to an API for your AMQP server can connect to it and communicate with other code -- using or creating simple messaging patterns or deeply complex ones. And everything in between.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;RabbitMQ Quickstart&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href="http://www.rabbitmq.com/"&gt;RabbitMQ&lt;/a&gt; is a messaging system written in &lt;a href="http://erlang.org/"&gt;Erlang&lt;/a&gt;, but in particular, it is an implementation of AMQP. The RabbitMQ web site provides documentation on &lt;a href="http://www.rabbitmq.com/install.html"&gt;installing&lt;/a&gt; and &lt;a href="http://www.rabbitmq.com/admin-guide.html"&gt;administering&lt;/a&gt; the messaging server. I run mine on Ubuntu, but since I've got a custom Erlang install, I didn't install the package (I dumped the source in &lt;span style="font-family:courier new;"&gt;/usr/lib/erlang/lib&lt;/span&gt;). To participate in the code play for this blog series, you'll need to install RabbitMQ.&lt;br /&gt;&lt;br /&gt;Once you've got it installed, you'll need to start it up. If you've used something like Ubuntu's apt-get to install RabbitMQ, starting it up is as simple as this:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;sudo rabbitmq-server&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;If you've got a custom setup like mine, you might need to do something like this (changing the defaults as needed):&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/lib/erlang/lib/rabbitmq-server-1.5.5/&lt;br /&gt;&lt;span class="nv"&gt;BIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;/scripts/rabbitmq-server&lt;br /&gt;&lt;br /&gt;&lt;span class="nv"&gt;RABBITMQ_MNESIA_BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;/mnesia &lt;span class="se"&gt;\&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;RABBITMQ_LOG_BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/log/rabbitmq &lt;span class="se"&gt;\&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;RABBITMQ_NODE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5672 &lt;span class="se"&gt;\&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;RABBITMQ_NODENAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rabbit &lt;span class="se"&gt;\&lt;/span&gt;&lt;br /&gt;  &lt;span class="nv"&gt;$BIN&lt;/span&gt; &amp;amp;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A txAMQP Example&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now that we've got a messaging server running, but before we try to implement out kilt store scenarios, let's take a quick sneak peek at txAMQP with a simple example having the following components:&lt;br /&gt;&lt;ul&gt;&lt;li style="color: rgb(102, 0, 0);"&gt;a RabbitMQ server&lt;/li&gt;&lt;li style="color: rgb(0, 0, 153);"&gt;a txAMQP producer&lt;/li&gt;&lt;li style="color: rgb(102, 0, 204);"&gt;a txAMQP consumer&lt;/li&gt;&lt;/ul&gt;From reading the spec, we have a general sense of what needs to happen in our &lt;span style="color: rgb(0, 0, 153);"&gt;producer&lt;/span&gt;. It needs to:&lt;br /&gt;&lt;ul style="color: rgb(0, 0, 153);"&gt;&lt;li&gt;connect to the RabbitMQ server&lt;/li&gt;&lt;li&gt;open a channel&lt;br /&gt;&lt;/li&gt;&lt;li&gt;send a message down the channel&lt;/li&gt;&lt;/ul&gt;Similarly, our reading lets us anticipate the needs of the &lt;span style="color: rgb(102, 0, 204);"&gt;consumer&lt;/span&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li style="color: rgb(102, 0, 204);"&gt;connect to the RabbitMQ server&lt;/li&gt;&lt;li style="color: rgb(102, 0, 204);"&gt;open a channel&lt;br /&gt;&lt;/li&gt;&lt;li style="color: rgb(102, 0, 204);"&gt;create an exchange and message queue on the RabbitMQ server, binding the two&lt;/li&gt;&lt;li style="color: rgb(102, 0, 204);"&gt;check for in-coming messages and consume them&lt;/li&gt;&lt;/ul&gt;I have refactored some examples that the author of txAMQP &lt;a href="http://blogs.digitar.com/jjww/2009/01/rabbits-and-warrens/#comment-681"&gt;created&lt;/a&gt; and I've put them up &lt;a href="http://bazaar.launchpad.net/%7Eoubiwann/adytum-collection/Docs/files/head%3A/messaging/amqp/twisted/producer-consumer/"&gt;here&lt;/a&gt;. Once you download the three Python files (and the spec file, one directory level up), you can run them in two separate terminals. In terminal 1, start up the consumer:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;python2.5 consumer amqp0-8.xml&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;In terminal 2, fire off a message:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;python2.5 producer amqp0-8.xml &lt;span class="se"&gt;\&lt;/span&gt;&lt;br /&gt; &lt;span class="s2"&gt;&amp;quot;producer-to-consumer test message 1&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;After running the producer with that message, you should see the same text rendered in the consumer terminal window. You can also fire the message off first, then start up the consumer. The message is sitting in a queue on your RabbitMQ instance and will be available to your consumer as soon as it connects.&lt;br /&gt;&lt;br /&gt;Now that you see evidence of this working, you're going to be curious about the code :-) Go ahead and &lt;a href="http://bazaar.launchpad.net/%7Eoubiwann/adytum-collection/Docs/files/head%3A/messaging/amqp/twisted/producer-consumer/"&gt;take a look&lt;/a&gt;. There are lots of comments in the code that give hints as to what's going on and the responsibilities that are being addressed.&lt;br /&gt;&lt;br /&gt;If you are familiar with Twisted, you may have noted that the code looks a little strange. If you're not, you may have noticed that the code looks normal, with the exception of extensive yield usage and the &lt;span style="font-family:courier new;"&gt;inlineCallbacks&lt;/span&gt; decorator. Let me give a quick overview:&lt;br /&gt;&lt;br /&gt;Ordinarily, Twisted-based libraries and applications use the asynchronous &lt;a href="http://twistedmatrix.com/projects/core/documentation/howto/defer.html"&gt;Twisted deferred idiom&lt;/a&gt;. However, there's a little-used bit of syntactic sugar in Twisted (for Python 2.5 and greater)  that lets you write async code that looks like regular, synchronous code. This was briefly explored &lt;a href="http://blog.mekk.waw.pl/archives/14-Twisted-inlineCallbacks-and-deferredGenerator.html"&gt;in a post&lt;/a&gt; on another blog last year. The Twisted API docstring for &lt;span style="font-family:courier new;"&gt;inlineCallbacks&lt;/span&gt; has a &lt;a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.defer.html#inlineCallbacks"&gt;concise example&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Briefly, the difference is as follows. In standard Twisted code, we assign a deferred-producing function's or method's return value to a variable and then call that deferred's methods (e.g., &lt;span style="font-family:courier new;"&gt;addCallback&lt;/span&gt;):&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;someFunc&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;someAsyncCall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_someCallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anotherAsyncCall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_anotherCallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;With &lt;span style="font-family:courier new;"&gt;inlineCallbacks&lt;/span&gt;, you decorate your function (or method) and yield for every deferred-producing call:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nd"&gt;@inlineCallbacks&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;someFunc&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;result1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;someAsyncCall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="c"&gt;# work with result; no need for a callback&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;anotherAsyncCall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="c"&gt;# work with second result; no need for a callback&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Visually, this flows as regular Python code. However, know that the &lt;span style="font-family:courier new;"&gt;yield&lt;/span&gt;s prevent the function from blocking and execution resumes as soon as the deferred has a result (which is assigned to the left-hand side). Since this latter idiom is used in txAMQP, I use it in the examples as well.&lt;br /&gt;&lt;br /&gt;Next, we finally reach our implementation!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;References&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.enterpriseintegrationpatterns.com/Chapter1.html"&gt;&lt;/a&gt;The &lt;a href="http://jira.amqp.org/confluence/download/attachments/720900/amqp0-8.pdf?version=1"&gt;AMQP Spec&lt;/a&gt;&lt;/li&gt;&lt;li&gt;The &lt;a href="https://launchpad.net/txamqp"&gt;async Python library&lt;/a&gt; for AMQP&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.rabbitmq.com/"&gt;RabbitMQ&lt;/a&gt;&lt;/li&gt;&lt;li&gt;A &lt;a href="http://app.arat.us/blog/?p=38"&gt;txAMQP example&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-8018168738559081016?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/Xi5GBHBooNg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/8018168738559081016/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=8018168738559081016" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/8018168738559081016?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/8018168738559081016?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/Xi5GBHBooNg/sinfonia-on-messaging-with-txamqp-part_18.html" title="A Sinfonia on Messaging with txAMQP, Part III" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp-part_18.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4HQnYzcSp7ImA9WxJWE0k.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-4613470270539237100</id><published>2009-06-11T22:03:00.008-05:00</published><updated>2009-06-18T12:58:53.889-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-18T12:58:53.889-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="txamqp-sinfonia" /><category scheme="http://www.blogger.com/atom/ns#" term="amqp" /><category scheme="http://www.blogger.com/atom/ns#" term="architecture" /><category scheme="http://www.blogger.com/atom/ns#" term="messaging" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>A Sinfonia on Messaging with txAMQP, Part II</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A Sinfonia on Messaging:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp.html"&gt;The Voice of Business&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp-part.html"&gt;The Voice of Architecture&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp-part_18.html"&gt;A RabbitMQ and txAMQP Interlude&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;After writing the last blog post, I found a &lt;a href="http://www.enterpriseintegrationpatterns.com/"&gt;fantastic site&lt;/a&gt; that focuses on messaging in the enterprise. I have really enjoyed the big-picture overview I get from some of the Martin Fowler signature books in this series, so I ordered &lt;a href="http://amazon.com/o/asin/0321200683/ref=nosim/enterpriseint-20"&gt;a copy of this one&lt;/a&gt; too.&lt;br /&gt;&lt;br /&gt;On the web site, the authors give a nice example for messaging integration in &lt;a href="http://www.enterpriseintegrationpatterns.com/Chapter1.html"&gt;Chapter 1&lt;/a&gt;. They provide a more detailed, supplier-version of the kilt store (we're doing "manufacturing" as opposed to distribution) with "Widget-Gadget Corp", but the basic principles are the same. I highly recommend reading that entire page. I used it as the basis for much of this post.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Business Process Overview&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At a top-level, we have the following business process for MacGrudder's kilt store:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm3.static.flickr.com/2468/3616902471_976fb0bbc7_o.png" style="border: medium none ;" /&gt;&lt;br /&gt;&lt;br /&gt;These are represented by a sales guy or a web store, a third-party billing service, MacGrudder, and a third-party shipping service.&lt;br /&gt;&lt;br /&gt;Up until now, the sale process could be either a user deciding to buy something in the online store or the sales guy engaging with a customer. Both generated orders; neither shared resources. The web app interfaced with the payment gateway operating by billing/shipping guy. The sales guy had to call in his orders to the billing/shipping guy. Once orders were charged/approved, a printout was handed to MacGrudder, who then created the ordered kilt. Once completed, he'd set it aside for shipping guy to come box it up and slap a label on it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Voice of Architecture&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We're now ready to weave in the second voice of our &lt;a href="http://en.wikipedia.org/wiki/Inventions_and_Sinfonias_%28J._S._Bach%29"&gt;three-part invention&lt;/a&gt;. MacGrudder's original infrastructure consists of silos of applications, functionality, data, and process. We want to interconnect these separated areas in order to reduce long-term overhead incurred by redundant components and data. Practically, we want to see the following changes:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm4.static.flickr.com/3662/3618180544_e906571e0f_o.png"&gt;&lt;img style="border: 0pt none ; margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 240px; height: 137px;" src="http://farm4.static.flickr.com/3662/3618180544_b5ca784ed1_m.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:85%;"&gt;Unified orders&lt;/span&gt;&lt;/span&gt;: at the end of the sales process, there should be one abstraction of the "order", regardless if the source was the web store, a phone call, or the sales guy. The order abstraction will be a message (or series of messages, for orders with multiple items; we'll be addressing only the simple case of a single item).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm3.static.flickr.com/2441/3618361660_7b40df1bf9_o.png"&gt;&lt;img style="border: 0pt none ; margin: 0pt 10px 10px 0pt; float: right; cursor: pointer; width: 240px; height: 137px;" src="http://farm3.static.flickr.com/2441/3618361660_ca06012474_m.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Unified validation and billing&lt;/span&gt;&lt;/span&gt;: at the end of the order creation process, there should be a validated order or an invalid order (e.g., if there were insufficient funds). At the end of the billing process, there should be an approved order that has be paid for via a single means (e.g., a single payment gateway, without bothering billing guy for manual entry). Additionally, once an order has been validated, messages should be sent to other components in the system.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm4.static.flickr.com/3299/3618662706_574433f920_o.png"&gt;&lt;img style="border: 0pt none ; margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 240px; height: 137px;" src="http://farm4.static.flickr.com/3299/3618662706_d0aebb491b_m.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;Unified status&lt;/span&gt;&lt;/span&gt;: at the end of the manufacturing process, both the shipping guy and customers should be aware that the product has been completed and is ready to be sent: the shipping guy can connect to our messaging system (probably via a service) and the customer can be notified by email or by checking the order status in the web kilt store.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the next installment, we will finally start looking at the code. We'll look at the "unified orders" messaging solution after covering some basics with RabbitMQ and Twisted integration, and then see how far we get with implementation details and descriptions. Unified validation, billing, and status might have to be pushed to additional posts.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;References&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Enterprise Integration Patterns, &lt;a href="http://www.enterpriseintegrationpatterns.com/Chapter1.html"&gt;Chapter 1&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.soa-in-practice.com/"&gt;SOA in Practice&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-4613470270539237100?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/f3QMwXP6OwI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/4613470270539237100/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=4613470270539237100" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/4613470270539237100?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/4613470270539237100?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/f3QMwXP6OwI/sinfonia-on-messaging-with-txamqp-part.html" title="A Sinfonia on Messaging with txAMQP, Part II" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp-part.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4ARng8eCp7ImA9WxJWE0k.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-8225971593034234909</id><published>2009-06-07T16:22:00.005-05:00</published><updated>2009-06-18T12:59:07.670-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-18T12:59:07.670-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="txamqp-sinfonia" /><category scheme="http://www.blogger.com/atom/ns#" term="amqp" /><category scheme="http://www.blogger.com/atom/ns#" term="twisted" /><category scheme="http://www.blogger.com/atom/ns#" term="uls" /><category scheme="http://www.blogger.com/atom/ns#" term="messaging" /><category scheme="http://www.blogger.com/atom/ns#" term="soa" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>A Sinfonia on Messaging with txAMQP, Part I</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A Sinfonia on Messaging:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp.html"&gt;The Voice of Business&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp-part.html"&gt;The Voice of Architecture&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp-part_18.html"&gt;A RabbitMQ and txAMQP Interlude&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Prelude&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A complete messaging solution is a &lt;a href="http://en.wikipedia.org/wiki/Inventions_and_Sinfonias_%28J._S._Bach%29"&gt;three-part invention&lt;/a&gt; of business need, architecture, and implementation. In its final form, these three voices blend in harmony, with each one taking a dominant role depending upon which part of the solution one examines.&lt;br /&gt;&lt;br /&gt;Neither have I the ability nor skill to seamlessly weave three concepts together while clearly explaining their roles. Therefore, I will separate out the voices from each other and leave it as an exercise for the reader to construct an application and practice the principles involved, thus experiencing well-earned contrapuntal pleasures first-hand.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As computing and data exchange systems increased in complexity over the past 30 years, so has the need for improvements -- and where possible, simplifications. Some of these efforts have been focused on decentralization of communications (shared, distributed load) and decoupling of messaging from applications (removing redundancy and increasing delivery speed/throughput). The first steps towards this were made in the 1990s with explorations in "middleware" application universe.&lt;br /&gt;&lt;br /&gt;Messaging, as we now refer to it in the industry, arouse from those middleware adventures: out of the business drive to refactor old software as new services to wider, more sophisticated audiences. With many new services replacing a single, monolithic application, formal and well-architected solutions were needed for creating, editing, and deleting shared data.&lt;br /&gt;&lt;br /&gt;From &lt;a href="http://en.wikipedia.org/wiki/Message_Oriented_Middleware"&gt;Wikipedia&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;Message-oriented middleware (MOM) is infrastructure focused on message sending that increases the interoperability, portability, and flexibility of an application by allowing the application to be distributed over multiple heterogeneous platforms. It reduces the complexity of developing applications that span multiple operating systems and network protocols by insulating the application developer from the details of the various operating system and network interfaces.&lt;/blockquote&gt;AMQP (Advanced Message Queuing Protocol) is one of these protcols.&lt;br /&gt;&lt;br /&gt;In a &lt;a href="http://blogs.computerworld.com/new_ubuntu_linux_server_is_for_business"&gt;recent blog post&lt;/a&gt; about Ubuntu as a business server, Vaughan-Nichols provides evidence for Ubuntu's and Canonical's commitment to enterprise, saying "... the new [version of] Ubuntu also includes AMQP [...] support. AMQP is an important set of middleware and SOA [...] protocols."&lt;br /&gt;&lt;br /&gt;AMQP has demonstrated itself as a compelling protocol for messaging solutions, even to the point of being included in two Linux distributions. The code included in this blog series is &lt;a href="https://launchpad.net/txamqp"&gt;txAMQP&lt;/a&gt;, an asynchronous Python AMQP library built with &lt;a href="http://twistedmatrix.com/"&gt;Twisted&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Note that &lt;a href="http://twistedmatrix.com/pipermail/twisted-python/2008-September/018330.html"&gt;last year&lt;/a&gt; I had planned to write a blog series on messaging with &lt;a href="http://metajack.im/2008/09/04/get-twisted-on-xmpp---the-future-of-twisted-words/"&gt;Twisted and XMPP&lt;/a&gt;, but was unable to as a result of time constraints. These days, I'm working with AMQP instead of XMPP, but I still hold some hope that I'll be able to write an anolog for this series from the perspective of XMPP.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Voice of Business&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Dipping into the future, &lt;a href="http://jira.amqp.org/confluence/display/AMQP/AMQP+1-0+Business+Requirements"&gt;one of the goals&lt;/a&gt; for AMQP as developed by a special interest group is the following:&lt;br /&gt;&lt;blockquote&gt;Decentralized, Locally Governed Federated Mesh of AMQP Brokers with standardized Global Addressing. The killer application for AMQP is transacted secure business messages between corporations - e.g. send a banking confirmation message to confirms@bank.com [...]&lt;/blockquote&gt;I find this rather exciting due to my interest in &lt;a href="http://oubiwann.blogspot.com/search/label/uls"&gt;ultra large-scale systems&lt;/a&gt;; scenarios like the one described above are the seeds for tomorrow's ULS systems :-)&lt;br /&gt;&lt;br /&gt;For now, though, let's look at a more immediate use for AMQP: a messaging protocol for shared services between departments in a small store. In this exercise, the voice of business is the primary melody; everything else (architecture and implementation) is done in support of this theme.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;An Example&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Fhionnlaidh MacGrudder creates hand-made kilts to order. He's got a sales guy who works with movie costume design shops and the like. He's got a web girl who wrote and maintains a custom  store front app. He's got a friend who does shipping and billing for him (as well as some other local Glen Orchy artisans). Until now, these three business "groups" associated with the kilt shop have been maintaining their own records, sometimes copying and updating them manually from each others' various export files.&lt;br /&gt;&lt;br /&gt;Fhionnlaidh's niece Fíona is programmer, business student, and is dating shipping guy's son. Horrified by the inefficiencies in her uncle's business processes (and tired of her boyfriend's father's complaints), she has proposed the following:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;sales guy will maintain customer contact info offer this as a service to the store and billing&lt;/li&gt;&lt;li&gt;the web store will dynamically update displayed data when sales guy changes it&lt;/li&gt;&lt;li&gt;the CRM will dynamically update displayed data when a web store customer updates their info&lt;/li&gt;&lt;li&gt;MacGrudder will have a new web page he goes to where all pending orders are presented with their full details; changes can be updated by a customer in real-time until MacGrudder has started working on the order&lt;br /&gt;&lt;/li&gt;&lt;li&gt;billing/shipping  guy will be notified instantly as soon as MacGrudder marks a kilt order as completed&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;This setup has the following benefits:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Contacts will be maintained in a single data store&lt;/li&gt;&lt;li&gt;There is zero latency between customer-driven updates and sales guy-driven updates&lt;/li&gt;&lt;li&gt;Customers have increased post-purchase flexibility with their orders&lt;/li&gt;&lt;li&gt;Shipping guy can plug into MacGudder's messaging and be notified when packages are ready for pickup&lt;/li&gt;&lt;li&gt;Everyone has more time for buttered scones and tea (especially shipping guy, who will no longer be making unneeded trips down the glen)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The following changes will be made to the current software:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Contacts will need to be merged into the CRM&lt;/li&gt;&lt;li&gt;A read/write data service for the contacts will need to be created&lt;/li&gt;&lt;li&gt;The CRM front-end will need to be upgraded to an AJAX-enabled version&lt;/li&gt;&lt;li&gt;The web store app will need to be updated to support AJAX&lt;/li&gt;&lt;li&gt;A new page will be created which displays the status of all orders and allows MacGrudder to change an order from "pending" to "in-progress" to "completed"&lt;/li&gt;&lt;li&gt;The current "new order" email notification code in the web app will need to be changed so that it uses the same messaging as MacGrudder's status page&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A new service needs to be created for shipping guy so that he can choose to be notified about pending pickups by email or he can check a web page or even make a query directly to the service, thus preventing unnecessary trips to MacGrudder's isolated little shop&lt;br /&gt;&lt;/li&gt;&lt;li&gt;After all the work is done, somone's going to need to order more scones&lt;/li&gt;&lt;/ul&gt;This example is not meant to fully justify messaging for businesses, but rather to provide a simple use case for which we can write some simple (and less than robust) code. It is a toy, but a conceptually useful one with a solid, concrete foundation.&lt;br /&gt;&lt;br /&gt;In the next installment, we'll review the business process (with diagrams!) and the explore the architecture of the system, before and after. Another post will take that architecture and combine it with MacGrudder's already extant infrastructure, reusing as much as possible. With that in place, we will have the opportunity to look at some RabbitMQ basics and some actual txAMQP code.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;References&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.soa-in-practice.com/"&gt;SOA in Practice&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Message_Oriented_Middleware"&gt;Message-oriented middleware&lt;/a&gt; on Wikipedia&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol"&gt;AMQP&lt;/a&gt; on Wikipedia&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The &lt;a href="http://jira.amqp.org/confluence/download/attachments/720900/amqp0-8.pdf?version=1"&gt;AMQP Spec&lt;/a&gt;&lt;/li&gt;&lt;li&gt;A &lt;a href="http://barryp.org/software/py-amqplib/"&gt;synchronous Python library&lt;/a&gt; for AMQP&lt;/li&gt;&lt;li&gt;The &lt;a href="https://launchpad.net/txamqp"&gt;async Python library&lt;/a&gt; for AMQP&lt;/li&gt;&lt;li&gt;A &lt;a href="http://app.arat.us/blog/?p=38"&gt;txAMQP example&lt;/a&gt;&lt;/li&gt;&lt;li&gt;An &lt;a href="http://blogs.digitar.com/jjww/2009/01/rabbits-and-warrens/"&gt;intro to messaging and py-amqplib&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-8225971593034234909?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/NKiCEOnzXe0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/8225971593034234909/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=8225971593034234909" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/8225971593034234909?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/8225971593034234909?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/NKiCEOnzXe0/sinfonia-on-messaging-with-txamqp.html" title="A Sinfonia on Messaging with txAMQP, Part I" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/06/sinfonia-on-messaging-with-txamqp.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUABSXk8eSp7ImA9WxJQFU0.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-2822188360640178600</id><published>2009-05-28T05:45:00.001-05:00</published><updated>2009-05-28T05:49:18.771-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-28T05:49:18.771-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="after-cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>After the Cloud: Epilogue</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;After the Cloud:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-prelude.html"&gt;Prelude&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-so-far.html"&gt;So Far&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-new-big.html"&gt;The New Big&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-to-atomic-computation-and.html"&gt;To Atomic Computation and Beyond&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-open-heaps.html"&gt;Open Heaps&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-heaps-of-cash.html"&gt;Heaps of Cash&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-epilogue.html"&gt;Epilogue&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Though wildly exciting to imagine a future of computing where ubiquitous devices are more deeply integrated into the infrastructure we use to power our applications, the real purpose of these posts has been to explore possibilities.&lt;br /&gt;&lt;br /&gt;Let's have crazy thoughts. Let's build upon them, imagining ways in which they &lt;span style="font-style: italic;"&gt;could&lt;/span&gt; become a reality. Let's not only munch on the regular diet of the technical "now"; let's plant seeds in many experiments for the future.&lt;br /&gt;&lt;br /&gt;This post is about thinking of small, mobile devices and cloud computing. But it's also a rough template. Let's do the same thing for a the desktop: how might it evolve? Where will users be spending their time? Let's do it for the OS and the kernel: what radical changes can we envision there? The technology behind health care. Education. Our new patterns of behaviour in a constantly changing world. All of these and more deserve our attention.&lt;br /&gt;&lt;br /&gt;The more we discuss such topics in a public forum, the more thought will be given to them. Such increased awareness and attention might spark the light of innovation years ahead of time,  and do so in the context of an open exchange of ideas. Let's have Moore's law for the improved quality of life with regard to technology; let's take it out of the chip and into our lives.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-2822188360640178600?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/N5wOrAju1f4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/2822188360640178600/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=2822188360640178600" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/2822188360640178600?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/2822188360640178600?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/N5wOrAju1f4/after-cloud-epilogue.html" title="After the Cloud: Epilogue" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/05/after-cloud-epilogue.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYCR3syfSp7ImA9WxJQEEs.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-1311826067334300225</id><published>2009-05-23T01:25:00.006-05:00</published><updated>2009-05-23T02:36:06.595-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-23T02:36:06.595-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu" /><category scheme="http://www.blogger.com/atom/ns#" term="canonical" /><category scheme="http://www.blogger.com/atom/ns#" term="freedom" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>Canonical's Vision</title><content type="html">&lt;div&gt;&lt;br /&gt;Canonical's most recent AllHands meeting finished last night (this morning, really... I can't believe I got up at 7:30am), and I'm somewhat at a loss for words. In a good way.&lt;br /&gt;&lt;br /&gt;But I'll try anyway :-)&lt;br /&gt;&lt;br /&gt;As someone who was highly skeptical of the validity of Canonical's business model prior to working here, I can say that not only do I not doubt our ability to be a hugely successful company, but I am &lt;span style="font-style: italic;"&gt;deeply&lt;/span&gt; committed to that success. Before AllHands, Canonical had earned my respect and loyalty through the consistent support and care of its employees. After AllHands, I have a much greater practical, hands-on understanding of Canonical's strategies and the various projects involved in creating a reality of success.&lt;br /&gt;&lt;br /&gt;What's more, though, is the completeness of my belief in the people and the vision. This is thanks to the massive exposure we've had during AllHands to the collective vision; the team projects; all the individuals with amazing histories, skills, unbelievable talent and ability to deliver; and most of all, the dedication that each employee of Canonical has to truly making the world a better place for anyone who depends upon technology.&lt;br /&gt;&lt;br /&gt;Ubuntu is free, and that's great. But Canonical needs to be a huge commercial success if its free OS distribution is going to have the power to transform the market and thus people's lives. This AllHands has given me a complete picture of how that will happen: we're all working on a different part of this puzzle, and we're all making it happen.&lt;br /&gt;&lt;br /&gt;Success in the marketplace &lt;span style="font-style: italic;"&gt;is&lt;/span&gt; crucial. Not because of greed or the lust for power, but because we live in a world where value is exchanged. As part of that ecosystem, we want to bring the greatest value to the people. This is not "selling out"; it's &lt;span style="font-style: italic;"&gt;selling&lt;/span&gt;. This does not give away a user's freedom; it helps guarantee its continued safety in a competitive, capitalist society.&lt;br /&gt;&lt;br /&gt;If we want anyone to embrace Ubuntu instead of a non-free OS -- without asking our users to sacrifice &lt;span style="font-style: italic;"&gt;anything&lt;/span&gt; -- we're going to need to make very serious changes in design, usability, integration, and stability. To do this in a clean, unified manner really only comes with a significant investment of time, direction, and capital. Due to the seriousness of Canonical's altruistic vision, as we generate this capital, we're making the dream come true for the world.&lt;br /&gt;&lt;br /&gt;At AllHands, I've seen designs that will seriously challenge Apple. I've seen a usability team's plans for true computing goodness. I've seen revenue models that have made my jaw drop. I've seen glimpses of the bright future.&lt;br /&gt;&lt;br /&gt;And baby, it's exciting as hell.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-1311826067334300225?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/pl_HGDoV_eo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/1311826067334300225/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=1311826067334300225" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/1311826067334300225?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/1311826067334300225?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/pl_HGDoV_eo/canonicals-vision.html" title="Canonical's Vision" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/05/canonicals-vision.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUAMR308fip7ImA9WxJQFU0.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-6433984318269678958</id><published>2009-05-18T11:43:00.002-05:00</published><updated>2009-05-28T05:49:46.376-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-28T05:49:46.376-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="after-cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="auctions" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>After the Cloud: Heaps of Cash</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;After the Cloud:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-prelude.html"&gt;Prelude&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-so-far.html"&gt;So Far&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-new-big.html"&gt;The New Big&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-to-atomic-computation-and.html"&gt;To Atomic Computation and Beyond&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-open-heaps.html"&gt;Open Heaps&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-heaps-of-cash.html"&gt;Heaps of Cash&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-epilogue.html"&gt;Epilogue&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A One-Two Punch&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Let me give you the punchline first, this time. Imagine a service that:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Combines the cloud management features of EC2 for any system (in this case, mobile devices), the monitoring and update management of &lt;a href="http://www.canonical.com/projects/landscape"&gt;Canonical's Landscape&lt;/a&gt;, the buying/selling power of an e-commerce application, the auctioning capabilities of eBay, and the data of marketing campaigns.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Seamlessly integrates all this into a cloud (Open Heap!) provisioning/acquisition system or as part of your mobile provider's billing and information web pages.&lt;/li&gt;&lt;/ol&gt;So where does the cash come in?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Power to the People&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As usual, revenue would depend upon market adoption. That would depend upon appeal (addressed with marketing), usefulness (addressed by software engineering and usability), and viability. That last one's particularly interesting, as it's where people and the cash intersect.&lt;br /&gt;&lt;br /&gt;A product suite and service, all built around open heaps, could have a long and fruitful life if implemented with the end user in mind. Users would have the opportunity to become partners in an extraordinary way: they would be consuming a service, while at the same time, being given the opportunity to resell a portion of that service for use in the cloud-like architectures of open heaps.&lt;br /&gt;&lt;br /&gt;The first company that does this really well would have a continuously growing following of users. This company would be helping consumers earn immediate cash back on their property. This is something I believe deeply in; it's a positive manifestation of the continuing evolution of the consumer's role in the market. I'm convinced that the more symbiotic a relationship between consumer and producer, the healthier an economy will be.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Providers&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In an open heap scenario, there are two providers: the mobile phone provider and the heap provider. Phone companies get to make money from the deal passively: through a partnership that provides them with a certain percentage of the revenue or indirectly through heap-related network use.&lt;br /&gt;&lt;br /&gt;The heap provider (e.g., someone like Amazon or &lt;a href="http://www.rightscale.com/index.php"&gt;RightScale&lt;/a&gt;), would stand to make the most of everyone. Even though they wouldn't own the devices themselves (in contrast to current cloud providers), they would be able to assess fees on various transactions and for related services.&lt;br /&gt;&lt;br /&gt;Imagine application developers "renting" potential CPU, memory, storage and bandwitdth from a heap that included 100s of 1000s of mobile users. The heap provider would be the trusted third party between the device owner and the application developer. In this way, the provider acts like an escrow service and can asses feeds accordingly.&lt;br /&gt;&lt;br /&gt;Imagine a dynamic sub-market that arises out of this sort of provisioning: with millions of devices to choose from, a user is going to want to make theirs more appealing than 1000s of others. Enter auctions. Look at how much money eBay makes. Look at the fractional fees that they asses... fees which have earned them billions of dollars.&lt;br /&gt;&lt;br /&gt;Throw in value-adds like monitoring and specialized management features, and you've got additional sources of revenue. There's a lot of potential in something like this...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Review&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Obviously, all of this is little more than creative musing. The technology isn't quite there yet for a lot of what is required to make this a reality. Regardless, given the shere numbers of small, networkable devices in our society, we need to explore how to best exploit untapped resources in mobile computing, providing additional, cheaper environments for small applications, decreasing the dependency we have upon large data centers, and hopefully reducing the draw on power grids. We need decentralized, secure storage and processing. We need smarter, more fair, consumer-as-beneficiary, economies.&lt;br /&gt;&lt;br /&gt;Next, we develope a new segment of the market, where any user or company with one or more networked devices would be able to log in to an open heap provider's software and offer their machine as another member in that cloud. There's a lot of work involved in making that happen, much of it focused on the design and implementation of really good software.&lt;br /&gt;&lt;br /&gt;If we can accomplish all that, we will have reinvented the cloud as something far greater and more flexible than it is today.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-6433984318269678958?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/QuXkOEOaie8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/6433984318269678958/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=6433984318269678958" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/6433984318269678958?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/6433984318269678958?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/QuXkOEOaie8/after-cloud-heaps-of-cash.html" title="After the Cloud: Heaps of Cash" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/05/after-cloud-heaps-of-cash.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4MSXg5fCp7ImA9WxJQFU0.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-1917053847593604326</id><published>2009-05-14T17:09:00.004-05:00</published><updated>2009-05-28T05:53:08.624-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-28T05:53:08.624-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="after-cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="mobile-computing" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>After the Cloud: Open Heaps</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;After the Cloud:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-prelude.html"&gt;Prelude&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-so-far.html"&gt;So Far&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-new-big.html"&gt;The New Big&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-to-atomic-computation-and.html"&gt;To Atomic Computation and Beyond&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-open-heaps.html"&gt;Open Heaps&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-heaps-of-cash.html"&gt;Heaps of Cash&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-epilogue.html"&gt;Epilogue&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Refresher&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Up to now, we've considered technical explorations and possible related future directions for the technology surrounding the support of distributed applications and infrastructure. This post takes a break and returns to thoughts of provisioning resources on small devices such as mobile phones. As stated in &lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-to-atomic-computation-and.html"&gt;To Atomic Computation and Beyond&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;This could be just the platform for running small processes in a distributed environment. And making it a reality could prove to be quite lucrative.&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;A forthcoming blog post will explore more about the possibilities involved with phone clouds... &lt;/blockquote&gt;But first, I'm so tired of the term "cloud," so I did some free-association... from cloud to clouds to "tons of little clouds" to "close to the ground" to cumulus to heap (Latin for "cumulus"). Heap! It's irresistible :-)&lt;br /&gt;&lt;br /&gt;"Open" is such a terribly abused word these days (more so than cloud), but using it as an adjective for a wild collection of ad-hoc, virtualized process spaces satisfies some subtle sense of humor. Open Heaps it is.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Starting Points&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Let's think about the medium in our example:  cellular telephony. &lt;span style="font-style: italic;"&gt;Is there a potential market here?&lt;/span&gt; Here are some raw numbers from &lt;a href="http://en.wikipedia.org/wiki/Cellular_telephony#cite_note-reuters50-3"&gt;Wikipedia&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;By November 2007, the total number of mobile phone subscriptions in the world had reached 3.3 billion, or half of the human population (although some users have multiple subscriptions, or inactive subscriptions), which also makes the mobile phone the most widely spread technology and the most common electronic device in the world.&lt;/blockquote&gt;I think we can count that as a tentative "yes."&lt;a href="http://en.wikipedia.org/wiki/Cellular_telephony#cite_note-reuters50-3" title=""&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Can we do this the easy way and just use TCP/IP?&lt;/span&gt; In other words, what about using &lt;a href="http://en.wikipedia.org/wiki/WiFi_phone"&gt;WiFi phones&lt;/a&gt; or &lt;a href="http://en.wikipedia.org/wiki/Dual-mode_phone"&gt;dual-mode mobile phones&lt;/a&gt; as the communication medium for devices in our open heaps? Well, that would certainly make many things much easier, since everything would stay in the TCP/IP universe. However, the market penetration of standard mobile phones is so much greater in comparison.&lt;br /&gt;&lt;br /&gt;That being said, how many currently operating phones are capable of serving content on the internet, running background processes, etc.? Maybe only a small fraction, perhaps even enough to justify supporting only devices such as &lt;a href="http://en.wikipedia.org/wiki/Handheld_devices"&gt;handhelds&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Smart_phone"&gt;smartphones&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Mobile_internet_device"&gt;MIDs&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/UMPC"&gt;UMPCs&lt;/a&gt;, and &lt;a href="http://en.wikipedia.org/wiki/Netbook"&gt;Netbooks&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Two possibilities for ventures here might be:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;A startup that developed an Open Heap offering for any Internet-connected device.&lt;/li&gt;&lt;li&gt;A company that formed a partnership with one or more mobile carriers, acting as a bridge between the carrier-controlled network/device-management capabilities and the Internet.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Business Problem&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So, let's say we've got the technology ready to go that will allow users to upload a process hypervisor to their phones, and that this technology provides the ability for users to allot process resources (e.g., RAM, CPU, storage). There are still a couple basic principles to address to justify a business in this area:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;How will people be better off with this than without it?&lt;/li&gt;&lt;li&gt;How will this technology generate revenue?&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;In general, I believe that consumers are always better off with more choices. I also believe that balanced systems run better than those that are rigged to benefit just one group. As such, I have an idealist's interest in things like Open Heaps, as they will empower interested consumers to earn revenue (however  small) on their own property (mobile phones and other devices with marketable resources). What's more, if there are billions of devices available as nodes in Open Heaps, and there is a computing demand for those resources, then there will inevitably be competitors aiming to capitalize on them.  Generally speaking, I also believe that increased competition provides a better chance for improved quality of service.&lt;br /&gt;&lt;br /&gt;Conversely, imagine that Open Heaps don't happen, that the idle resources of mobile devices (or any other eligible equipment) either remain untapped of their potential or, worse, are put to use by corporations that only desire the end consumer to have limited power over their own property and how it's used. Dire scenarios aren't difficult to imagine, thanks to various examples of anti-consumer behaviour we've seen from large corporations and special interest organizations in the recent past.&lt;br /&gt;&lt;br /&gt;So, yes -- I think we can make a case for this being of benefit to consumers (and thus a marketer's dream!). The more prevalent mobile devices become, the more they will integrate into our daily lives... and the more important it will be that these are managed as the rightful property of the consumer, people that have the right to rent or lease and profit from their property as they see fit.&lt;br /&gt;&lt;br /&gt;But, how could this generate revenue?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Next up: &lt;/span&gt;Gimme da cash!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-1917053847593604326?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/1NQiCAMcffw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/1917053847593604326/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=1917053847593604326" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/1917053847593604326?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/1917053847593604326?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/1NQiCAMcffw/after-cloud-open-heaps.html" title="After the Cloud: Open Heaps" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/05/after-cloud-open-heaps.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UGQ3g-cSp7ImA9WxJTFU0.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-292539567855777331</id><published>2009-04-23T11:46:00.000-05:00</published><updated>2009-04-23T11:47:02.659-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-23T11:47:02.659-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="generators" /><category scheme="http://www.blogger.com/atom/ns#" term="greenlets" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="coroutines" /><category scheme="http://www.blogger.com/atom/ns#" term="concurrency" /><title>Generators and Coroutines</title><content type="html">&lt;div&gt;&lt;br /&gt;This came up in the blog comments yesterday, but it really deserves a post of its own. A few days back, I was googling for code and articles that have been written regarding the use of Python 2.5 generators to build coroutines. All I got were many dead ends. Nothing really seemed to have any substance nor did materials dive into the depths in the manner I wanted and was hoping to find. I was at a loss... until I came across &lt;a href="http://jeremyhylton.blogspot.com/2009/03/coroutines-in-python.html"&gt;a blog post&lt;/a&gt; by Jeremy Hylton.&lt;br /&gt;&lt;br /&gt;This was heaven-sent. Until then, I'd never looked at David Beazley's instruction materials, but immediately was dumbstruck at the beautiful directness, clarity, and simplicity of his style. He was both lucid in the topics while conveying great enthusiasm for them. With Python 2.5 generator-based coroutines, this is something that few have been able to do a fraction as well as David has. I cannot recommend the content of these two presentations highly enough:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.dabeaz.com/generators-uk/"&gt;Generator Tricks for Systems Programmers&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.dabeaz.com/coroutines/index.html"&gt;A Curious Course on Coroutines and Concurrency&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Even though I've never been to one of his classes, after reading his &lt;a href="http://www.dabeaz.com/cv.html"&gt;fascinating background&lt;/a&gt;, I'd love the chance to pick his brain... for about a year or two (class or no!).&lt;br /&gt;&lt;br /&gt;I've done a little bit of prototyping using greenlets before, and will soon need to do much more than that with Python 2.5 generators. My constant companion in this work will be David's &lt;a href="http://www.dabeaz.com/coroutines/index.html"&gt;Curious Course&lt;/a&gt;. Also, don't give the other slides a pass, simply because you already understand generators. David's not just about conveying information: he's gifted at sharing and shifting perspective.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-292539567855777331?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/sm-Fz1Glgw0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/292539567855777331/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=292539567855777331" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/292539567855777331?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/292539567855777331?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/sm-Fz1Glgw0/generators-and-coroutines.html" title="Generators and Coroutines" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/04/generators-and-coroutines.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAHRH4_eSp7ImA9WxJTFEw.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-1324256446279352420</id><published>2009-04-22T11:45:00.000-05:00</published><updated>2009-04-22T11:45:35.041-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-22T11:45:35.041-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="lisp" /><category scheme="http://www.blogger.com/atom/ns#" term="haskell" /><category scheme="http://www.blogger.com/atom/ns#" term="erlang" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="functional-programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>Functional Programming in Python</title><content type="html">&lt;div&gt;&lt;br /&gt;Over the past couple years or so I've toyed with functional programming, dabbling in Lisp, Scheme, Erlang, and most recently, Haskell. I've really enjoyed the little bit I've done and have broadened my experience and understanding in the process.&lt;br /&gt;&lt;br /&gt;Curious as to what folks have done with Python and functional programming, I recently did a google search I should have run years ago and discovered some community classics. I'm posting them here, in the event that I might spare others such an error in oversight :-)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://gnosis.cx/publish/programming/charming_python_13.txt"&gt;Functional Programming in Python&lt;/a&gt; (2001)&lt;/li&gt;&lt;li&gt;&lt;a href="http://gnosis.cx/publish/programming/charming_python_16.txt"&gt;More Functional Programming in Python&lt;/a&gt; (2001)&lt;/li&gt;&lt;li&gt;&lt;a href="http://gnosis.cx/publish/programming/charming_python_19.txt"&gt;Even More Functional Programming in Python&lt;/a&gt; (2001)&lt;/li&gt;&lt;li&gt;&lt;a href="http://gnosis.cx/publish/programming/charming_python_b13.txt"&gt;Functional programming in Python becomes lazy&lt;/a&gt; (2003)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amk.ca/python/writing/functional"&gt;Functional Programming HOWTO&lt;/a&gt; (updated 2006)&lt;/li&gt;&lt;li&gt;The &lt;a href="http://oakwinter.com/code/functional/documentation/"&gt;functional&lt;/a&gt; module (updated 2007)&lt;/li&gt;&lt;/ul&gt;I've always enjoyed David's writing style, though I've never read his FP articles until now. They were quite enjoyable and have aged well, despite referencing older versions of Python. Andrew's HOWTO provides a wonderful, modern summary.&lt;br /&gt;&lt;br /&gt;I make fairly regular use of &lt;a href="http://docs.python.org/library/itertools.html"&gt;itertools&lt;/a&gt; but have never used the &lt;a href="http://docs.python.org/library/operator.html"&gt;operator&lt;/a&gt; module -- though I now look forward to some FP idiomatic Python playtime with it :-)  I've never used &lt;a href="http://docs.python.org/library/functools.html"&gt;functools&lt;/a&gt;, either.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-1324256446279352420?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/m0ukyk5kS6Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/1324256446279352420/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=1324256446279352420" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/1324256446279352420?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/1324256446279352420?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/m0ukyk5kS6Y/functional-programming-in-python.html" title="Functional Programming in Python" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/04/functional-programming-in-python.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8FR3Y8eyp7ImA9WxJQFU0.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-7128087200518073816</id><published>2009-04-21T10:36:00.005-05:00</published><updated>2009-05-28T05:50:16.873-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-28T05:50:16.873-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="smalltalk" /><category scheme="http://www.blogger.com/atom/ns#" term="cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="after-cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="erlang" /><category scheme="http://www.blogger.com/atom/ns#" term="parallelism" /><category scheme="http://www.blogger.com/atom/ns#" term="virtualization" /><category scheme="http://www.blogger.com/atom/ns#" term="uls" /><category scheme="http://www.blogger.com/atom/ns#" term="mobile-computing" /><title>After the Cloud: To Atomic Computation and Beyond</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;After the Cloud:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-prelude.html"&gt;Prelude&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-so-far.html"&gt;So Far&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-new-big.html"&gt;The New Big&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-to-atomic-computation-and.html"&gt;To Atomic Computation and Beyond&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-open-heaps.html"&gt;Open Heaps&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-heaps-of-cash.html"&gt;Heaps of Cash&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-epilogue.html"&gt;Epilogue&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;To restate the problem: we've got cloud for systems and we've got cloud for a large number of applications. We don't have cloud for processes (e.g., custom, light-weight applications/long-running daemons).&lt;br /&gt;&lt;br /&gt;Personally, I don't want a whole virtual machine to myself, I just need a tiny process space for my daemon. When my daemon starts getting slammed, I want new instances of it started in a cloud (and then killed when they're not needed).&lt;br /&gt;&lt;br /&gt;What's more, over time, I want to be writing my daemon better and better... using less of everything (memory, CPU, disk) in subsequent iterations. I want this process cloud to be able to handle potentially significant changes in my software.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Dream Cloud&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;So, after all that stumbling around, thinking about servers in the data center as the horsepower behind distributed services, and then user PCs/laptops as a more power-friendly alternative, the obvious hit me: phones. They are almost ubiquitous. People leave them on, plugged in, and only use them for a fraction of that time. What if we were able to construct a cloud from cell phones? Hell, let's throw in Laptops and netbooks, too. And Xboxes, Wii, and TiVos. Theoretically, anything that could support (or be hacked to support) a virtual process space could become part of this cloud.&lt;br /&gt;&lt;br /&gt;This could be just the platform for running small processes in a distributed environment. And making it a reality could prove to be quite lucrative.&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;A forthcoming blog post will explore more about the possibilities involved with phone clouds... but for now, let's push things even further.&lt;br /&gt;&lt;br /&gt;When I mentioned this idea to Chris Armstrong at the Ubuntu Developer Conference last December, he immediately asked me if I'd read &lt;a href="http://www.antipope.org/charlie/blog-static/index.html"&gt;Charles Stross&lt;/a&gt;' book &lt;a href="http://www.amazon.com/Halting-State-Charles-Stross/dp/0441014984"&gt;Halting State&lt;/a&gt;. I had started it, but hadn't gotten to the part about the phones. A portion of Stross' future vision in that book dealt with the ability of users to legally run programs of other's phones. I really enjoyed the tale, but afterwards I was ready to explore other possibilities.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Horse-buggy Virtualization&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So I sat down and pondered other possibilities over the course of several weeks. I kept trying to think like business visionaries, given a new resource to exploit. But finally I stopped that and tried just imagining the possibilities based on examples computing and business history.&lt;br /&gt;&lt;br /&gt;What's the natural thing for businesses to do when someone invents something or improves something? Put new improvements to old uses, potentially reinventing old markets in the process. That's just the sort of thing that could happen with the cloudification of mobile devices.&lt;br /&gt;&lt;br /&gt;For examples, imagine this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Phone cloud becomes a reality.&lt;/li&gt;&lt;li&gt;Someone in a garage in Silicon Valley buys a bunch of cheap phones, gumstix, or other small ARM components, rips off the cases, and sells them in rack-mountable enclosures.&lt;/li&gt;&lt;li&gt;Data centers start supplementing their old hardware offering with this new one that lets them use phone cloud tech (originally built for remote, hand-held devices) to sell tiny fractions of resources to users (on new, consolidated hardware... like having hundreds of phone uses in a single room with full bars, 24/7).&lt;/li&gt;&lt;li&gt;With the changing hardware and continuing improvements in virtualization software, more abstraction takes place.&lt;/li&gt;&lt;li&gt;Virtualization slowly goes from tool to &lt;span style="font-style: italic;"&gt;prima materia&lt;/span&gt;, allowing designers not to focus on old-style, horse-drawn "machines" like your grandpa used to rack, but rather abstract process spaces that provide just what is needed, for example, to enable a daemon to run.&lt;/li&gt;&lt;/ul&gt;Once you've gotten that far, you're just inches from producing a meta operating system: process spaces (and other abstracted bits) can be built up to form a traditional user space. Or they can be used to build something entirely different and new. The computing universe suddenly gets a lot more flexible and dynamic.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Democritus Meets Modern Software&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So, let's say that my dream comes true: I can now push all my tiny apps into a cloud service and turn off the big machines I've got colocated throughout the US. But once this is in place, how can we improve our applications to take even better advantage of such a system, one so capable of massively distributing our running code?&lt;br /&gt;&lt;br /&gt;This leads us to an almost metaphysical software engineering question: how small can you divide an application until you reach the limits of functionality, where any further division would be senseless bytes and syntax errors? In terms of running processes, what is your code atom?&lt;br /&gt;&lt;br /&gt;Prior to a few years ago, the most common answer would likely have been "my script" or "my application". Unless, of course, you asked a Scheme programmer. Programming languages like Scheme, Haskell, and Erlang are finding rapidly increasing acceptance as solutions for distributed programming problems because functional programming languages lend themselves easily to the problem of concurrency and parallelism.&lt;br /&gt;&lt;br /&gt;If we had a massive computing cloud (atmosphere, more likely!) where we could run code in virtual process spaces, we could theoretically go even further than running a daemon: we could split our daemon up into async functions. These distributed functions could be available as continuously running microthreads/greenlets/whatever. They could accept an input and produce an output. Composing distributed functions could result in a program. Programs could change, failover, improve, etc., just by adding or removing distributed functions or by changing their order.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;From Atoms to Dynamic Programs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once we've broken down our programs into distributed functions and have broken our concept of an "Operating System" down into virtual process spaces, we can start building a whole new world of software:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Software becomes very dynamic, very distributed. &lt;/li&gt;&lt;li&gt;The particulars of hardware become irrelevant (it just needs to be present, somewhere).&lt;/li&gt;&lt;li&gt;We see an even more marked correlation between power consumption and code, where functions themselves could be measured in joules consumed per second.&lt;/li&gt;&lt;li&gt;Just for fun, let's throw in dynamic selection of fuctions or even genetic algorithms, and we have ourselves one of the core branches of the predicted &lt;a href="http://www.sei.cmu.edu/uls/"&gt;Ultra-large Scale Systems&lt;/a&gt; :-)&lt;/li&gt;&lt;/ul&gt;I mention this not for cheap thrills, but rather because of the importance of having a vision. Even if we don't get to where we think we're going, by looking ahead and forward, we have the opportunity to influence our journey such that we increase the chances of getting to a place equal to or better than where we'd originally intended.&lt;br /&gt;&lt;br /&gt;From a more practical perspective: today, I'm concerned about running daemons in the cloud. Tomorrow I could very well be concerned about finer granularity than that. Why not explore the potential results of such technology? Yes, it my prove infeasible now; but even still, it could render insights... and maybe more.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A Parting Message&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Before I wind this blog post down, I'd like to paste a couple really excellent quotes. They are good not so much for their immediate content, but for the pregnant potentials they contain; for the directions they can point our musings... and engineerings. These are two similar thoughts about messaging from two radically different contexts. I leave you with these moments of Zen:&lt;br /&gt;&lt;br /&gt;On the Erlang mail list,  four years ago, Erlang expert Joe Armstrong &lt;a href="http://article.gmane.org/gmane.comp.lang.erlang.general/7694"&gt;posted this&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;In  Concurrency Oriented  (CO)  programming you  concentrate on  the concurrency  and  the messages  between  the  processes.  There is  no sharing of data.&lt;br /&gt;&lt;br /&gt;[A program] should  be thought of thousands of  little black boxes all doing things  in parallel  - these black  boxes can send  and receive messages.  Black boxes can detect errors in other black boxes - that's all.&lt;br /&gt;...&lt;br /&gt;Erlang uses  a simple functional language  inside the [black boxes]  - this is not particularly interesting - *any*  language that does the job would do - the important bit is the concurrency.&lt;/blockquote&gt;On the Squeak mail list in 1998, Alan Kay had &lt;a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/1998-October/017019.html"&gt;this to say&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;...Smalltalk is not only NOT its syntax or the class library, it is not even about classes. I'm sorry that I long ago coined the term "objects" for this topic because it gets many people to focus on the lesser idea.&lt;br /&gt;&lt;br /&gt;The big idea is "messaging" -- that is what the kernal of Smalltalk/Squeak is all about... The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be. Think of the internet -- to live, it (a) has to allow many different kinds of ideas and realizations that are beyond any single standard and (b) to allow varying degrees of safe interoperability between these ideas.&lt;br /&gt;&lt;br /&gt;If you focus on just messaging -- and realize that a good metasystem can late bind the various 2nd level architectures used in objects -- then much of the language-, UI-, and OS based discussions on this thread are really quite moot.&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Next up&lt;/span&gt;: The Business of Computing Atmospheres&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-7128087200518073816?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/rRLA8a2lzbk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/7128087200518073816/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=7128087200518073816" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/7128087200518073816?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/7128087200518073816?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/rRLA8a2lzbk/after-cloud-to-atomic-computation-and.html" title="After the Cloud: To Atomic Computation and Beyond" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/04/after-cloud-to-atomic-computation-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8BQXg9eCp7ImA9WxJQFU0.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-5448943643030007193</id><published>2009-04-20T12:07:00.008-05:00</published><updated>2009-05-28T05:50:50.660-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-28T05:50:50.660-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="miniturization" /><category scheme="http://www.blogger.com/atom/ns#" term="tahoe" /><category scheme="http://www.blogger.com/atom/ns#" term="vde" /><category scheme="http://www.blogger.com/atom/ns#" term="cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="after-cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="virtualization" /><category scheme="http://www.blogger.com/atom/ns#" term="hardware" /><category scheme="http://www.blogger.com/atom/ns#" term="storage" /><title>After the Cloud: The New Big</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;After the Cloud:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-prelude.html"&gt;Prelude&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-so-far.html"&gt;So Far&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-new-big.html"&gt;The New Big&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-to-atomic-computation-and.html"&gt;To Atomic Computation and Beyond&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-open-heaps.html"&gt;Open Heaps&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-heaps-of-cash.html"&gt;Heaps of Cash&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-epilogue.html"&gt;Epilogue&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Intermission&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've made a few hints so far about what cloud service I'd like to see come into being, and at the end of this post, we'll get closer to discussing that. Hang in there: the post after this one will describe that in more detail. Then, after that, there will be at least one post which will take a peek at some of the many business opportunities that could come from this.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A Passing Comment&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At PyCon 2006 in Dallas, TX, an after-hours event was held in a local bookstore. At one point during that evening, &lt;a href="http://itamarst.org/"&gt;Itamar&lt;/a&gt;, &lt;a href="http://moshez.wordpress.com/"&gt;Moshe&lt;/a&gt; and I got into a discussion about miniaturization and Moshe went off on a hilarious rant that Itamar and I just sat back and enjoyed. His whole tirade was based on the beauty and perfection of &lt;a href="http://www.gumstix.com/"&gt;gumstix&lt;/a&gt;. This was the first I'd heard of them; I had no idea a product like that was on the market, and it hit me like a ton of bricks.&lt;br /&gt;&lt;br /&gt;For the next day or so all I could think about was buying a boxload of gumstix computers and doing something with them -- anything! And not just because they were the coolest toys ever, but because there was something about them that I could just &lt;span style="font-style: italic;"&gt;feel&lt;/span&gt; was a part of the future of computing (see my 2004 post on &lt;a href="http://oubiwann.blogspot.com/2004/03/dinosaurs-and-mammals.html"&gt;Dinosaurs and Mammals&lt;/a&gt;).  It seemed that these miniture devices could help prototype what was destined to be one of the most exciting fields in the coming years for both systems and application engineers.&lt;br /&gt;&lt;br /&gt;Sadly, I never did get that box :-) But I neither did I stop thinking about them. Confronted with the problem of small distributed services sitting on big, barely-used iron, gumstix haunted my musings.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Tiny Apps in the Cloud?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When at Divmod, one of the strategies that Glyph and I were working on concerned Twisted adoption in web hosting and cloud environments. The differences between CGI and Twisted applications are magnified when one considers a cloud environment like &lt;a href="http://www.mosso.com/"&gt;Mosso&lt;/a&gt; and one that would suitably support Twisted design principals. I spent a &lt;span style="font-style: italic;"&gt;lot&lt;/span&gt; of time pondering the ramifcations of that one, let me tell you. A potential merger permanently postponed those business possibilities, but a nice side benefit was the forking of &lt;a href="http://pythondirector.sourceforge.net/"&gt;Python Director&lt;/a&gt; into a pure-Twisted conversion, &lt;a href="https://edge.launchpad.net/txloadbalancer"&gt;txLoadBalancer&lt;/a&gt; (with the beginnings of native, in-app load-balancing support).&lt;br /&gt;&lt;br /&gt;Thoughts of adjusting tiny apps to be able to run on big cloud hardware still grated, though. It felt dangerously close to pounding round pegs into square holes. What I really wanted was something closer to the future hinted at by &lt;a href="http://www.sei.cmu.edu/uls/"&gt;Ultra Large-Scale Systems&lt;/a&gt; research: massively distributed, fault-tolerant services running on everything :-) Until then, though, I would have been satisfied with tiny apps on tiny hardware, consuming only the resources they need in order to provide the service they were designed for.&lt;br /&gt;&lt;br /&gt;This brought up ideas of distributed storage, memory, and processing as well as the need for redundacy and failover. But tiny. All I could see was tiny hardware, tiny apps, tiny protocols, tiny power consumption. For me, tiny was big. The easiest "tiny" problem to address with small devices was storage. And I already knew the guys that were working on the problem.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Distributed Storage Done Right&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There's an odd, rather abstract parallel between EC2 and &lt;a href="http://allmydata.org/trac/tahoe"&gt;Tahoe&lt;/a&gt; (a secure, decentralized, fault-tolerant filesystem). EC2 arose in part from a corporation acting out of its best interests: turn a liability into an asset. For Tahoe, the "body"  in question isn't a corporation, but rather a community. And the commodity is not bottom lines, but rather data owned and treasured by members of a data-consuming community.&lt;br /&gt;&lt;br /&gt;Here's a quick description of Tahoe from a &lt;a href="http://allmydata.org/%7Ezooko/lafs.pdf"&gt;2008 paper&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;Tahoe is a storage grid designed to provide secure, long-term storage, such as for backup applications. It consists of userspace processes running on commodity PC hardware and communicating with [other Tahoe nodes] over TCP/IP.&lt;/blockquote&gt;Tahoe is written in Python using Twisted and a &lt;a href="http://foolscap.lothar.com/trac"&gt;capabilities system&lt;/a&gt; inspired by those defined by &lt;a href="http://www.erights.org/"&gt;E&lt;/a&gt;. But what does this mean to a user? It means that anyone can setup and run a storage grid on their personal computers. All data is encrypted and redundant, so you don't need to trust members of the community (your data grid), you just need to set aside some disk space on your machines for them.&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://allmydata.org/pipermail/tahoe-dev/2008-July/000657.html"&gt;a message&lt;/a&gt; to the Tahoe mail list, I responded to an associate who was exploring Tahoe for in-memory use by Python mapreduce applications. I wanted in-memory distributed storage for a different use case (tiny apps on tiny devices!) but our interests were similar. It turned out one of the primary Tahoe developers was working on related code; something that could be used as the basis for future support for distributed, solid-state devices.&lt;br /&gt;&lt;br /&gt;Here's some nice dessert: Twisted coder &lt;a href="http://blog.dreid.org/"&gt;David Reid&lt;/a&gt; was reported to have gotten Tahoe runnig on his iPhone. &lt;span style="font-style: italic;"&gt;Now&lt;/span&gt; we're talking ;-) (Update: David has informed me that &lt;a href="http://allmydata.com/"&gt;Allmydata&lt;/a&gt; has a Tahoe client that runs on his iPhone).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Processing in the Right Direction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But what about the CPU? Running daemons? Can we do something similar with processing power? If a whole virtual machine is too much for users, can we get a virtual processing space? I want to be able to run my process (e.g., a Twisted daemon) on someone else's machine, but in such a way that they feel perfectly safe running it. I want Tahoe for processes :-)&lt;br /&gt;&lt;br /&gt;As part of some recent experiments in setting up a virtual lab of running gumstix ARM images, I needed to be able to connect mutliple gumstix instances in a virtual network for testing purposes. In a search for such a solution, I discovered &lt;a href="http://vde.sourceforge.net/"&gt;VDE&lt;/a&gt;. Then, unexpectedly, I ran across a couple fascinating wiki pages on the site of related super-project Virtual Square Networking. Their domain is currently not resolving for me, so I can't pull the exact text, but here's a blurb from a &lt;a href="http://sourceforge.net/projects/view-os/"&gt;sister project&lt;/a&gt; on SourceForge:&lt;br /&gt;&lt;blockquote&gt;View OS is a user configurable, modular process virtual machine, or system call hypervisor. For each process the user is able to define a "view of the world" in terms of file system, networking, devices, permissions, users, time and so on.&lt;br /&gt;&lt;/blockquote&gt;Man, that's so close, I can almost &lt;span style="font-style: italic;"&gt;taste&lt;/span&gt; it!&lt;br /&gt;&lt;br /&gt;Where is all this techno-rambling going? Well, I'm sure some of you have long since guessed by now :-) Regardless, I will save that for the next post.&lt;br /&gt;&lt;br /&gt;Oh, and yes: tiny is the new big.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;Next Up:&lt;/span&gt; A Passing Message&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-5448943643030007193?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/XlTLUsJ1cMI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/5448943643030007193/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=5448943643030007193" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5448943643030007193?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5448943643030007193?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/XlTLUsJ1cMI/after-cloud-new-big.html" title="After the Cloud: The New Big" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/04/after-cloud-new-big.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8DQH4-fSp7ImA9WxJQFU0.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-172906485796759121</id><published>2009-04-19T13:14:00.007-05:00</published><updated>2009-05-28T05:51:11.055-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-28T05:51:11.055-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="systems" /><category scheme="http://www.blogger.com/atom/ns#" term="cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="after-cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="cgi twisted" /><category scheme="http://www.blogger.com/atom/ns#" term="applications" /><title>After the Cloud: So Far</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;After the Cloud:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-prelude.html"&gt;Prelude&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-so-far.html"&gt;So Far&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-new-big.html"&gt;The New Big&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-to-atomic-computation-and.html"&gt;To Atomic Computation and Beyond&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-open-heaps.html"&gt;Open Heaps&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-heaps-of-cash.html"&gt;Heaps of Cash&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-epilogue.html"&gt;Epilogue&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Systems Engineering in a Box&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The recent redefinition of "the cloud" as a service and commodity is a brilliant bit of frugal resource management (making use of idle resources in an expensive data center) coupled with flawless marketing. Yes, from a business perspective, that's an amazing coup. But it's the 30,000 foot technical perspective that really impresses me:&lt;br /&gt;&lt;br /&gt;In the same way that software  frameworks, their libraries, and best practices have, through the trials of last 40 tears, productized application engineering, the cloud has started to experience something similar. What everyone is now calling the cloud is really the productization of systems engineering.&lt;br /&gt;&lt;br /&gt;Systems engineering (and the management of related resources) has proven to be an expensive, time-consuming endeavor best left to the experts. Sadly, those that need it are often in the unenviable position of having to determine who the experts are without having the proper background to do so effectively. When the planning, building, and management of large systems works well, it's a labor of sweat and blood.  When it doesn't, it's the same thing, with a nightmare tinge  about the whole thing coupled with an odd time-dilation effect.&lt;br /&gt;&lt;br /&gt;It seems that in applicable circumstances, some businesses are spared that nightmare by using a &lt;a href="http://www.ibm.com/ibm/cloud/"&gt;cloud service&lt;/a&gt; or &lt;a href="http://eucalyptus.cs.ucsb.edu/"&gt;product&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Bionic CGI&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As someone with a long history and interest in application development, I was particularly keen on &lt;a href="http://code.google.com/appengine/docs/whatisgoogleappengine.html"&gt;Google App Engine&lt;/a&gt; when it came out. This was a different take on the cloud, one that &lt;a href="http://www.mosso.com/cloud.jsp"&gt;Mosso&lt;/a&gt; also seems to be embracing: upload an application that is capable of having it's data access and views distributed/load balanced across multiple systems (virtual or otherwise).&lt;br /&gt;&lt;br /&gt;This is essentially CGI's grandchild. You have an application that needs to be started up by any number of machines in response to demand. A CGI app in Mosso will probably need very few (if any) adjustments required in order to run "in the cloud." Google is a special case, since developers are using custom, black-box infrastructure built by Google (for insights into this, check out &lt;a href="http://research.google.com/pubs/papers.html"&gt;these papers&lt;/a&gt;), but I'd be willing to bet someone lunch that there is room for a CGI analogy at some level of Google App Engine.I guess with Google, we kind of have both application &lt;span style="font-style: italic;"&gt;and&lt;/span&gt; systems engineering in a box, in so far as the systems support your application.&lt;br /&gt;&lt;br /&gt;At any rate, it's CGI better than it was before. Better, stronger, faster.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Rub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;However fascinating these cloud offerings may be, I find myself not getting what I need. As a developer of &lt;a href="http://twistedmatrix.com/trac/"&gt;Twisted&lt;/a&gt; applications, I'm interested in small apps. Hell, I don't even like running databases and full-blown web servers. A while ago, I spent a couple years working on some Twisted-based application components that could be run as independent services (thus load-balanceable) and completely replace the standard web server + database + lots of code routine for application development.&lt;br /&gt;&lt;br /&gt;So what about developers out there like me, who want to run tiny apps? We don't need "classic" web hosting, nor CGI in the cloud, nor cloud-virutualized versions of large machines.&lt;br /&gt;&lt;br /&gt;As a segment of the population, business consideration for developers such as myself might seem like a waste of time. But before dismissing us, consider this:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Exploring small niche's like this one often lead to interesting revelations.&lt;/li&gt;&lt;li&gt;Market segments that have proven quite vibrant may be able to expand into even greater territories (e.g., the iPhone apps phenomena).&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-style: italic;"&gt;Next up&lt;/span&gt;: Tiny &gt; *&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-172906485796759121?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/FFwpYHJRzK8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/172906485796759121/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=172906485796759121" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/172906485796759121?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/172906485796759121?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/FFwpYHJRzK8/after-cloud-so-far.html" title="After the Cloud: So Far" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/04/after-cloud-so-far.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8MSXY6eip7ImA9WxJQFU0.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-4013443220091528663</id><published>2009-04-18T02:34:00.010-05:00</published><updated>2009-05-28T05:51:28.812-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-28T05:51:28.812-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="after-cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>After the Cloud: Prelude</title><content type="html">&lt;div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;After the Cloud:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-prelude.html"&gt;Prelude&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-so-far.html"&gt;So Far&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-new-big.html"&gt;The New Big&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/04/after-cloud-to-atomic-computation-and.html"&gt;To Atomic Computation and Beyond&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-open-heaps.html"&gt;Open Heaps&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-heaps-of-cash.html"&gt;Heaps of Cash&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oubiwann.blogspot.com/2009/05/after-cloud-epilogue.html"&gt;Epilogue&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;These days, it seems that no matter where we go, we hear something about "the cloud." It's not really buzz anymore... it has become far more accepted and widely discussed to be that. For some organizations it's actually part of their current, every-day infrastructure. For others, it soon will be. As far as I'm concerned, now's the perfect time to start discussing what's next :-)&lt;br /&gt;&lt;br /&gt;If you've spent any time reading some of the blog content I've managed to post over the past several years, you've probably noted that I like to explore the long view (if rather informally). Well, that's what I've got in store for you now: a series of blog posts that explore the long view of a post-cloud industry. Hopefully, with some new twists and turns along the way.&lt;br /&gt;&lt;br /&gt;First off, I want to cover some basic ground, so the first couple posts might be a little less interesting that those that follow. Fortunately, I've been pondering these particular ideas since my month sabbatical last August -- this means I've already got most of the material written and ready to go!&lt;br /&gt;&lt;br /&gt;These posts are going to take a peek at practical, hands-on ideas regarding the ways in which one might make use of current nascent tech to build prototypes for tomorrow's infrastructure, what that infrastructure might be, business ideas about what do do with that tech, and even future possibilities for information-based markets.&lt;br /&gt;&lt;br /&gt;Hope you enjoy it as much as I've enjoyed thinking about it :-)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-4013443220091528663?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/MHyTxsXBKm4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/4013443220091528663/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=4013443220091528663" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/4013443220091528663?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/4013443220091528663?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/MHyTxsXBKm4/after-cloud-prelude.html" title="After the Cloud: Prelude" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/04/after-cloud-prelude.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUCQXc7eCp7ImA9WxJTEE8.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-8270581487489702217</id><published>2009-04-17T22:25:00.001-05:00</published><updated>2009-04-17T22:44:20.900-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-17T22:44:20.900-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="community" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="uls" /><title>ULS-SIG: New Python Special Interest Group</title><content type="html">&lt;div&gt;&lt;br /&gt;After several discussions at the end of last summer and an incubation in &lt;a href="http://mail.python.org/mailman/listinfo/meta-sig"&gt;Meta-SIG&lt;/a&gt;, &lt;a href="http://holdenweb.blogspot.com/"&gt;Steve Holden&lt;/a&gt;, &lt;a href="http://zyasoft.com/pythoneering/"&gt;Jim Baker&lt;/a&gt; and I are pleased to announce the Python special interest group for ultra large-scale systems. For more about ULS system, you might want to read &lt;a href="http://oubiwann.blogspot.com/2008/05/required-reading-ultra-large-systems.html"&gt;this post&lt;/a&gt; or &lt;a href="http://oubiwann.blogspot.com/2008/06/ultra-large-systems-example.html"&gt;this one&lt;/a&gt;. The &lt;a href="http://www.python.org/community/sigs/"&gt;SIGs page&lt;/a&gt; has been updated, so you can find us there with the rest of them (subscribe and archive links, too), and we've even got &lt;a href="http://www.python.org/community/sigs/current/uls-sig/"&gt;our own page&lt;/a&gt; :-)&lt;br /&gt;&lt;br /&gt;The initial group of interested parties (and thus the first members of the list) represent an interesting cross-section of the Python community, including the following:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Jython hackers&lt;/li&gt;&lt;li&gt;Twisted hackers&lt;/li&gt;&lt;li&gt;Stackless hackers&lt;/li&gt;&lt;li&gt;XMPP experts&lt;/li&gt;&lt;li&gt;MMPORG developers&lt;/li&gt;&lt;li&gt;SOA and Business Process consultants&lt;/li&gt;&lt;li&gt;General technology and software companies&lt;/li&gt;&lt;/ul&gt;The technological umbrella of ULS systems covers a vast array of topics and interests, but basic principle unifying all of these is their potential contribution to making massive, highly distributed systems a functional reality.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.sei.cmu.edu/uls/files/roadmap.pdf"&gt;One overview&lt;/a&gt; of ULS systems research states that we currently don't have an effective understanding of software (it's nature, development, and management) at the scale anticipated for ULS systems. These "fundamental gaps" will hinder the development of such systems until they can be crossed. Doing so will require breakthroughs in many fields with insights and experience gained over time.&lt;br /&gt;&lt;br /&gt;Python programmers represent an extraordinary segment of the population: creative, curious, motivated, communicative, and deeply intelligent individuals. Our community is filled with minds that continuously produce solutions for a vast array of problems across a great many disciplines.&lt;br /&gt;If there's any one group out there that could pull this off, I think it's ours :-)&lt;br /&gt;&lt;br /&gt;A future post will provide a sketch of areas of interest in Python that are already sneaking up on the gaps outlined in ULS systems reports. There is a lot of software and supporting libraries that have an obvious connection to ULS systems, but even more fun are the ones that don't... and isn't always the darkest corners that yield the most unlooked for surprises?&lt;br /&gt;&lt;br /&gt;While you're waiting for that, though, feel free to &lt;a href="http://mail.python.org/mailman/listinfo/uls-sig"&gt;join us&lt;/a&gt; on the mail list!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-8270581487489702217?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/xb5K0qGhahY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/8270581487489702217/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=8270581487489702217" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/8270581487489702217?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/8270581487489702217?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/xb5K0qGhahY/uls-sig-new-python-special-interest.html" title="ULS-SIG: New Python Special Interest Group" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/03/uls-sig-new-python-special-interest.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUBSXg-eip7ImA9WxVaGU8.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-5788766034617511434</id><published>2009-04-16T17:16:00.003-05:00</published><updated>2009-04-16T17:50:58.652-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-16T17:50:58.652-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="psu" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="pycon2009" /><category scheme="http://www.blogger.com/atom/ns#" term="psf" /><title>Newest Members of the PSF</title><content type="html">&lt;div&gt;&lt;br /&gt;Since it's now official, I can blog about it: I was delighted to discover that &lt;a href="http://jcalderone.livejournal.com/"&gt;JP&lt;/a&gt;, &lt;a href="http://radix.twistedmatrix.com/"&gt;radix&lt;/a&gt;, &lt;a href="http://glyph.twistedmatrix.com/"&gt;glyph&lt;/a&gt;, and I were voted into the &lt;a href="http://www.python.org/psf/"&gt;Python Software Foundation&lt;/a&gt; this year at PyCon :-)  Not only is that four for Twisted, but it's two for Divmod and two more for Canonical.&lt;br /&gt;&lt;br /&gt;There was another Canonical employee -- Matthias Klose -- voted in as well, and with Barry Warsaw and Gustavo Niemeyer, that brings a tally for Canonical to at least 5, and maybe more (let me know if I've missed you!).&lt;br /&gt;&lt;br /&gt;It gets even better, though: check out the rest of the new members list:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Jim Baker&lt;/li&gt;&lt;li&gt;Ben Bangert&lt;/li&gt;&lt;li&gt;James Bennett&lt;/li&gt;&lt;li&gt;Graham Dumpleton&lt;/li&gt;&lt;li&gt;Martijn Faassen&lt;/li&gt;&lt;li&gt;Michael Fletcher&lt;/li&gt;&lt;li&gt;Michael Foord&lt;/li&gt;&lt;li&gt;Doug Hellmann &lt;/li&gt;&lt;li&gt;Adrian Holovaty&lt;/li&gt;&lt;li&gt;Jacob Kaplan-Moss&lt;/li&gt;&lt;li&gt;Jesse Noller&lt;/li&gt;&lt;li&gt;Benjamin Peterson&lt;/li&gt;&lt;li&gt;Ted Pollari&lt;/li&gt;&lt;li&gt;Mark Ramm&lt;/li&gt;&lt;li&gt;Malcolm Tredinnick&lt;/li&gt;&lt;li&gt;Kirby Urner &lt;/li&gt;&lt;li&gt;Robert Dino Viehland&lt;/li&gt;&lt;li&gt;Thomas Waldmann &lt;/li&gt;&lt;li&gt;Frank Wierzbicki&lt;/li&gt;&lt;/ul&gt;I am thrilled to be a PSF member and look forward to deepening my support of Python through this new level of involvement. Even more, though, I'm honored and delighted to be working with both the &lt;a href="http://www.python.org/psf/members/"&gt;esteemed veteran members&lt;/a&gt; as well as these amazing new additions.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-5788766034617511434?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/P78Rv0155vQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/5788766034617511434/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=5788766034617511434" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5788766034617511434?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5788766034617511434?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/P78Rv0155vQ/newest-members-of-psf.html" title="Newest Members of the PSF" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/04/newest-members-of-psf.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYBQX88eCp7ImA9WxVbEUQ.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-5958358166358495675</id><published>2009-03-27T17:37:00.005-05:00</published><updated>2009-03-27T17:49:10.170-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-27T17:49:10.170-05:00</app:edited><title>txLoadBalancer Lightening Talk?</title><content type="html">&lt;div&gt;&lt;br /&gt;As I mentioned in &lt;a href="http://oubiwann.blogspot.com/2009/03/hot-talks-at-pycon-2009.html"&gt;this post&lt;/a&gt;, I wasn't able to make it to PyCon this year. I'm super bummed now, 'cause I just got an email about a potential lighting talk for &lt;a href="https://launchpad.net/txloadbalancer"&gt;txLoadBalancer&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'm not sure when tomorrow it has been tentatively scheduled for, but go! And then tell me how it was :-)&lt;br /&gt;&lt;br /&gt;As I told one of the presenters (&lt;a href="http://jehiah.cz/"&gt;Jehiah Czebotar&lt;/a&gt;), this is really motivating me to get the next release out :-)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-5958358166358495675?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/_KBr3OfCkE0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/5958358166358495675/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=5958358166358495675" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5958358166358495675?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/5958358166358495675?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/_KBr3OfCkE0/txloadbalancer-lightening-talk.html" title="txLoadBalancer Lightening Talk?" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/03/txloadbalancer-lightening-talk.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8FQns7fCp7ImA9WxVbEU4.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-6886938781352367469</id><published>2009-03-27T00:36:00.003-05:00</published><updated>2009-03-27T00:46:53.504-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-27T00:46:53.504-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="rrd" /><category scheme="http://www.blogger.com/atom/ns#" term="pyrrd" /><category scheme="http://www.blogger.com/atom/ns#" term="rrdtool" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>New PyRRD Release: 0.0.7</title><content type="html">&lt;div&gt;&lt;br /&gt;Version 0.1 is nearing as the 7th release made it out the door tonight. The latest features include RRD info/fetch methods, a simple RRD object mapper, and the ability to dump files programmatically. Various bug fixes have been applied, thanks to feedback and patches from the community. In particular,           &lt;form id="captcha" style="display: none;" method="get" action="#" autocomplete="off"&gt;  Type the characters you see in the picture below.&lt;br /&gt;&lt;img src="http://code.google.com/hosting/captcha?id=105039380&amp;amp;si=1" style="padding: 4px;" height="70" width="200" /&gt; &lt;input name="ca" value="5fe8d54a01513ff6f032b64596cf5903" type="hidden"&gt; &lt;input name="aca" value="bc6af0c7e33c6a36b93abaf7a5c0ca8e" type="hidden"&gt;&lt;br /&gt;&lt;input name="cg" id="cg" value="" size="22" onkeyup="checksubmit()" autocomplete="off" type="text"&gt; &lt;a href="javascript:playCaptcha()" title="Listen and type the numbers you hear"&gt;&lt;img src="http://www.gstatic.com/codesite/ph/images/accessibility.gif" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="color: rgb(102, 102, 102);"&gt;Letters are not case-sensitive&lt;/div&gt;  &lt;script type="text/javascript"&gt; function playCaptcha() {  var wavURL = '/hosting/captcha?id=105913651&amp;si=1';  var embedCode = '&lt;embed src="' + wavURL + '" hidden="true" autostart="true"&gt;&lt;/embed&gt;';  document.getElementById("playAudio").innerHTML = "";  document.getElementById("playAudio").innerHTML = embedCode;  document.getElementById("cg").value="";  document.getElementById("cg").focus(); } &lt;/script&gt;   &lt;input value="Submit" type="submit"&gt; and&lt;br /&gt;&lt;/form&gt;Aaron Westendorf of Agora Games, Leem Smit, and nasvos.&lt;br /&gt;&lt;br /&gt;You can download from PyPI (or use setuptools to install it) at the expected location:&lt;br /&gt;&lt;a href="http://pypi.python.org/pypi/PyRRD/"&gt;http://pypi.python.org/pypi/PyRRD/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note that the the PyPI page has a quick run-down on the basic features and how to use them.&lt;br /&gt;&lt;br /&gt;The next feature to be implemented has already been planned out (it's just a matter of sitting down and writing the code now): adding support for the Python bindings. If this is important to you, be sure to star the issue in the bug tracker:&lt;br /&gt;&lt;a href="http://code.google.com/p/pyrrd/issues/detail?id=5&amp;amp;can=1"&gt;http://code.google.com/p/pyrrd/issues/detail?id=5&amp;amp;can=1&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-6886938781352367469?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/-ICn5wWw6i8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/6886938781352367469/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=6886938781352367469" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/6886938781352367469?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/6886938781352367469?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/-ICn5wWw6i8/new-pyrrd-release-007.html" title="New PyRRD Release: 0.0.7" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/03/new-pyrrd-release-007.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE4ER3o-eyp7ImA9WxVVFk8.&quot;"><id>tag:blogger.com,1999:blog-8825992.post-8924601113306776917</id><published>2009-03-09T12:30:00.004-05:00</published><updated>2009-03-09T13:21:46.453-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-09T13:21:46.453-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="presentations" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="pycon" /><category scheme="http://www.blogger.com/atom/ns#" term="pycon2009" /><title>Hot Talks at PyCon 2009</title><content type="html">&lt;div&gt;&lt;br /&gt;This year's PyCon talks look absolutely fabulous, and should be a real treat for attendees. I'm probably not going to be able to make it (working for a startup last year put me in a financial position I'm only slowly recovering from). Since it looks like the Landscape team won't be sprinting there this year, Canonical won't be footing the bill.&lt;br /&gt;&lt;br /&gt;Were I to attend, though, the talks I have my eyes on are the following (listed in visual scanning order of the &lt;a href="http://us.pycon.org/2009/conference/schedule/"&gt;schedule&lt;/a&gt;):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT28" href="http://us.pycon.org/2009/conference/schedule/event/28/"&gt;Twisted, AMQP and Thrift: Bridging messaging and RPC for building scalable distributed applications (#40)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT21" href="http://us.pycon.org/2009/conference/schedule/event/21/"&gt;Panel: Python VMs (#15)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT30" href="http://us.pycon.org/2009/conference/schedule/event/30/"&gt;Building tests for large, untested codebases (#112)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT31" href="http://us.pycon.org/2009/conference/schedule/event/31/"&gt;Introduction to Multiprocessing in Python (#6)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT33" href="http://us.pycon.org/2009/conference/schedule/event/33/"&gt;The State of the Python Community: Leading the Python tribe (#118)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT59" href="http://us.pycon.org/2009/conference/schedule/event/59/"&gt;PyPy status talk. (#72)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT69" href="http://us.pycon.org/2009/conference/schedule/event/69/"&gt;Concurrency and Distributed Computing with Python Today (#49)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT73" href="http://us.pycon.org/2009/conference/schedule/event/73/"&gt;Batteries Included!  Python on Low Cost Tiny Embedded Wireless Devices (#28)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT71" href="http://us.pycon.org/2009/conference/schedule/event/71/"&gt;Easy AI with Python (#115)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT75" href="http://us.pycon.org/2009/conference/schedule/event/75/"&gt;Abstraction as Leverage (#110)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a class="eventinfo" id="TT72" href="http://us.pycon.org/2009/conference/schedule/event/72/"&gt;Metaprogramming with Decorators and Metaclasses (#120)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;There are many different wonderful topics being covered at PyCon this year -- this just happens to be the list that converges most closely with my own interests :-) No offense if I've left you out!&lt;br /&gt;&lt;br /&gt;I will be sorry to have to miss these, but I will greatly look forward to their audio or video recordings as well as the presenters' published slides and papers.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8825992-8924601113306776917?l=oubiwann.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ElectricDuncan/~4/88904hYrgls" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://oubiwann.blogspot.com/feeds/8924601113306776917/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8825992&amp;postID=8924601113306776917" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/8924601113306776917?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8825992/posts/default/8924601113306776917?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ElectricDuncan/~3/88904hYrgls/hot-talks-at-pycon-2009.html" title="Hot Talks at PyCon 2009" /><author><name>Duncan McGreggor</name><uri>http://www.blogger.com/profile/17155270977759488515</uri><email>oubiwann@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="11761565810112908517" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://oubiwann.blogspot.com/2009/03/hot-talks-at-pycon-2009.html</feedburner:origLink></entry></feed>
