<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<feed xmlns="http://www.w3.org/2005/Atom">

	<title>Planet London Python</title>
	<link rel="self" href="http://londonpython.org.uk/atom.xml"/>
	<link href="http://londonpython.org.uk/"/>
	<id>http://londonpython.org.uk/atom.xml</id>
	<updated>2010-09-03T19:22:29+00:00</updated>
	<generator uri="http://www.planetplanet.org/">Planet/2.0 +http://www.planetplanet.org</generator>

	<entry xml:lang="en-us">
		<title type="html">Links for 2010-09-02 [del.icio.us]</title>
		<link href="http://feedproxy.google.com/~r/SmallValuesOfCool/~3/BiYTedOUUf8/brunns"/>
		<id>http://del.icio.us/brunns#2010-09-02</id>
		<updated>2010-09-03T07:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://lifehacker.com/5627286/battle-of-the-android-home-screen-launchers-adw-vs-launcherpro-vs-helixlauncher&quot;&gt;Battle of the Android Home Screen Launchers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
		<author>
			<name>Simon Brunning</name>
			<uri>http://www.brunningonline.net/simon/blog/</uri>
		</author>
		<source>
			<title type="html">Small Values of Cool</title>
			<subtitle type="html">Simon Brunning - stuff that I find interesting</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/SmallValuesOfCool"/>
			<id>http://feeds.feedburner.com/SmallValuesOfCool</id>
			<updated>2010-09-03T07:22:10+00:00</updated>
			<rights type="html">Copyright 2010</rights>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">IMAPClient 0.6.1 released</title>
		<link href="http://freshfoo.com/blog/IMAPClient-0.6.1"/>
		<id>http://freshfoo.com/blog/2010/09/02/IMAPClient-0.6.1</id>
		<updated>2010-09-02T21:56:00+00:00</updated>
		<content type="html">&lt;p&gt;I've just released IMAPClient 0.6.1.&lt;/p&gt;
&lt;p&gt;The only functional change in the release is that it now automatically
patches imaplib's IMAP4_SSL class to fix &lt;a class=&quot;reference external&quot; href=&quot;http://bugs.python.org/issue5949&quot;&gt;Python Issue 5949&lt;/a&gt;. This is
a bug that's been fixed in later Python 2.6 versions and 2.7 but still
exists in Python versions that are in common use. Without fix this you
may experience hangs when using SSL.&lt;/p&gt;
&lt;p&gt;The patch is only applied if the running Python version is known to be
one of the affected versions. It is applied when IMAPClient is
imported.&lt;/p&gt;
&lt;p&gt;The only other change in this release is that I've now marked
IMAPClient as &amp;quot;production ready&amp;quot; on PyPI and have updated the README
to match. This was prompted by a request to clarify the current status
of the project and seeing that all current functionality is solid and,
I don't plan to change the existing APIs in backwards-incompatible
ways, I've decided to indicate the project as suitable for production
use.&lt;/p&gt;
&lt;p&gt;As always, IMAPClient can be installed from PyPI (&lt;tt class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;pip&lt;/span&gt; &lt;span class=&quot;pre&quot;&gt;install&lt;/span&gt;
&lt;span class=&quot;pre&quot;&gt;imapclient&lt;/span&gt;&lt;/tt&gt;) or downloaded from the &lt;a class=&quot;reference external&quot; href=&quot;http://imapclient.freshfoo.com//&quot;&gt;IMAPClient site&lt;/a&gt;. Feedback, bug
reports and patches are most welcome.&lt;/p&gt;</content>
		<author>
			<name>Menno Smits</name>
			<email>menno AT freshfoo DOT com</email>
			<uri>http://freshfoo.com/blog</uri>
		</author>
		<source>
			<title type="html">Menno's Musings</title>
			<subtitle type="html">software | life | whatever</subtitle>
			<link rel="self" href="http://freshfoo.com/blog/index.atom"/>
			<id>http://freshfoo.com/blog/index.atom</id>
			<updated>2010-09-03T19:22:21+00:00</updated>
			<rights type="html">Copyright 2009 Menno Smits</rights>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-09-02</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/wzPXC2Eyoc0/"/>
		<id>http://www.magpiebrain.com/2010/09/02/links-for-2010-09-02/</id>
		<updated>2010-09-02T21:01:38+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://keynotekungfu.com/&quot;&gt;Keynote Wireframe Toolkit &amp;#8211; Get your Keynote Kung-Fu on&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/keynote&quot;&gt;keynote&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/prototyping&quot;&gt;prototyping&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/ux&quot;&gt;ux&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/ui&quot;&gt;ui&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/webdesign&quot;&gt;webdesign&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://keynotopia.com/&quot;&gt;Keynotopia &amp;#8211; Keynote themes and templates for interactive prototyping of iPad, iPhone, Android and web apps&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/keynote&quot;&gt;keynote&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/prototyping&quot;&gt;prototyping&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/ux&quot;&gt;ux&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/ui&quot;&gt;ui&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/webdesign&quot;&gt;webdesign&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=wzPXC2Eyoc0:xizVsxeEHiw:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=wzPXC2Eyoc0:xizVsxeEHiw:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=wzPXC2Eyoc0:xizVsxeEHiw:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=wzPXC2Eyoc0:xizVsxeEHiw:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=wzPXC2Eyoc0:xizVsxeEHiw:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Links for 2010-09-01 [del.icio.us]</title>
		<link href="http://feedproxy.google.com/~r/SmallValuesOfCool/~3/DFEzOgSpqSw/brunns"/>
		<id>http://del.icio.us/brunns#2010-09-01</id>
		<updated>2010-09-02T07:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.guardian.co.uk/music/musicblog/2010/sep/01/gender-stereotypes-indie-music&quot;&gt;Ask the indie professor: Are gender stereotypes still present in indie music?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
		<author>
			<name>Simon Brunning</name>
			<uri>http://www.brunningonline.net/simon/blog/</uri>
		</author>
		<source>
			<title type="html">Small Values of Cool</title>
			<subtitle type="html">Simon Brunning - stuff that I find interesting</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/SmallValuesOfCool"/>
			<id>http://feeds.feedburner.com/SmallValuesOfCool</id>
			<updated>2010-09-03T07:22:10+00:00</updated>
			<rights type="html">Copyright 2010</rights>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-09-01</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/tCii5xzKIzA/"/>
		<id>http://www.magpiebrain.com/2010/09/01/links-for-2010-09-01/</id>
		<updated>2010-09-01T21:03:12+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.exampler.com/blog/2010/09/01/editing-trees-in-clojure-with-clojurezip/&quot;&gt;“Editing” trees in Clojure with clojure.zip&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/clojure&quot;&gt;clojure&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/zip&quot;&gt;zip&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/tree&quot;&gt;tree&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.darkcoding.net/software/setting-up-munin-on-ubuntu/&quot;&gt;Graham King » Setting up Munin on Ubuntu&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/ubuntu&quot;&gt;ubuntu&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/munin&quot;&gt;munin&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/monitoring&quot;&gt;monitoring&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/sysadmin&quot;&gt;sysadmin&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/devops&quot;&gt;devops&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://munin-monitoring.org/&quot;&gt;Munin &amp;#8211; Trac&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;A Linux tool for monitoring resource trends&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/apache&quot;&gt;apache&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/resource&quot;&gt;resource&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/analysis&quot;&gt;analysis&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/logging&quot;&gt;logging&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/monitoring&quot;&gt;monitoring&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/sysadmin&quot;&gt;sysadmin&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/devops&quot;&gt;devops&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/munin&quot;&gt;munin&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://lanyrd.com/&quot;&gt;Lanyrd | the social conference directory&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/twitter&quot;&gt;twitter&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/conference&quot;&gt;conference&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/simonwillison&quot;&gt;simonwillison&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://gigix.agilechina.net/2010/9/1/migrating-to-a-decent-scm&quot;&gt;透明思考 | Migrating To A Decent SCM&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;How to move several thousand devs from clearcase to SVN in 7 days. ish.&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/scm&quot;&gt;scm&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/devops&quot;&gt;devops&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/clearcase&quot;&gt;clearcase&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/svn&quot;&gt;svn&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.graylog2.org/&quot;&gt;Home &amp;#8211; Graylog2 &amp;#8211; Free Open Source remote TCP/UDP Syslog daemon with Web Interface&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;An open-source syslog storage and viewing system using MongoDB and rails&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/syslog&quot;&gt;syslog&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/syadmin&quot;&gt;syadmin&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/logging&quot;&gt;logging&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/devops&quot;&gt;devops&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/rails&quot;&gt;rails&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/mongodb&quot;&gt;mongodb&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=tCii5xzKIzA:t8_2LOt6vUk:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=tCii5xzKIzA:t8_2LOt6vUk:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=tCii5xzKIzA:t8_2LOt6vUk:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=tCii5xzKIzA:t8_2LOt6vUk:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=tCii5xzKIzA:t8_2LOt6vUk:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Links for 2010-08-30 [del.icio.us]</title>
		<link href="http://feedproxy.google.com/~r/SmallValuesOfCool/~3/1-wLh8riss0/brunns"/>
		<id>http://del.icio.us/brunns#2010-08-30</id>
		<updated>2010-08-31T07:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://lifeunbounded.blogspot.com/2010/08/stepping-stones.html&quot;&gt;Stepping Stones&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nasa.gov/multimedia/imagegallery/image_feature_1748.html&quot;&gt;Galaxy at the Edge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
		<author>
			<name>Simon Brunning</name>
			<uri>http://www.brunningonline.net/simon/blog/</uri>
		</author>
		<source>
			<title type="html">Small Values of Cool</title>
			<subtitle type="html">Simon Brunning - stuff that I find interesting</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/SmallValuesOfCool"/>
			<id>http://feeds.feedburner.com/SmallValuesOfCool</id>
			<updated>2010-09-03T07:22:10+00:00</updated>
			<rights type="html">Copyright 2010</rights>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Preparedness,  Privilege and Discrimination</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/wgannH-wsRw/preparedness-privilege-and.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-1215412724317643549</id>
		<updated>2010-08-29T13:23:26+00:00</updated>
		<content type="html">Coming very late to the party I noticed a blog entry from June &lt;a href=&quot;http://www.stubbornella.org/content/2010/07/26/woman-in-technology/&quot;&gt;about the JavaScript community's response&lt;/a&gt; to Google's financial support to allow more women to attend JSConf Europe. It sounds like it was indeed the usual real can of worms, and many of the comments show the usual lack of appreciation of the problems from the privileged side of the issue (in this case men, since it is a gender issue and women appear to be about as well represented in the JavaScript community as they are in the Python world, which is to say hardly at all).&lt;br /&gt;
&lt;br /&gt;
The reason I found it interesting was that this year, for the first time, PyCon also used Google's support to fund the attendance for more women, who came from as far afield as Roumania and India. I was gratified to be told by several of those who would otherwise not have been at the conference how happy they were to have had the chance to attend. (In truth I had little to do with it: Google should get the credit for the funding, and the actual hard work was done by Peter Kropf and Gloria Willedsen). In the Python community's case there was one short period of adverse comment on the #python IRC channel, which resulted in my exchanging emails with one person to explain why I thought it was a good idea to encourage more women to be at PyCon. End of story, except that in 2010 women represented 11% of PyCon attendance, up from 2% the previous year. I count that as one of the better results of my time as chairman.&lt;br /&gt;
&lt;br /&gt;
Now I am not saying this to be smug, but because I believe there was a reason for the difference in the reactions. Last year the PSF, at Guido van Rossum's urging, started a diversity mailing list which discussed the questions of race, gender and other discrimination extensively and sometimes acrimoniously. Eventually this led to a proposal for a &quot;diversity statement&quot;, which was referred to the membership where it triggered another round of extensive and sometimes acrimonious discussions, leading to a referral back to the diversity list and a further proposal which was finally accepted by the membership more or less unchanged and adopted by the Board:&lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt;The Python Software Foundation and the global Python community welcome and encourage participation by everyone. Our community is based on mutual respect, tolerance, and encouragement, and we are working to help each other live up to these principles. We want our community to be more diverse: whoever you are, and whatever your background, we welcome you.&lt;/b&gt;&lt;/blockquote&gt;&lt;br /&gt;
This may not be the best statement ever, but if anyone bothers to look it does make it clear that these issues have been addressed. Thus anyone who feels discriminated against can decide that at least they would have a chance of a fair hearing should they choose to complain (which, sadly, I imagine most don't, instead choosing to vote with their feet). Similarly, anyone about to indulge in discriminatory behavior might think twice before doing so.&lt;br /&gt;
&lt;br /&gt;
The hidden benefit of this long-drawn-out process was the creation, on the diversity list, of a corpus of varied individuals who had discussed these&amp;nbsp; issues and hammered out a shared approach to the problems that included a refusal to punish individuals for things done out of ignorance. It also meant that when one speaker used a slightly ill-advised graphic in a presentation the issue was dealt with then and there in a very direct manner without any recriminations, and I didn't even get to hear about it until&amp;nbsp; much later that day. The speaker was advised that the material was inappropriate and that therefore the slides and the video of the talk wouldn't be published, and hopefully left without feeling that they weren't welcome at next year's conference.&lt;br /&gt;
&lt;br /&gt;
I hope that the JavaScript community manages to develop its own understanding of diversity issues and its own process for dealing with them. I know it took up a lot of my time as PSF chairman and gave me some uncomfortable moments (and does not exempt me from the results of my own stupidity in the future), but I am glad it led to a tolerant community process that nevertheless has made it clear that discrimination is not acceptable.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/496482-1215412724317643549?l=holdenweb.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=wgannH-wsRw:vpgHAFjwj0Q:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=wgannH-wsRw:vpgHAFjwj0Q:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=wgannH-wsRw:vpgHAFjwj0Q:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/wgannH-wsRw&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">The Hiring Smiley Curve</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/q02uUm9v8Fw/hiring-smiley-curve.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-6059789251297128229</id>
		<updated>2010-08-28T22:20:21+00:00</updated>
		<content type="html">I recently commented on how hi-tech companies seem to advertise for &quot;rock star&quot; developers. This appears to me to be a little shortsighted. Maybe Google have enough money to do it, but the average company looking for a singer wouldn't be able to go out and hire Mick Jagger or Van Morrison (yes, I know, I am showing my age - it will become obvious this isn't an accident). So why do they think they can afford the software equivalent?&lt;br /&gt;
&lt;br /&gt;
As I mature (that sounds so much less pejorative than &quot;grow older&quot;, doesn't it?) I have realized that my decision to eschew the corporate world and plough my own furrow wasn't entirely disastrous. I have been self-employed, or an employee of a company which I owned, for over twenty years now. The last large company I worked for was Sun Microsystems, and I left in 1988 after realizing that I was a misfit for the corporate environment. Since then I can honestly say I have never worked for a more charming or delightful person. Nowadays my boss never hesitates to take my interests into account.&lt;br /&gt;
&lt;br /&gt;
Just occasionally, I have toyed with the idea of third-party employment, most recently with Google (twice). The first time I explained before going for interview that I was not prepared to relocate to the West coast . At the time I was moving back from the UK to the USA, and had just bought a house in Virginia, so I was a little surprised to learn three weeks after my interview that &quot;we aren't prepared to make a remote hire, but would consider you for Mountain View&quot;. Large company mentality: ignore what the potential recruit wants, and try to hire them anyway. No sale. About a month ago they called me to ask if I would consider employment in the DC area, but it turned out they were only hiring for Java projects. &lt;a href=&quot;http://www.artima.com/weblogs/viewpost.jsp?thread=42242&quot;&gt;I used to write Java but I'm all right now&lt;/a&gt;, so the recruiter and I agreed to part company amicably after ten minutes on the 'phone.&lt;br /&gt;
&lt;br /&gt;
None of this amounts to a hill of beans but I was encouraged about a year ago, when I was talking to someone in New York City about experience levels and consulting opportunities, to learn about the &quot;smiley curve&quot; theory of work rewards. In brief, this theory says that you hire young raw recruits because they are full of energy and don't cost much. As people become more experienced they expect more money but their productivity doesn't go up commensurately, so they are less desirable but you need them because there aren't enough young turks to do all the work. Then, as you mature, your desirability goes up again because (direct quote, as far as I can remember) &quot;you have seen everything and you know everything&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot;&gt;&lt;a href=&quot;http://3.bp.blogspot.com/_JT1n2tt-4Wg/THmz-sXJ5LI/AAAAAAAAAXo/X12s_0qnmZM/s1600/text6359.png&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://3.bp.blogspot.com/_JT1n2tt-4Wg/THmz-sXJ5LI/AAAAAAAAAXo/X12s_0qnmZM/s320/text6359.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot;&gt;&lt;/div&gt;If true, this is quite encouraging. There must be lots of companies looking for someone as experienced as me. The only question now is whether they can afford me!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/496482-6059789251297128229?l=holdenweb.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=q02uUm9v8Fw:iykKk19gEyc:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=q02uUm9v8Fw:iykKk19gEyc:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=q02uUm9v8Fw:iykKk19gEyc:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/q02uUm9v8Fw&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Links for 2010-08-27 [del.icio.us]</title>
		<link href="http://feedproxy.google.com/~r/SmallValuesOfCool/~3/96FMrrbT1po/brunns"/>
		<id>http://del.icio.us/brunns#2010-08-27</id>
		<updated>2010-08-28T07:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.guardian.co.uk/uk/2010/aug/13/london-underground-runaway-train-tube&quot;&gt;Runaway tube train prompts London Underground inquiry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wearehugh.com/public/2010/08/html5-web-workers/&quot;&gt;An implausibly illustrated introduction to HTML5 Web Workers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://psoug.org/reference/datatypes.html&quot;&gt;Oracle Data Types &amp;amp; Subtypes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.techonthenet.com/oracle/check.php&quot;&gt;Oracle/PLSQL Check Constraints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.guardian.co.uk/lg-talking-technology/top-50-apps&quot;&gt;Top 50 Android apps | guardian.co.uk&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
		<author>
			<name>Simon Brunning</name>
			<uri>http://www.brunningonline.net/simon/blog/</uri>
		</author>
		<source>
			<title type="html">Small Values of Cool</title>
			<subtitle type="html">Simon Brunning - stuff that I find interesting</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/SmallValuesOfCool"/>
			<id>http://feeds.feedburner.com/SmallValuesOfCool</id>
			<updated>2010-09-03T07:22:10+00:00</updated>
			<rights type="html">Copyright 2010</rights>
		</source>
	</entry>

	<entry xml:lang="en-uk">
		<title type="html">Musings about django.contrib.auth.models.User</title>
		<link href="http://www.peterbe.com/plog/musings-about-django.contrib.auth.models.user"/>
		<id>http://www.peterbe.com/plog/musings-about-django.contrib.auth.models.user</id>
		<updated>2010-08-27T20:15:00+00:00</updated>
		<content type="html">&lt;p&gt;Dawned on me that the Django auth user model that ships with Django is like the string built-in of a high level programming language. With the string built-in it's oh so tempting to add custom functionality to it like a fancy captialization method or some other function that automatically strips whitespace or what not. Yes, I'm looking at you Prototype for example.&lt;/p&gt;
&lt;p&gt;By NOT doing that, and leaving it as it is, you automatically manage to Keep It Simple Stupid and your application code makes sense to the next developer who joins your project. &lt;/p&gt;
&lt;p&gt;I'm not a smart programmer but I'm a smart developer in that I'm good at keeping things pure and simple. It means I can't show off any fancy generators, monads or metaclasses but it does mean that fellow coders who follow my steps can more quickly hit the ground running. &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.fry-it.com/&quot;&gt;My colleagues&lt;/a&gt; and I now have more than ten Django projects that rely on, without overriding, the &lt;code&gt;django.contrib.auth.models.User&lt;/code&gt; class and there has been many times where I've been tempted to use it as a base class or something instead but in retrospect I'm wholeheartedly happy I didn't. The benefit isn't technical; it's a matter of teamwork and holistic  productivity. &lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com</uri>
		</author>
		<source>
			<title type="html">Peterbe.com</title>
			<subtitle type="html">Peter Bengtssons's personal homepage about little things that concern him.</subtitle>
			<link rel="self" href="http://www.peterbe.com/rss.xml?oc=Python&amp;oc=Zope"/>
			<id>http://www.peterbe.com/rss.xml?oc=Python&amp;oc=Zope</id>
			<updated>2010-09-03T19:22:11+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Apple Going Over the Top?</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/W_mc_9nro9M/apple-going-over-top.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-1657474676348969025</id>
		<updated>2010-08-27T18:24:25+00:00</updated>
		<content type="html">Yet again I rejoice that I am not an iPhone user. Indeed, given this latest news I might well just chuck&amp;nbsp; my Mac mini away in protest (no, you probably don't want it - it's an aging obsolete PPC mini from about six years ago).&lt;br /&gt;
&lt;br /&gt;
In &lt;a href=&quot;https://www.eff.org/deeplinks/2010/08/steve-jobs-watching-you-apple-seeking-patent-0&quot;&gt;news from the Electronic Frontier Foundation&lt;/a&gt; I learned today that Apple has applied for patents on method of spying intrusively on the users of their devices. Here's a partial list of possible applications:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;The system can take a picture of the user's face, &quot;without a flash,  any noise, or any indication that a picture is being taken to prevent  the current user from knowing he is being photographed&quot;;&lt;/li&gt;
&lt;li&gt;The system can record the user's voice, whether or not a phone call is even being made;&lt;/li&gt;
&lt;li&gt;The system can determine the user's unique individual heartbeat &quot;signature&quot;;&lt;/li&gt;
&lt;li&gt;To determine if the device has been hacked, the device can watch for  &quot;a sudden increase in memory usage of the electronic device&quot;;&lt;/li&gt;
&lt;li&gt;The user's &quot;Internet activity can be monitored or any communication  packets that are served to the electronic device can be recorded&quot;; and&lt;/li&gt;
&lt;li&gt;The device can take a photograph of the surrounding location to determine where it is being used.&lt;/li&gt;
&lt;/ul&gt;So enjoy your iPhones. I won;t be doing business with a company that thinks this way. Sigh. I suppose that means the new laptop will have to be PC based.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/496482-1657474676348969025?l=holdenweb.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=W_mc_9nro9M:iLbiGMN14pM:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=W_mc_9nro9M:iLbiGMN14pM:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=W_mc_9nro9M:iLbiGMN14pM:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/W_mc_9nro9M&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Links for 2010-08-26 [del.icio.us]</title>
		<link href="http://feedproxy.google.com/~r/SmallValuesOfCool/~3/gKt0FGg3y4I/brunns"/>
		<id>http://del.icio.us/brunns#2010-08-26</id>
		<updated>2010-08-27T07:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html&quot;&gt;The History of Python: Why Python's Integer Division Floors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rocketpunk-manifesto.com/2010/08/in-which-i-bash-space-colonization.html&quot;&gt;In Which I Bash Space Colonization Again&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.technologyreview.com/blog/arxiv/25673/?ref=rss&quot;&gt;Fine Structure Constant Varies With Direction in Space, Says New Data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
		<author>
			<name>Simon Brunning</name>
			<uri>http://www.brunningonline.net/simon/blog/</uri>
		</author>
		<source>
			<title type="html">Small Values of Cool</title>
			<subtitle type="html">Simon Brunning - stuff that I find interesting</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/SmallValuesOfCool"/>
			<id>http://feeds.feedburner.com/SmallValuesOfCool</id>
			<updated>2010-09-03T07:22:10+00:00</updated>
			<rights type="html">Copyright 2010</rights>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Links for 2010-08-25 [del.icio.us]</title>
		<link href="http://feedproxy.google.com/~r/SmallValuesOfCool/~3/4TZl6bp4pmo/brunns"/>
		<id>http://del.icio.us/brunns#2010-08-25</id>
		<updated>2010-08-26T07:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://git-scm.com/course/svn.html&quot;&gt;Git - SVN Crash Course&lt;/a&gt;&lt;br /&gt;
Git for SVN users.&lt;/li&gt;
&lt;/ul&gt;</content>
		<author>
			<name>Simon Brunning</name>
			<uri>http://www.brunningonline.net/simon/blog/</uri>
		</author>
		<source>
			<title type="html">Small Values of Cool</title>
			<subtitle type="html">Simon Brunning - stuff that I find interesting</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/SmallValuesOfCool"/>
			<id>http://feeds.feedburner.com/SmallValuesOfCool</id>
			<updated>2010-09-03T07:22:10+00:00</updated>
			<rights type="html">Copyright 2010</rights>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-25</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/oYd6i9G77Q4/"/>
		<id>http://www.magpiebrain.com/2010/08/25/links-for-2010-08-25/</id>
		<updated>2010-08-25T21:01:42+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://developer.fellowshipone.com/patterns/&quot;&gt;Design Patterns Library | Fellowship Technologies&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;interesting collection of design patterns for Web UIs.&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/web&quot;&gt;web&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/designpatterns&quot;&gt;designpatterns&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/ux&quot;&gt;ux&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://cemerick.com/2010/08/24/hosting-maven-repos-on-github/&quot;&gt;Hosting Maven Repos on Github | cemerick&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;So basically, it&amp;#039;s a level of redirection on just checking the dependencies in in the first place.&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/maven&quot;&gt;maven&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/dependencymanagement&quot;&gt;dependencymanagement&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/git&quot;&gt;git&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/github&quot;&gt;github&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=oYd6i9G77Q4:2oBjdEs2K3Y:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=oYd6i9G77Q4:2oBjdEs2K3Y:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=oYd6i9G77Q4:2oBjdEs2K3Y:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=oYd6i9G77Q4:2oBjdEs2K3Y:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=oYd6i9G77Q4:2oBjdEs2K3Y:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Links for 2010-08-24 [del.icio.us]</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/bcYlVTjcOZE/steve.holden"/>
		<id>http://del.icio.us/steve.holden#2010-08-24</id>
		<updated>2010-08-25T07:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.slideshare.net/adamwiggins/cloud-services&quot;&gt;Cloud Services&lt;/a&gt;&lt;br /&gt;
If Grig Gheorghiu says this guy knows what he&amp;#039;s talking about, he probably does&lt;/li&gt;
&lt;/ul&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/bcYlVTjcOZE&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Links for 2010-08-24 [del.icio.us]</title>
		<link href="http://feedproxy.google.com/~r/SmallValuesOfCool/~3/Ncz1jTVQL3c/brunns"/>
		<id>http://del.icio.us/brunns#2010-08-24</id>
		<updated>2010-08-25T07:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://lifehacker.com/5616299/lifehacker-pack-for-android-our-list-of-the-best-android-apps&quot;&gt;Lifehacker Pack for Android: Our List of the Best Android Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bitbucket.org/Anay/buildnotify/&quot;&gt;BuildNotify&lt;/a&gt;&lt;br /&gt;
CCMenu equivalent for Ubuntu.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/AlexZeitler/gitcheatsheet&quot;&gt;AlexZeitler's gitcheatsheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://techcheatsheets.com/&quot;&gt;TechCheatSheets.com&lt;/a&gt;&lt;br /&gt;
What it says on the tin.&lt;/li&gt;
&lt;/ul&gt;</content>
		<author>
			<name>Simon Brunning</name>
			<uri>http://www.brunningonline.net/simon/blog/</uri>
		</author>
		<source>
			<title type="html">Small Values of Cool</title>
			<subtitle type="html">Simon Brunning - stuff that I find interesting</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/SmallValuesOfCool"/>
			<id>http://feeds.feedburner.com/SmallValuesOfCool</id>
			<updated>2010-09-03T07:22:10+00:00</updated>
			<rights type="html">Copyright 2010</rights>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-23</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/ROUO62g5e88/"/>
		<id>http://www.magpiebrain.com/2010/08/23/links-for-2010-08-23/</id>
		<updated>2010-08-23T21:03:11+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://github.com/hugoduncan/clj-ssh&quot;&gt;hugoduncan&amp;#039;s clj-ssh at master &amp;#8211; GitHub&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;A clojure wrapper over jsch&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/ssh&quot;&gt;ssh&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/clojure&quot;&gt;clojure&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/sysadmin&quot;&gt;sysadmin&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://bldgblog.blogspot.com/2010/08/pallet-house.html&quot;&gt;BLDGBLOG: Pallet House&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;Several kinds of awesome&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/architecture&quot;&gt;architecture&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/reuse&quot;&gt;reuse&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/recycling&quot;&gt;recycling&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/building&quot;&gt;building&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/temporary&quot;&gt;temporary&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=ROUO62g5e88:p4XHDcKUsnY:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=ROUO62g5e88:p4XHDcKUsnY:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=ROUO62g5e88:p4XHDcKUsnY:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=ROUO62g5e88:p4XHDcKUsnY:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=ROUO62g5e88:p4XHDcKUsnY:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Running CherryPy on Android with SL4A</title>
		<link href="http://www.defuze.org/archives/228-running-cherrypy-on-android-with-sl4a.html"/>
		<id>http://www.defuze.org/?p=228</id>
		<updated>2010-08-23T20:05:12+00:00</updated>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://www.cherrypy.org&quot;&gt;CherryPy&lt;/a&gt; runs on &lt;a href=&quot;http://developer.android.com&quot; target=&quot;_blank&quot;&gt;Android&lt;/a&gt; thanks to the &lt;a href=&quot;http://code.google.com/p/android-scripting/&quot; target=&quot;_blank&quot;&gt;SL4A&lt;/a&gt; project. So if you feel like running Python and your own web server on your Android device, well you can just do so. You&amp;#8217;ve probably not heard something that awesome since the pizza delivery guy rung the door.&lt;/p&gt;
&lt;p&gt;How to get on about it? Well that&amp;#8217;s the surprise, CherryPy in itself doesn&amp;#8217;t need to be patched. Granted I haven&amp;#8217;t tried all the various tools provided by CherryPy but the server and the dispatching works just fine.&lt;/p&gt;
&lt;p&gt;First, you need get the CherryPy source code, build and copy the resulting cherrypy package into the SL4A scripts directory.&lt;/p&gt;
&lt;p&gt;Once you&amp;#8217;ve plugged your phone to your machine through USB, run the next commands:&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;bash&quot;&gt;$ &lt;span&gt;svn&lt;/span&gt; &lt;span&gt;co&lt;/span&gt; http:&lt;span&gt;//&lt;/span&gt;svn.cherrypy.org&lt;span&gt;/&lt;/span&gt;trunk cp3-trunk
$ &lt;span&gt;cd&lt;/span&gt; cp3-trunk
$ python setup.py build
$ &lt;span&gt;cp&lt;/span&gt; &lt;span&gt;-r&lt;/span&gt; build&lt;span&gt;/&lt;/span&gt;lib.linux-i686-&lt;span&gt;2.6&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;cherrypy&lt;span&gt;/&lt;/span&gt; &lt;span&gt;/&lt;/span&gt;media&lt;span&gt;/&lt;/span&gt;usb0&lt;span&gt;/&lt;/span&gt;sl4a&lt;span&gt;/&lt;/span&gt;scripts&lt;span&gt;/&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Just change the path to match your environment. That&amp;#8217;s it.&lt;/p&gt;
&lt;p&gt;Now you can copy your own script, let&amp;#8217;s assume you use something like below:&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span&gt;import&lt;/span&gt; &lt;span&gt;logging&lt;/span&gt;
&lt;span&gt;# The multiprocessing package isn't&lt;/span&gt;
&lt;span&gt;# part of the ASE installation so&lt;/span&gt;
&lt;span&gt;# we must disable multiprocessing logging&lt;/span&gt;
&lt;span&gt;logging&lt;/span&gt;.&lt;span&gt;logMultiprocessing&lt;/span&gt; = &lt;span&gt;0&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;import&lt;/span&gt; android
&lt;span&gt;import&lt;/span&gt; cherrypy
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; Root&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;droid&lt;/span&gt; = android.&lt;span&gt;Android&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    @cherrypy.&lt;span&gt;expose&lt;/span&gt;
    &lt;span&gt;def&lt;/span&gt; index&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;droid&lt;/span&gt;.&lt;span&gt;vibrate&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;&amp;quot;Hello from my phone&amp;quot;&lt;/span&gt;
&amp;nbsp;
    @cherrypy.&lt;span&gt;expose&lt;/span&gt;
    &lt;span&gt;def&lt;/span&gt; location&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        location = &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;droid&lt;/span&gt;.&lt;span&gt;getLastKnownLocation&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;.&lt;span&gt;result&lt;/span&gt;
        location = location.&lt;span&gt;get&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'network'&lt;/span&gt;, location.&lt;span&gt;get&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'gps'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;&amp;quot;LAT: %s, LON: %s&amp;quot;&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;location&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'latitude'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;,
                                     location&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'longitude'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;def&lt;/span&gt; run&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
    cherrypy.&lt;span&gt;config&lt;/span&gt;.&lt;span&gt;update&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#123;&lt;/span&gt;&lt;span&gt;'server.socket_host'&lt;/span&gt;: &lt;span&gt;'0.0.0.0'&lt;/span&gt;&lt;span&gt;&amp;#125;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    cherrypy.&lt;span&gt;quickstart&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;Root&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;, &lt;span&gt;'/'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;if&lt;/span&gt; __name__ == &lt;span&gt;'__main__'&lt;/span&gt;:
    run&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see we must disable the multiprocessing logging since the multiprocessing package isn&amp;#8217;t included with SL4A. &lt;/p&gt;
&lt;p&gt;Save that script on your computer as cpdroid.py for example. Copy that file into the scripts directory of SL4A.&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;bash&quot;&gt;$ &lt;span&gt;cp&lt;/span&gt; cpdroid.py &lt;span&gt;/&lt;/span&gt;media&lt;span&gt;/&lt;/span&gt;usb0&lt;span&gt;/&lt;/span&gt;sl4a&lt;span&gt;/&lt;/span&gt;scripts&lt;span&gt;/&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unplug your phone and go to the SL4A application. Click on the cpdroid.py script, it should start fine. Then from your browser, go to http://phone_IP:8080/ and tada! You can also go to the /location path to get the geoloc of your phone.&lt;/p&gt;</content>
		<author>
			<name>Sylvain Hellegouarch</name>
			<uri>http://www.defuze.org</uri>
		</author>
		<source>
			<title type="html">defuze.org</title>
			<link rel="self" href="http://www.defuze.org/feed/atom"/>
			<id>http://www.defuze.org/feed/atom</id>
			<updated>2010-08-23T21:22:33+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Windows Vista Mystery Shares</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/AQEbYzaNcHc/windows-vista-mystery-shares.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-1976183560008121164</id>
		<updated>2010-08-22T22:41:41+00:00</updated>
		<content type="html">&lt;a href=&quot;http://3.bp.blogspot.com/_JT1n2tt-4Wg/THHOMozl30I/AAAAAAAAAXQ/041-a7h_oek/s1600/SharedFolders.png&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://3.bp.blogspot.com/_JT1n2tt-4Wg/THHOMozl30I/AAAAAAAAAXQ/041-a7h_oek/s320/SharedFolders.png&quot; /&gt;&lt;/a&gt;For reasons best known to Microsoft, when I try to delete a folder which has been shared (through the Explorer interface) it takes &lt;i&gt;forever&lt;/i&gt; to complete. This would not be so bad if there were just one or two shares, but sadly (for reasons best known to Microsoft) a large number of folders randomly appear to have become shares (see the screen dump of a portion of my home directory at the right). I have no idea how these folders became shared. It certainly wasn't any intentional act of mine, and heaven alone knows what this does to performance.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot;&gt;&lt;a href=&quot;http://3.bp.blogspot.com/_JT1n2tt-4Wg/THHPeEkfw2I/AAAAAAAAAXY/raO0gnl0cwk/s1600/NotShared.png&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://3.bp.blogspot.com/_JT1n2tt-4Wg/THHPeEkfw2I/AAAAAAAAAXY/raO0gnl0cwk/s320/NotShared.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Now, you are probably wondering why I don't just switch off sharing before I delete the directory. The answer to that is that although Windows is displaying the folders as shared, it doesn't really seem to believe that they are shared. So there doesn't appear to be an easy way to switch this sharing off.&lt;br /&gt;
&lt;br /&gt;
If I had some idea how it had been switched on in the first place that might help, but as with so many other aspects of Windows performance this remains a mystery. If someone cold offer some insight I'd be happy to find out what's going on here.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/496482-1976183560008121164?l=holdenweb.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=AQEbYzaNcHc:mboiL67UESM:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=AQEbYzaNcHc:mboiL67UESM:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=AQEbYzaNcHc:mboiL67UESM:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/AQEbYzaNcHc&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Weekly python tips (WeeklyPyTips) mailing list</title>
		<link href="http://ianozsvald.com/2010/08/22/weekly-python-tips-weeklypytips-mailing-list/"/>
		<id>http://ianozsvald.com/?p=1014</id>
		<updated>2010-08-21T23:20:47+00:00</updated>
		<content type="html">&lt;p&gt;I&amp;#8217;ve just written the first few weeks worth of Python Tips for my new list: &lt;b&gt;weeklypytips AT aweber.com&lt;/b&gt; or use the form below.&lt;/p&gt;
&lt;p&gt;The list is aimed at beginner and intermediate Pythonistas, if you join then each week you&amp;#8217;ll receive a Python tip (probably 3-6 paragraphs with source code). I originally &lt;a href=&quot;http://www.mail-archive.com/tutor@python.org/msg43840.html&quot;&gt;announced&lt;/a&gt; it in the Python Tutor list.&lt;/p&gt;
&lt;p&gt;The first batch of tips cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Downloading files from the Internet in just 2 lines&lt;/li&gt;
&lt;li&gt;Scraping web sites&lt;/li&gt;
&lt;li&gt;IPython introduction&lt;/li&gt;
&lt;li&gt;Iteration&lt;/li&gt;
&lt;li&gt;Controlling hardware (including serial ports, cameras and robots)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have a long list of topics to cover, if the feedback is positive then I&amp;#8217;ll keep adding the tips. To join the list just mail the email address above (the email can be empty), you&amp;#8217;ll be asked to confirm your subscription, after that you&amp;#8217;ll get one tip per week.&lt;/p&gt;
&lt;p&gt;To make it really easy just use the form below:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;hr /&gt;
Ian applies Artificial Intelligence for companies (&lt;a href=&quot;http://morconsulting.com&quot; title=&quot;Artificial Intelligence consultant&quot;&gt;Mor Consulting&lt;/a&gt;), programs Python, 
produces professional screencasts (&lt;a href=&quot;http://procasts.co.uk/examples.html&quot; title=&quot;Professional screencast production&quot;&gt;ProCasts&lt;/a&gt;), writes &lt;a href=&quot;http://TheScreencastingHandbook.com&quot; title=&quot;Screencasting Tutorial eBook&quot;&gt;The Screencasting Handbook&lt;/a&gt; and is also a sea-side dweller and consumer of fine coffees.

&lt;!--
google_ad_client = &quot;pub-9428211972348006&quot;;
/* 300x250, created 8/6/10 */
google_ad_slot = &quot;2197971840&quot;;
google_ad_width = 300;
google_ad_height = 250;
//--&gt;</content>
		<author>
			<name>Ian Ozsvald</name>
			<uri>http://ianozsvald.com</uri>
		</author>
		<source>
			<title type="html">Entrepreneurial Geekiness » Python</title>
			<subtitle type="html">My thoughts on screencasting, ProCasts and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2010-09-01T17:22:21+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-20</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/f5fG5Gm9hOM/"/>
		<id>http://www.magpiebrain.com/2010/08/20/links-for-2010-08-20/</id>
		<updated>2010-08-20T21:02:02+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://blog.redbot.org/command-line-redbot&quot;&gt;Command-Line REDbot &amp;#8211; RED news and information&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;A command-line interface for the cache header checking redbot. Very cool.&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/redbot&quot;&gt;redbot&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/http&quot;&gt;http&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/cache&quot;&gt;cache&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/python&quot;&gt;python&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://redbot.org/&quot;&gt;RED&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;The Resource Expert Droid is an online app which validates cache headers for HTTP ans gives advice on them. Mundo coolio.&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/http&quot;&gt;http&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/cache&quot;&gt;cache&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/validation&quot;&gt;validation&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/onlineapps&quot;&gt;onlineapps&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=f5fG5Gm9hOM:9dB5HRtjsNw:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=f5fG5Gm9hOM:9dB5HRtjsNw:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=f5fG5Gm9hOM:9dB5HRtjsNw:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=f5fG5Gm9hOM:9dB5HRtjsNw:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=f5fG5Gm9hOM:9dB5HRtjsNw:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-19</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/kU4OFtG-v5U/"/>
		<id>http://www.magpiebrain.com/2010/08/19/links-for-2010-08-19/</id>
		<updated>2010-08-19T21:02:44+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/&quot;&gt;Structure and Interpretation of Computer Programs, Video Lectures&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;Video lectures from the SICP authors&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/video&quot;&gt;video&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/sicp&quot;&gt;sicp&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/lisp&quot;&gt;lisp&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/mit&quot;&gt;mit&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=kU4OFtG-v5U:Rvv-K639f3s:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=kU4OFtG-v5U:Rvv-K639f3s:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=kU4OFtG-v5U:Rvv-K639f3s:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=kU4OFtG-v5U:Rvv-K639f3s:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=kU4OFtG-v5U:Rvv-K639f3s:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-18</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/yxT1WQ9f9H0/"/>
		<id>http://www.magpiebrain.com/2010/08/18/links-for-2010-08-18/</id>
		<updated>2010-08-18T21:01:32+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.eyesonafrica.net/safari-photography.htm&quot;&gt;African Safari Photography &amp;amp; Safari Photography Tips&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/camera&quot;&gt;camera&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/photography&quot;&gt;photography&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/safari&quot;&gt;safari&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/tips&quot;&gt;tips&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.luminous-landscape.com/essays/Safari-Tips.shtml&quot;&gt;Digital Safari Equipment Tips&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/safari&quot;&gt;safari&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/digital&quot;&gt;digital&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/photography&quot;&gt;photography&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/camera&quot;&gt;camera&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/tips&quot;&gt;tips&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://nakkaya.com/2010/08/17/visualising-the-wikileaks-war-logs-using-clojure/&quot;&gt;Visualising the Wikileak&amp;#039;s war logs using Clojure&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;In a similar vein to my recent Clojure &amp;amp; Incanter work, albeit with slightly more important data&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/incanter&quot;&gt;incanter&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/clojure&quot;&gt;clojure&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/war&quot;&gt;war&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/afghanistan&quot;&gt;afghanistan&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/guardian&quot;&gt;guardian&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=yxT1WQ9f9H0:5gsosL35L1g:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=yxT1WQ9f9H0:5gsosL35L1g:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=yxT1WQ9f9H0:5gsosL35L1g:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=yxT1WQ9f9H0:5gsosL35L1g:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=yxT1WQ9f9H0:5gsosL35L1g:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-17</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/1OYZ1beInDA/"/>
		<id>http://www.magpiebrain.com/2010/08/17/links-for-2010-08-17/</id>
		<updated>2010-08-17T21:02:40+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://wearehugh.com/public/2010/08/html5-web-workers/&quot;&gt;An implausibly illustrated introduction to HTML5 Web Workers&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/browser&quot;&gt;browser&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/javascript&quot;&gt;javascript&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/multithreaded&quot;&gt;multithreaded&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://gizmodo.com/5613794/what-is-exactly-a-doctorate&quot;&gt;What Exactly Is a Doctorate?&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;Fantastic pictorial representation of a PHD&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/phd&quot;&gt;phd&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/visualization&quot;&gt;visualization&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/visualrepresentations&quot;&gt;visualrepresentations&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=1OYZ1beInDA:i-BrZ7XchFQ:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=1OYZ1beInDA:i-BrZ7XchFQ:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=1OYZ1beInDA:i-BrZ7XchFQ:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=1OYZ1beInDA:i-BrZ7XchFQ:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=1OYZ1beInDA:i-BrZ7XchFQ:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Schmidt Foot-In-Mouth Attack Continues</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/HDhKOoaO9sk/schmidt-foot-in-mouth-attack-continues.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-2376652610562028144</id>
		<updated>2010-08-16T22:52:36+00:00</updated>
		<content type="html">Wow, two consecutive Eric Schmidt posts. But this really is quite newsworthy. An interview with Wall Street Journal published on Saturday claims&lt;br /&gt;
&lt;blockquote&gt;He predicts, apparently seriously, that every young person one day will  be entitled automatically to change his or her name on reaching  adulthood in order to disown youthful hijinks stored on their friends'  social media sites.&amp;nbsp;&lt;/blockquote&gt;&lt;br /&gt;
This really is the most patent hogwash. Surely someone like Schmidt, with a brain the size of a planet, could foresee that if such name changing were to become commonplace it would inevitably lead to the creation of services that mapped between past and present-day identities? Given the ability to identify images recently demonstrated by sites like &lt;a href=&quot;http://tineye.com/&quot;&gt;tineye.com&lt;/a&gt; it's only a matter of time before changing your name will no longer be a way to erase the records of your misdeeds.&lt;br /&gt;
&lt;br /&gt;
This makes it all the more important that privacy and basic information security become high school subjects, but alas the corporate overlords that have the ear of government in most developed (and many less-developed) countries will be attempting to make sure that isn't a priority, because it isn't in their interests.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/496482-2376652610562028144?l=holdenweb.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=HDhKOoaO9sk:bkKAFzF0Dck:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=HDhKOoaO9sk:bkKAFzF0Dck:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=HDhKOoaO9sk:bkKAFzF0Dck:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/HDhKOoaO9sk&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-16</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/a7RmGyPjz-8/"/>
		<id>http://www.magpiebrain.com/2010/08/16/links-for-2010-08-16/</id>
		<updated>2010-08-16T21:02:52+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://mmcgrana.github.com/2010/08/clj-http-clojure-http-client.html&quot;&gt;Clj-http. A new http client for clojure.&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/http&quot;&gt;http&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/clojure&quot;&gt;clojure&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://data-sorcery.org/2010/02/05/pdf-charts/&quot;&gt;Saving Incanter charts as PDF documents | Data Sorcery with Clojure&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/incanter&quot;&gt;incanter&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/pdf&quot;&gt;pdf&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/clojure&quot;&gt;clojure&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=a7RmGyPjz-8:gqaGxmOqz38:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=a7RmGyPjz-8:gqaGxmOqz38:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=a7RmGyPjz-8:gqaGxmOqz38:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=a7RmGyPjz-8:gqaGxmOqz38:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=a7RmGyPjz-8:gqaGxmOqz38:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Graphing Unique Users With Incanter</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/0oaUmxWQz9M/"/>
		<id>http://www.magpiebrain.com/?p=938</id>
		<updated>2010-08-16T19:02:13+00:00</updated>
		<content type="html">&lt;p&gt;In a previous post, I showed how we could use Clojure and specifically Incanter to process access logs to graph hits on our site. Now, we&amp;#8217;re going to adapt our solution to allow us to to show the number of unique users over time. &lt;/p&gt;
&lt;p&gt;We&amp;#8217;re going to change the previous solution to pull out the core dataset representing the raw data we&amp;#8217;re interested in from the access log &amp;#8211; &lt;code&gt;records-from-access-log&lt;/code&gt; remains unchanged from before:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
(defn access-log-to-dataset
  [filename]
  (col-names (to-dataset (records-from-access-log filename)) [&quot;Date&quot; &quot;User&quot;]))
&lt;/pre&gt;
&lt;p&gt;The raw dataset retrieved from this call looks like this:&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;User&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11/Aug/2010:00:00:30 +0100&lt;/td&gt;
&lt;td&gt;Bob&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11/Aug/2010:00:00:31 +0100&lt;/td&gt;
&lt;td&gt;Frank&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11/Aug/2010:00:00:34 +0100&lt;/td&gt;
&lt;td&gt;Frank&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Now, we need to work out the number of unique users in a given time period. Like before, we&amp;#8217;re going to use &lt;code&gt;$rollup&lt;/code&gt; to group multiple records by minute, but we need to work out how to summarise the user column. To do this, we create a custom summarise function which calculates the number of unique users:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
(defn num-unique-items
  [seq]
  (count (set seq)))
&lt;/pre&gt;
&lt;p&gt;Then use that to modify the raw dataset and graph the resulting dataset:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
(defn access-log-to-unique-user-dataset
  [access-log-dataset]
    ($rollup num-unique-items &quot;User&quot; &quot;Date&quot;
      (col-names (conj-cols ($map #(round-ms-down-to-nearest-min (as-millis %)) &quot;Date&quot; access-log-dataset) ($ &quot;User&quot; access-log-dataset)) [&quot;Date&quot; &quot;Unique Users&quot;])))

(defn concurrent-users-graph
  [dataset]
  (time-series-plot :Date :User
                             :x-label &quot;Date&quot;
                             :y-label &quot;User&quot;
                             :title &quot;Users Per Min&quot;
                             :data (access-log-to-unique-user-dataset dataset)))

(def access-log-dataset
  (access-log-to-dataset &quot;/path/to/access.log&quot;))

(save (concurrent-users-graph access-log-dataset) &quot;unique-users.png&quot;)
&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://www.magpiebrain.com/wp-content/uploads/2010/08/unique-users.png&quot;&gt;&lt;img src=&quot;http://www.magpiebrain.com/wp-content/uploads/2010/08/unique-users-300x239.png&quot; alt=&quot;&quot; title=&quot;unique-users&quot; width=&quot;300&quot; height=&quot;239&quot; class=&quot;aligncenter size-medium wp-image-939&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see the full source code listing &lt;a href=&quot;http://gist.github.com/527531&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=0oaUmxWQz9M:ZTwamKtY150:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=0oaUmxWQz9M:ZTwamKtY150:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=0oaUmxWQz9M:ZTwamKtY150:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=0oaUmxWQz9M:ZTwamKtY150:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=0oaUmxWQz9M:ZTwamKtY150:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">I’m a Windows Person. How can I contribute to Python? [Part I]</title>
		<link href="http://ramblings.timgolden.me.uk/2010/08/16/im-a-windows-person-how-can-i-contribute-to-python-part-i/"/>
		<id>http://ramblings.timgolden.me.uk/2010/08/16/im-a-windows-person-how-can-i-contribute-to-python-part-i/</id>
		<updated>2010-08-16T13:24:00+00:00</updated>
		<content type="html">&lt;p&gt;If I might essay a generalisation: Windows-based users of Python are less likely to have become involved in the development of Python itself. This might be for the same reasons that other people don’t get involved: a lack of time, of inclination, or of confidence in their ability to help. But it might be because Windows users on the whole aren’t so accustomed to delving into the source code of the things they use, nor are they used to checking out from source control, testing fixes and rebuilding. It’s not so much part of the culture.&lt;/p&gt;
&lt;p&gt;I’m keen to see more Windows users &amp;amp; developers active in core CPython development. Python has been supported on Windows for a long time by the core development team but it can sometimes feel a little bit like a poor cousin. The majority of Python users (and of key Python developers) are Unix-based: traditionally Linux &amp;amp; BSD, these days often OS X. Even if they’re not unsympathetic to the needs of Windows users, they may not be be in a position to help. But Python is a volunteer effort and if Windows-savvy developers aren’t available, Windows issues will remain unfixed and untested and better support for Windows-specific issues will not be forthcoming.&lt;/p&gt;
&lt;p&gt;There are practicalities involved: Subversion or Mercurial, Visual Studio, being able to build Python from scratch and so on, but let’s start from the other end: you’re well-intentioned and motivated, but what should you do? I’m focusing on Windows-specific issues, but some of what I say here applies to anyone who’s interested in helping Python’s core development.&lt;/p&gt;
&lt;h2&gt;How should I start?&lt;/h2&gt;
&lt;p&gt;You don’t have to be an über-hacker or even a developer at all to contribute to Python. (Although you can do more if you are). You can start by submitting bug reports or requests for improvements to the issue tracker:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Good&lt;/strong&gt;: Submit a bug report: send an email to bugs@python.org detailing what version of Python you’re using and on which version of Windows, what you did and what went wrong. Or what you think should happen. If you&amp;#8217;re able to re-test with a newer version of Python that will help, in case the bug&amp;#8217;s already been identified and fixed. If it’s a documentation issue you’re describing, be clear what alternative or additional text you’re proposing.
&lt;li&gt;&lt;strong&gt;Better&lt;/strong&gt;: Submit a bug report or feature request and a failing test case: send an email as above, but attach the simplest possible self-contained script which will cause the failure you’re describing or which will illustrate what should happen.
&lt;li&gt;&lt;strong&gt;Best&lt;/strong&gt;: Submit a bug report with a failing test and add a patch which you believe will solve the issue plus a patch to the relevant Python test module plus a doc patch if applicable. If this is a documentation issue, the ideal is a patch against the reStructuredText docs; at the least, a clear plain text version of what you’re proposing.
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Things to bear in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don’t be disappointed if no-one takes any action. Ideally – and often – someone quickly notices the new issue, does a little categorisation on it and assigns it to a developer who’s known to be the owner of the area where the problem occurred. At the least, one or more developers may be added to the nosy list, and one of them may take ownership. Even if that doesn’t happen, you’ve definitely done the right thing by reporting the issue and offering a patch. If it’s Windows-related, feel free to add me to the nosy list. But even if a developer is assigned, developers are volunteers with their own availability, pressures and interests.
&lt;li&gt;Don’t be surprised if the issue isn’t quite as straightforward as it appears at first blush, particularly if backwards compatibility is at stake. There may be some history of which you’re unaware, or some ramifications in other areas of the codebase which aren&amp;#8217;t obvious.
&lt;li&gt;Don’t give up in despair if the issue is rejected. This isn’t a hard-hearted manoeuvre by the core developers to reject all outside help. It just means that things aren’t always as simple as they might appear and some bigger-picture issue might have put the kibosh on your bright idea. If you feel that a valid point has genuinely been misunderstood you’re free to ask that the issue be reopened; but please don’t do this frivolously.
&lt;li&gt;Not all versions of Python are under active development. At the time of writing, the 2.x series is at the end of its life with 2.7 the final release. Clear bugs may be fixed in that branch, but little else. It’s unlikely that anything categorised as a new feature will make it in there. The same goes for 3.1. The latest development branch is version 3.2 where new features will be targetted. Any earlier releases will either see no changes whatsoever or only critical security fixes.
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;I’m a Windows developer, but where are the problems?&lt;/h2&gt;
&lt;p&gt;Being a core Python developer on Windows can mean several things: doing any kind of Python core development when Windows is your primary platform; working on Windows-specific modules, such as msvcrt or winreg, or the Windows-specific aspects of other modules, such as os and subprocess; or assessing and maintaining platform-specific subtleties such as compiler-sensitive datatype sizes or line-ending issues.&lt;/p&gt;
&lt;p&gt;A lot depends on your own inclinations, motivations and areas of expertise. If you’re an experienced Visual Studio user you might focus more on some of the compiler-specific issues or build file configurations. If you have experience of sysadmin-type work you might want to look at the os module which wraps some of the Win32 API in posix-like calls or the winreg module which exposes the registry functions. If you’re a general purpose C coder who just uses Windows as a platform then you could look at the core Python code or the parts of the stdlib written in C. If you&amp;#8217;re an MSI guru, look at some of the outstanding issues in Python&amp;#8217;s own MSI and the bdist_msi distutils subsystem.&lt;/p&gt;
&lt;p&gt;Ultimately involvement probably comes from one of three things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scratching your own itch&lt;/strong&gt;: is there something in the docs which you’ve never really understood because it relies on knowledge of Unix-specifics? Or just because it’s confusing? Have you been tripped up by a stdlib function which assumes that Windows paths always act like Unix paths? Have you tried to use os.access only to discover that it’s essentially useless on Windows? Do you think you could reimplement the signal module using the Win32 API? Or sponsor the merge of a 3rd-party Windows port of the curses module?
&lt;li&gt;&lt;strong&gt;Scratching someone else’s itch&lt;/strong&gt;: have a look at &lt;a href=&quot;http://bugs.python.org&quot;&gt;bugs.python.org&lt;/a&gt; and choose an issue which is unresolved. The issue tracker has recently had new quick-searches added to it down the left and you can easily build your own searches. &lt;a href=&quot;http://bugs.python.org/issue?@columns=title,id,activity,status&amp;#038;@sort=activity&amp;#038;@group=priority&amp;#038;@filter=components,status&amp;#038;@pagesize=50&amp;#038;@startwith=0&amp;#038;status=1&amp;#038;components=15&amp;#038;@dispname=Windows&quot;&gt;This search&lt;/a&gt;, for example, looks for unclosed issues which include Windows in the component list. It can be a useful exercise if you simply confirm that an unclear issue still obtains on current versions of Python and, possibly, on recent versions of Windows. Or if you produce a failing test case for a merely textual or vague report. (Something which can take quite some time). But be wary of producing “me-too” noise as people following that particular issue will receive notification emails which don’t add usefully to the known state of affairs.
&lt;li&gt;&lt;strong&gt;Finding an itch to scratch&lt;/strong&gt;: if you’re keen to contribute but haven’t experienced any problems which need fixing, and haven’t found any existing bugs which take your fancy, then why not just browse &lt;a href=&quot;http://svn.python.org/&quot;&gt;the source code&lt;/a&gt; seeing how things are done and looking for ways to improve. Be careful here since cosmetic, trivial or frivolous changes are generally frowned upon. But, for example, the subprocess and multiprocessing modules both involve some reasonably serious Windows-specific plumbing. The &lt;a href=&quot;http://svn.python.org/view/python/branches/py3k/Misc/maintainers.rst?view=markup&quot;&gt;module maintainers&lt;/a&gt; aren’t necessarily Windows experts and even if they are, the more eyes the better. There are other modules which have Windows-specific elements if only in small ways.
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;Where should I be helping?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The issue tracker&lt;/strong&gt;: &lt;a href=&quot;http://bugs.python.org&quot;&gt;bugs.python.org&lt;/a&gt; hosts the Python issue tracker, an instance of &lt;a href=&quot;http://pypi.python.org/pypi/roundup&quot;&gt;roundup&lt;/a&gt; which keeps track of all bug reports and feature requests. It’s broadly followed by core developers, but a small team keeps track of incoming bugs and tries to categorise them appropriately and to assign them to a known developer if possible, or to add to the issue’s nosy list developers known to be interested in that area of the system. By helping out in this way, you get a fairly good idea of the issues being reported and the work being done on them. And on which core developers have expertise in which areas of the system. It’s also relatively easy to get higher privileges on the tracker than he default logged-in user has so that you can help classify and manage open issues.
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: The documentation is maintained as &lt;a href=&quot;http://docutils.sourceforge.net/rst.html&quot;&gt;reStructuredText&lt;/a&gt; files &lt;a href=&quot;http://svn.python.org/view/python/branches/py3k/Doc/&quot;&gt;within Python’s version control repository&lt;/a&gt; and is published using &lt;a href=&quot;http://docutils.sourceforge.net/rst.html&quot;&gt;Sphinx&lt;/a&gt;. It’s very easy to change and patch and there’s a &lt;a href=&quot;http://svn.python.org/view/python/branches/py3k/Doc/make.bat?view=log&quot;&gt;batch&lt;/a&gt; file to rebuild it on Windows although you may need to tweak it a little. Doc patches are welcome, whether for small fry such as typos or slight clarifications, or for weightier rewrite.
&lt;li&gt;&lt;strong&gt;stdlib Python&lt;/strong&gt;: The Python-only parts of the standard library. A lot of the stdlib is written in Python itself; that’s what makes the whole package so portable. Even if you’re not a C developer, you can still debug and test issues in the stdlib itself. It’s especially possible to do this without a C compiler or even a Subversion checkout: you only need to put an altered version of the module in a test directory from which you run the Python interpreter and the interpreter will see the local version first.
&lt;li&gt;&lt;strong&gt;stdlib Python &amp;amp; C&lt;/strong&gt;: Some of the standard library relies partly or wholly on extension modules, written in C against Python’s C-API. The C is reasonably readable and is often concerned only with moving Python objects to and from some system library, which makes it a fairly restricted subset of C. To do anything useful with this, you will need a C compiler and, ideally, a version-controlled checkout.
&lt;li&gt;&lt;strong&gt;Core Python&lt;/strong&gt;: The core of CPython is written in C: the objects, the interpreter, the underlying data structures, key built-in modules. You’ll need to be a fairly good C programmer to work here, not least because the impact is high if a mistake is made.
&lt;li&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt;: CPython needs a certain amount of scaffolding to build, especially on Windows where the standard autoconf/make tools don&amp;#8217;t apply. This scaffolding tends to be under-supported, not least because it’s not very public-facing and doesn’t solve most people’s problems. But it still needs to be done. This includes Visual Studio solution and proj files, msi build mechanisms, buildbot scripts and documentation make files.
&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;This is Part I; Part II should include information about checkout out the source, building it, creating &amp;amp; applying patches and working within the development community.&lt;/p&gt;</content>
		<author>
			<name>Tim Golden</name>
			<uri>http://ramblings.timgolden.me.uk</uri>
		</author>
		<source>
			<title type="html">Moderate Realism » Tech</title>
			<subtitle type="html">The ramblings of Tim Golden</subtitle>
			<link rel="self" href="http://ramblings.timgolden.me.uk/category/tech/feed"/>
			<id>http://ramblings.timgolden.me.uk/category/tech/feed</id>
			<updated>2010-08-16T17:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-15</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/dzaPnn9jNAw/"/>
		<id>http://www.magpiebrain.com/2010/08/15/links-for-2010-08-15/</id>
		<updated>2010-08-15T21:00:57+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://asymmetrical-view.com/2009/06/22/executable-clojure-jars.html&quot;&gt;Creating Executable Jars For Your Clojure Application&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/clojure&quot;&gt;clojure&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/jar&quot;&gt;jar&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/executable&quot;&gt;executable&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=dzaPnn9jNAw:8CoPY_qVQFE:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=dzaPnn9jNAw:8CoPY_qVQFE:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=dzaPnn9jNAw:8CoPY_qVQFE:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=dzaPnn9jNAw:8CoPY_qVQFE:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=dzaPnn9jNAw:8CoPY_qVQFE:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Graphing Hits Per Minute Using Clojure &amp;amp; Incanter</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/b0ig6EZf9AM/"/>
		<id>http://www.magpiebrain.com/?p=913</id>
		<updated>2010-08-15T18:10:59+00:00</updated>
		<content type="html">&lt;p&gt;Continuing in a re-occurring series of posts showing &lt;a href=&quot;http://www.magpiebrain.com/2010/08/10/creating-sparse-tabular-data-with-clojure/&quot;&gt;my limited understanding of Clojure&lt;/a&gt;, today we&amp;#8217;re using Clojure for log processing. This example is culled from some work I&amp;#8217;m doing right now in the day job &amp;#8211; we needed to extract usage information to better understand how the system is performing.&lt;/p&gt;
&lt;h3&gt;The Problem&lt;/h3&gt;
&lt;p&gt;We have an Apache-style access log showing hits our site. We want to process this information to extract information like peak hits per minute, and perhaps eventually more detailed information like the nature of the request, response time etc. &lt;/p&gt;
&lt;p&gt;The log looks like this:&lt;/p&gt;
&lt;pre&gt;
43.124.137.100 - username 05/Aug/2010:17:27:24 +0100 &quot;GET /some/url HTTP/1.1&quot; 200 24 &quot;http://some.refering.domain/&quot; &quot;Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.9) Gecko/2009040821 Firefox/3.0.9 (.NET CLR 3.5.30729)&quot;&lt;/pre&gt;
&lt;h3&gt;Extracting The Information&lt;/h3&gt;
&lt;p&gt;We want to use &lt;a href=&quot;http://incanter.org/&quot;&gt;Incanter&lt;/a&gt; to help us process the data &amp;#038; graph it. Incanter likes its data as a sequence of sequences &amp;#8211; so that&amp;#8217;s what we&amp;#8217;ll create.&lt;/p&gt;
&lt;p&gt;First up &amp;#8211; processing a single line. I TDD&amp;#8217;d this solution, but have excluded the tests from the source listing for brevity.&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
user=&gt; (use 'clojure.contrib.str-utils)
nil
user=&gt; (use '[clojure.contrib.duck-streams :only (read-lines)])
nil

user=&gt; (defn extract-records-from-line
  [line-from-access-log]
  (let [[_ ip username date] (re-find #&quot;^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) - (\w+) (.+? .+?) &quot; line-from-access-log)]
    [date username]))
#'user/extract-records-from-line

user=&gt; (defn as-dataseries
  [access-log-lines]
  (map extract-records-from-line access-log-lines))
#'user/as-dataseries

user=&gt; (defn records-from-access-log
  [filename]
  (as-dataseries (read-lines filename)))
#'user/records-from-access-log
&lt;/pre&gt;
&lt;p&gt;A few things to note. &lt;code&gt;extract-records-from-line&lt;/code&gt; is matching more than strictly needed &amp;#8211; I just wanted to indicate the use of destructing for matching parts of the log line. I&amp;#8217;m pulling in the username &amp;#038; date &amp;#8211; the username is not strictly needed for what follows. Secondly, note the use of &lt;code&gt;read-lines&lt;/code&gt; from &lt;code&gt;clojure.contrib.duck-streams&lt;/code&gt; &amp;#8211; rather than &lt;code&gt;slurp&lt;/code&gt;, &lt;code&gt;read-lines&lt;/code&gt; is lazy. We&amp;#8217;ll have to process the whole file at some point, but it&amp;#8217;s a good idea to look to use lazy functions where possible.&lt;/p&gt;
&lt;p&gt;At this point, running &lt;code&gt;records-from-access-log&lt;/code&gt; gives us our sequence of sequences &amp;#8211; next up, pulling it into Incanter.&lt;/p&gt;
&lt;h3&gt;Getting The Data Into Incanter&lt;/h3&gt;
&lt;p&gt;We can check that our code is working properly by firing up Incanter. Given a sample log:&lt;/p&gt;
&lt;pre&gt;
56.24.137.230 - fred 05/Aug/2010:17:27:24 +0100 &quot;GET /some/url HTTP/1.1&quot; 200 24 &quot;http://some.refering.domain/&quot; &quot;SomeUserAgent&quot;
12.14.137.140 - norman 05/Aug/2010:17:27:24 +0100 &quot;GET /some/url HTTP/1.1&quot; 200 24 &quot;http://some.refering.domain/&quot; &quot;SomeUserAgent&quot;
42.1.137.110 - bob 05/Aug/2010:17:28:24 +0100 &quot;GET /some/url HTTP/1.1&quot; 200 24 &quot;http://some.refering.domain/&quot; &quot;SomeUserAgent&quot;
143.124.1.50 - clare 05/Aug/2010:17:29:24 +0100 &quot;GET /some/url HTTP/1.1&quot; 200 24 &quot;http://some.refering.domain/&quot; &quot;SomeUserAgent&quot;
&lt;/pre&gt;
&lt;p&gt;Let&amp;#8217;s create a dataset from it, and view the resulting records:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
user=&gt; (use 'incanter.core)
nil
user=&gt; (def access-log-to-dataset
(to-dataset (records-from-access-log &quot;/path/to/example-access.log&quot;)))
#'user/access-log-dataset
user=&gt; (view access-log-dataset)
&lt;/pre&gt;
&lt;p&gt;The result of the &lt;code&gt;view&lt;/code&gt; command:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.magpiebrain.com/wp-content/uploads/2010/08/incanter-dataset-nocols.png&quot;&gt;&lt;img src=&quot;http://www.magpiebrain.com/wp-content/uploads/2010/08/incanter-dataset-nocols-300x163.png&quot; alt=&quot;&quot; title=&quot;incanter-dataset-nocols&quot; width=&quot;300&quot; height=&quot;163&quot; class=&quot;aligncenter size-medium wp-image-927&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately, no column names &amp;#8211; but that is easy to fix using &lt;code&gt;col-names&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
user=&gt; (def access-log-dataset
(col-names (to-dataset (records-from-access-log &quot;/path/to/example-access.log&quot;)) [&quot;Date&quot; &quot;User&quot;]))
#'user/access-log-dataset
user=&gt; (view access-log-dataset)
&lt;/pre&gt;
&lt;p&gt;At this point you can see that it would be easy for us to pull in the URL, response code or other data rather than the username from the log &amp;#8211; all we&amp;#8217;d need to do is change &lt;code&gt;extract-records-from-line&lt;/code&gt; and update the column names.&lt;/p&gt;
&lt;h3&gt;Graphing The Data&lt;/h3&gt;
&lt;p&gt;To graph the data, we need to get Incanter to register the date column as what it is &amp;#8211; time. Currently it is in string format, so we need to fix that. Culling the basics from &lt;a href=&quot;http://jakemccrary.com/blog/2010/02/21/plotting-time-series-data-with-incanter/&quot; title=&quot;Plotting time series data with Incanter&quot;&gt;Jake McCray&amp;#8217;s post&lt;/a&gt;, here is what I ended up with (note use of Joda-Time for date handling &amp;#8211; you could use the standard SimpleDateFormat if you preferred):&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
user=&gt; (import 'org.joda.time.format.DateTimeFormat)
nil

user=&gt; (defn as-millis
  [date-as-str]
  (.getMillis (.parseDateTime (DateTimeFormat/forPattern &quot;dd/MMM/yyyy:HH:mm:ss Z&quot;) date-as-str)))
#'user/as-millis

user=&gt; (defn access-log-to-dataset
  [filename]
  (let [unmod-data (col-names (to-dataset (records-from-access-log filename)) [&quot;Date&quot; &quot;User&quot;])]
    (col-names (conj-cols ($map as-millis &quot;Date&quot; unmod-dataset) ($ &quot;User&quot; unmod-dataset)) [&quot;Date Time In Ms&quot; &quot;User&quot;])))
#'user/access-log-to-dataset
&lt;/pre&gt;
&lt;p&gt;While the date parsing should be pretty straightforward to understand, there are a few interesting things going on with the Incanter code that we should dwell on briefly.&lt;/p&gt;
&lt;p&gt; The &lt;code&gt;$&lt;/code&gt; function extracts a named column, whereas the &lt;code&gt;$map&lt;/code&gt; function runs another function over the named column from the dataset, returning the modified column (pretty familiar if you&amp;#8217;ve used &lt;code&gt;map&lt;/code&gt;).  &lt;code&gt;conj-cols&lt;/code&gt; then takes these resulting sequences to create our final dataset. &lt;/p&gt;
&lt;p&gt;We&amp;#8217;re not quite done yet though. We have our time-series records &amp;#8211; representing one hit on our webserver &amp;#8211; but don&amp;#8217;t actually have values to graph. We also need to work out how we group hits to the nearest minute. What we&amp;#8217;re going to do is replace our &lt;code&gt;as-millis&lt;/code&gt; function to one that rounds to the nearest minute. Then, we&amp;#8217;re going to use Incater to group those rows together &amp;#8211; summing the hits it finds per minute. But before that, we need to tell Incanter that each row represents a hit, by adding a &amp;#8216;Hits&amp;#8217; column. We&amp;#8217;re also going to ditch the user column, as it isn&amp;#8217;t going to help us here:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
user=&gt; (defn access-log-to-dataset
  [filename]
  (let [unmod-dataset (col-names (to-dataset (records-from-access-log filename)) [&quot;Date&quot; &quot;User&quot;])]
    (col-names (conj-cols ($map as-millis &quot;Date&quot; unmod-dataset) (repeat 1)) [&quot;Date&quot; &quot;Hits&quot;])))
#'user/access-log-to-dataset
&lt;/pre&gt;
&lt;p&gt;Next, we need to create a new function to round our date &amp;#038; time to the nearest minute.&lt;/p&gt;
&lt;p class=&quot;update&quot;&gt;Update: The earlier version of this post screwed up, and the presented &lt;code&gt;round-ms-down-to-nearest-min&lt;/code&gt; actually rounded to the nearest second. This is a corrected version:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
(defn round-ms-down-to-nearest-min
  [millis]
  (* 60000 (quot millis 60000)))
&lt;/pre&gt;
&lt;p&gt;If you wanted hits per second, here is the function:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
(defn round-ms-down-to-nearest-sec
  [millis]
  (* 1000 (quot millis 1000)))
&lt;/pre&gt;
&lt;p&gt;And one more tweak to &lt;code&gt;access-log-to-dataset&lt;/code&gt; to use the new function:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
(defn access-log-to-dataset
  [filename]
  (let [unmod-dataset (col-names (to-dataset (records-from-access-log filename)) [&quot;Date&quot; &quot;User&quot;])]
    (col-names (conj-cols ($map #(round-ms-down-to-nearest-min (as-millis %)) &quot;Date&quot; unmod-dataset) (repeat 1)) [&quot;Date&quot; &quot;Hits&quot;])))
&lt;/pre&gt;
&lt;p&gt;Finally, we need to roll our data up, summing the hits per minute &amp;#8211; all this done using &lt;code&gt;$rollup&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
(defn access-log-to-dataset
  [filename]
  (let [unmod-dataset (col-names (to-dataset (records-from-access-log filename)) [&quot;Date&quot; &quot;User&quot;])]
    ($rollup :sum &quot;Hits&quot; &quot;Date&quot;
      (col-names (conj-cols ($map #(round-ms-down-to-nearest-min (as-millis %)) &quot;Date&quot; unmod-dataset) (repeat 1)) [&quot;Date&quot; &quot;Hits&quot;]))))
&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;$rollup&lt;/code&gt; applies a summary function to a given column (in our case &amp;#8220;Hits&amp;#8221;), using another function to determine the parameters for that function (&amp;#8220;Date&amp;#8221; in our case). &lt;code&gt;:sum&lt;/code&gt; here is a built-in Incanter function, but we could provide our own.&lt;/p&gt;
&lt;p&gt;And the resulting dataset:&lt;br /&gt;
&lt;a href=&quot;http://www.magpiebrain.com/wp-content/uploads/2010/08/rollup-dataset.png&quot;&gt;&lt;img src=&quot;http://www.magpiebrain.com/wp-content/uploads/2010/08/rollup-dataset-300x112.png&quot; alt=&quot;&quot; title=&quot;rollup-dataset&quot; width=&quot;300&quot; height=&quot;112&quot; class=&quot;aligncenter size-medium wp-image-919&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now we have our dataset, let&amp;#8217;s graph it:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
user=&gt; (defn hit-graph
  [dataset]
  (time-series-plot :Date :Hits
                             :x-label &quot;Date&quot;
                             :y-label &quot;Hits&quot;
                             :title &quot;Hits&quot;
                             :data dataset))

user=&gt; (view (hit-graph (access-log-to-dataset &quot;/path/to/example-access.log&quot;)))
&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://www.magpiebrain.com/wp-content/uploads/2010/08/example-graph.png&quot;&gt;&lt;img src=&quot;http://www.magpiebrain.com/wp-content/uploads/2010/08/example-graph-300x240.png&quot; alt=&quot;&quot; title=&quot;example-graph&quot; width=&quot;300&quot; height=&quot;240&quot; class=&quot;aligncenter size-medium wp-image-924&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is deeply unexciting &amp;#8211; what about if we try a bigger dataset? Then we get things like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.magpiebrain.com/wp-content/uploads/2010/08/graph.png&quot;&gt;&lt;img src=&quot;http://www.magpiebrain.com/wp-content/uploads/2010/08/graph-300x240.png&quot; alt=&quot;&quot; title=&quot;graph&quot; width=&quot;300&quot; height=&quot;240&quot; class=&quot;aligncenter size-medium wp-image-926&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;You can grab the final code &lt;a href=&quot;http://gist.github.com/525777&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Incanter is much more than simply a way of graphing data. This (somewhat) brief example shows you how to get log data into an Incanter-frendly format &amp;#8211; what you want to do with it then is up to you. I may well explore other aspects of Incanter in further posts.&lt;/p&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=b0ig6EZf9AM:W6z5fAIdcB4:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=b0ig6EZf9AM:W6z5fAIdcB4:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=b0ig6EZf9AM:W6z5fAIdcB4:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=b0ig6EZf9AM:W6z5fAIdcB4:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=b0ig6EZf9AM:W6z5fAIdcB4:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-13</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/3TQKqRo5M8k/"/>
		<id>http://www.magpiebrain.com/2010/08/13/links-for-2010-08-13/</id>
		<updated>2010-08-13T21:01:23+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://lethain.com/entry/2009/nov/15/reading-file-in-clojure/&quot;&gt;Reading Files in Clojure @ Irrational Exuberance&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;How to read a file without blowing your stack&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/file&quot;&gt;file&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/io&quot;&gt;io&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/clojure&quot;&gt;clojure&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/tips&quot;&gt;tips&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://html5boilerplate.com/&quot;&gt;HTML5 Boilerplate &amp;#8211; A rock-solid default for HTML5 awesome.&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/css&quot;&gt;css&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/html&quot;&gt;html&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/javascript&quot;&gt;javascript&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=3TQKqRo5M8k:SdRDgY2YuDc:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=3TQKqRo5M8k:SdRDgY2YuDc:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=3TQKqRo5M8k:SdRDgY2YuDc:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=3TQKqRo5M8k:SdRDgY2YuDc:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=3TQKqRo5M8k:SdRDgY2YuDc:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Eric Schmidt Looks Forward to Big Brother</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/o5q0cAn2chQ/eric-schmidt-looks-forward-to-big.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-8141227466725348863</id>
		<updated>2010-08-12T16:33:44+00:00</updated>
		<content type="html">&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://2.bp.blogspot.com/_JT1n2tt-4Wg/TGREl7nsKYI/AAAAAAAAAXA/-UTTpXxYyRE/s1600/EricSchmidt.png&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/_JT1n2tt-4Wg/TGREl7nsKYI/AAAAAAAAAXA/-UTTpXxYyRE/s320/EricSchmidt.png&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot;&gt;&lt;span&gt;&quot;You only need to give up&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;just a little bit of freedom&quot;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Well, Google's senior management are really keeping us guessing this month. I am not really sure any longer whether the company actually has any coherent point of view on individual privacy. Nowadays it seems you can't even expect consistency. In a startling repetition of his prior assertions that not only is Internet anonymity dead but that he wants to dance on its grave. According to a &lt;a href=&quot;http://www.readwriteweb.com/archives/google_ceo_schmidt_people_arent_ready_for_the_tech.php&quot;&gt;Read Write Web report&lt;/a&gt; Eric Schmidt, CEO of Google, included the following comments in his remarks to the &lt;a href=&quot;http://techonomy.com/program-outline/&quot;&gt;Techonomy&lt;/a&gt; conference:&lt;br /&gt;
&lt;blockquote&gt;&quot;The only way to manage this is true transparency and no anonymity. In a  world of asynchronous threats, it is too dangerous for there not to be  some way to identify you.  We need a [verified] name service for people.   Governments will demand it.&quot;&lt;/blockquote&gt;&lt;br /&gt;
Any government that requires individuals to give up their rights to anonymity is a government past its sell-by date. To my mind this reveals further insight into Schmidt's &quot;what's good for business is good for the people&quot;&amp;nbsp; view exemplified by the much-discussed recent &lt;a href=&quot;http://www.google.com/hostednews/afp/article/ALeqM5iZnzyMYE_gCzJ3ZD6NwYovL2ZZoQ&quot;&gt;joint statement with Verizon on network neutrality&lt;/a&gt;. It's fairly obvious that Schmidt sees government's role as paving the way for corporations to increase their profits, not preserving the freedoms of the citizenry who elected it. This is so far from &quot;government of the people, for the people and by the people&quot; that it's apparently time &quot;do no evil&quot; was replaced by &quot;make more money&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://3.bp.blogspot.com/_JT1n2tt-4Wg/TGRGxP8EvNI/AAAAAAAAAXI/HbK10ljS1-A/s1600/EricSchmidt2.png&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;http://3.bp.blogspot.com/_JT1n2tt-4Wg/TGRGxP8EvNI/AAAAAAAAAXI/HbK10ljS1-A/s200/EricSchmidt2.png&quot; width=&quot;180&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot;&gt;&lt;span&gt;&quot;But that would hurt Google's&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;stock price!&quot;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;Yet it was only in May (yes, three months ago) that Schmidt was publicly suggesting that as far as Google was concerned &quot;&lt;a href=&quot;http://www.guardian.co.uk/technology/2010/may/19/eric-schmidt-google-privacy&quot;&gt;privacy is paramount&lt;/a&gt;&quot;. Does he really know what the priorities are any longer? It seems like we can dismiss any further utterances as the self-serving flip-floppery of the 129th richest man in the world. What does he really think? Apparently it depends on which way the financial wind is blowing. The really depressing thing is it's transparently obvious that here we have a man who will do well in politics. &quot;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0452285674/steveholden-20&quot;&gt;The Best Democracy Money Can Buy&lt;/a&gt;&quot; indeed.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/496482-8141227466725348863?l=holdenweb.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=o5q0cAn2chQ:EcL0G11VEWg:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=o5q0cAn2chQ:EcL0G11VEWg:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=o5q0cAn2chQ:EcL0G11VEWg:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/o5q0cAn2chQ&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-11</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/7noH-oFOa18/"/>
		<id>http://www.magpiebrain.com/2010/08/11/links-for-2010-08-11/</id>
		<updated>2010-08-11T21:02:31+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.linux.com/archive/feature/56443&quot;&gt;Linux.com :: Using screen for remote interaction&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/screen&quot;&gt;screen&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/unix&quot;&gt;unix&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/productivity&quot;&gt;productivity&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/pairing&quot;&gt;pairing&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/pairprograming&quot;&gt;pairprograming&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/linux&quot;&gt;linux&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://progit.org/2010/03/04/smart-http.html&quot;&gt;Smart HTTP Transport&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;An efficient read/write HTTP transfer protocol for Git&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/git&quot;&gt;git&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/http&quot;&gt;http&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/transport&quot;&gt;transport&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/sysadmin&quot;&gt;sysadmin&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/devops&quot;&gt;devops&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=7noH-oFOa18:WYc2R6mAlSc:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=7noH-oFOa18:WYc2R6mAlSc:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=7noH-oFOa18:WYc2R6mAlSc:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=7noH-oFOa18:WYc2R6mAlSc:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=7noH-oFOa18:WYc2R6mAlSc:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Creating Sparse Tabular Data With Clojure</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/Bl0pCpwcxT4/"/>
		<id>http://www.magpiebrain.com/?p=888</id>
		<updated>2010-08-10T21:11:49+00:00</updated>
		<content type="html">&lt;p&gt;In the spirit of making my mistakes in public &amp;#8211; something which I have a long history of on this blog &amp;#8211; I thought I&amp;#8217;d post up a solution I came up with for a relatively simple problem. I&amp;#8217;m not unhappy with the solution &amp;#8211; it works &amp;#8211; but I can&amp;#8217;t help thinking I&amp;#8217;m missing something and there is a more elegant solution out there.&lt;/p&gt;
&lt;h3&gt;The Problem&lt;/h3&gt;
&lt;p&gt;For our input we have a set of time series records. Each record contains a list of name value pairs. For each record, the keys are not fixed &amp;#8211; they may vary. Let&amp;#8217;s imagine that we&amp;#8217;re recording viewing figures for the major UK soap operas &amp;#8211; some soaps are on every day, some are only on a few days a week.&lt;/p&gt;
&lt;p&gt;In Clojure, we&amp;#8217;re got our data in the following form:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
((&quot;Monday&quot; {:eastenders 6.5, :thearchers 2.3, :corrinationstreet 5.6})
 (&quot;Tuesday&quot; {:eastenders 6.8, :thearchers 1.4})
 ...)
&lt;/pre&gt;
&lt;p&gt;We want to convert this into a single table of data, with the keys from the source data representing the columns, with each row representing a different timestamp, so that we can visualise the data with something like &lt;code&gt;gnuplot&lt;/code&gt;, &lt;code&gt;Incanter&lt;/code&gt; or just plain old excel. So we want to get to something like this (yes, I know The Archers is on at the weekend too, but this is just an example):&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Day&lt;/th&gt;
&lt;th&gt;Eastenders&lt;/th&gt;
&lt;th&gt;The Archers&lt;/th&gt;
&lt;th&gt; Coronation Street&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Monday&lt;/th&gt;
&lt;td&gt;6.5&lt;/td&gt;
&lt;td&gt;2.3&lt;/td&gt;
&lt;td&gt;5.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Tuesday&lt;/th&gt;
&lt;td&gt;6.8&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Wednesday&lt;/th&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;2.3&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Thursday&lt;/th&gt;
&lt;td&gt;6.7&lt;/td&gt;
&lt;td&gt;2.8&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Friday&lt;/th&gt;
&lt;td&gt;9.8&lt;/td&gt;
&lt;td&gt;2.1&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The challenge here (such as it is) is that we want a sparse table, and that our code cannot know beforehand the total universe of soap names (what if a new soap launched?).&lt;/p&gt;
&lt;h3&gt;The Header Row&lt;/h3&gt;
&lt;p&gt;The first part of this problem as I saw it was to determine which soaps our records represented to create a header row. The solution I came up with was to stick the keys for all records into a set:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
user=&gt; (def soaps
'((&quot;Monday&quot; {&quot;eastenders&quot; 6.5, &quot;thearchers&quot; 2.3, &quot;corrinationstreet&quot; 5.6})
(&quot;Tuesday&quot; {&quot;eastenders&quot; 6.8, &quot;thearchers&quot; 1.4})))

#'user/records
user=&gt; (defn as-columns [records]
(apply (partial conj #{}) (mapcat keys (map second records)))))
#'user/columns

user=&gt; (as-columns soaps)
#{&quot;corrinationstreet&quot; &quot;eastenders&quot; &quot;thearchers&quot;}
&lt;/pre&gt;
&lt;p&gt;Assuming we want a CSV file to store our content, a function to create the header row becomes:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
user=&gt; (str &quot;Date,&quot; (apply str (interpose &quot;,&quot; (as-columns soaps))))
&quot;Date,corrinationstreet,eastenders,thearchers&quot;
&lt;/pre&gt;
&lt;h3&gt;The Data&lt;/h3&gt;
&lt;p&gt;Now we have a list of all possible keys (in this example, the names of the soaps), we can use this to extract data from the records for each row. Getting data from a map is straightforward &amp;#8211; even handling the not-there case is simple enough:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
user=&gt; (def some-map
{&quot;eastenders&quot; 6.5, &quot;thearchers&quot; 2.3, &quot;corrinationstreet&quot; 5.6})
#'user/some-map

user=&gt; (get some-map &quot;eastenders&quot; &quot;-&quot;)
6.5

user=&gt; (get some-map &quot;hollyoaks&quot; &quot;-&quot;)
-
&lt;/pre&gt;
&lt;p&gt;Given a list of known columns, we can use a list comprehension to extract the data in a consistent order:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
user=&gt; (for [col #{&quot;eastenders&quot; &quot;thearchers&quot; &quot;corrinationstreet&quot;}]
(get {&quot;eastenders&quot; 6.8, &quot;thearchers&quot; 1.4} col &quot;-&quot;))
([&quot;-&quot;] [6.8] [1.4])
&lt;/pre&gt;
&lt;h3&gt;Pulling It All Together&lt;/h3&gt;
&lt;p&gt;Taking those various strands, we end up with the following solution:&lt;/p&gt;
&lt;pre class=&quot;brush: clojure;&quot;&gt;
(defn as-columns
  [records]
  (apply (partial conj #{}) (mapcat keys (map second records))))

(defn header-row
  [records]
  (str &quot;Date,&quot; (apply str (interpose &quot;,&quot; (as-columns records)))))

(defn values-for-record
  [columns values]
  (for [col columns] (get values col &quot;-&quot;)))

(defn as-row
  [record columns]
  (let [day (first record)
        values (second record)]
   (str day &quot;,&quot;
    (apply str (interpose &quot;,&quot; (values-for-record columns values))))))

(defn as-data
  [records]
  (apply str
    (interpose &quot;\n&quot;
      (for [record records]
          (as-row record (as-columns records))))))

(defn as-table
  [records]
    (apply str (header-row records) &quot;\n&quot; (as-data records)))
&lt;/pre&gt;
&lt;p&gt;Things I like with the solution: it works.&lt;/p&gt;
&lt;p&gt;Things I don&amp;#8217;t like with the solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Duplicated call to &lt;code&gt;as-columns&lt;/code&gt;, in both &lt;code&gt;as-data&lt;/code&gt; and &lt;code&gt;header-row&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Still don&amp;#8217;t think I&amp;#8217;ve got the indentation right&lt;/li&gt;
&lt;li&gt;Still worried I&amp;#8217;m creating functions which are too large, or that are not readable&lt;/li&gt;
&lt;li&gt;This solution was arrived at by hacking on the code in a REPL &amp;#8211; not TDD. My Clojure skills are still lacking, so I have to embark on the occasional hack-a-thon to learn some things &amp;#8211; this being one such exercise. I plan to re-implement this using TDD with what I&amp;#8217;ve learnt to see what I end up with. It will be interesting to see if TDDing this allays my fears about function size.&lt;/li&gt;
&lt;li&gt;Lots of (apply str (interpose&amp;#8230; duplication going around &amp;#8211; I should factor that out&lt;/li&gt;
&lt;li&gt;Not sure if the list comprehension here is needed &amp;#8211; have I missed something obvious?&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=Bl0pCpwcxT4:BXYSS_T8KWU:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=Bl0pCpwcxT4:BXYSS_T8KWU:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=Bl0pCpwcxT4:BXYSS_T8KWU:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=Bl0pCpwcxT4:BXYSS_T8KWU:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=Bl0pCpwcxT4:BXYSS_T8KWU:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-10</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/ZyG7x1PY20o/"/>
		<id>http://www.magpiebrain.com/2010/08/10/links-for-2010-08-10/</id>
		<updated>2010-08-10T21:02:43+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://blog.sharpie.com/2010/08/introducing-the-new-sharpie-liquid-pencil/&quot;&gt;Introducing The NEW Sharpie LIQUID PENCIL&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;Very cool &amp;#8211; writes like a pencil, erasable, but becomes permanent after three days. It&amp;#039;s like we&amp;#039;re living in the future!&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/pen&quot;&gt;pen&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/pencil&quot;&gt;pencil&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/stationary&quot;&gt;stationary&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/sharpie&quot;&gt;sharpie&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=ZyG7x1PY20o:lG6eix6CxdU:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=ZyG7x1PY20o:lG6eix6CxdU:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=ZyG7x1PY20o:lG6eix6CxdU:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=ZyG7x1PY20o:lG6eix6CxdU:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=ZyG7x1PY20o:lG6eix6CxdU:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Paypal Pending Balances</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/Km9w3v1kkhE/paypal-pending-balances.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-8051409871579758143</id>
		<updated>2010-08-08T23:12:44+00:00</updated>
		<content type="html">According to the PayPal user agreement:&lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt;10.7 Reserves.&lt;/b&gt; If you receive Purchase Payments,  PayPal, in its sole discretion, may place a Reserve on funds held in  your Premier or Business Account when PayPal believes there may be a  high level of risk associated with your Account. If PayPal places a  Reserve on funds in your Account, they will be shown as “pending” in  your PayPal Balance. If your Account is subject to a Reserve, PayPal  will provide you with notice specifying the terms of the Reserve. The  terms may require that a certain percentage of the amounts received into  your Account are held for a certain period of time, or that a certain  amount of money is held in reserve, or anything else that PayPal  determines is necessary to protect against the risk associated with your  Account. PayPal may change the terms of the Reserve at any time by  providing you with notice of the new terms.&amp;nbsp;&lt;/blockquote&gt;&amp;nbsp;What this doesn't say is that PayPal will also deny you the ability to earn interest on those funds while they are held in reserve.&amp;nbsp; Because Holden Web is organizing DjangoCon we currently have a substantial balance (which will soon disappear once the outgoing starts). So PayPal have decided that they can place $20,000 on reserve, thereby refusing me the right to earn interest on that money.&lt;br /&gt;
&lt;br /&gt;
Naturally the &quot;notice&quot; I received just said that the funds were being held on reserve until further notice, and when I inquired about this the &quot;explanation&quot; I received didn't explain anything at all: it simply pointed me to the user agreement and suggested that I could find out what information they had used in the decision-making process by taking out a subpoena. Definitely not cool. In terms of customer service PayPal are scoring about 1 out of 10 here.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/496482-8051409871579758143?l=holdenweb.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=Km9w3v1kkhE:rQ27CmBjC1U:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=Km9w3v1kkhE:rQ27CmBjC1U:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=Km9w3v1kkhE:rQ27CmBjC1U:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/Km9w3v1kkhE&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-06</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/XPYIPa9B5Cs/"/>
		<id>http://www.magpiebrain.com/2010/08/06/links-for-2010-08-06/</id>
		<updated>2010-08-06T21:02:21+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.ioncannon.net/programming/475/iphone-windowed-http-live-streaming-using-amazon-s3-and-cloudfront-proof-of-concept/&quot;&gt;iPhone Windowed HTTP Live Streaming Using Amazon S3 and Cloudfront Proof of Concept&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/cloudfront&quot;&gt;cloudfront&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/aws&quot;&gt;aws&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/s3&quot;&gt;s3&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/iphone&quot;&gt;iphone&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/ffmpeg&quot;&gt;ffmpeg&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/video&quot;&gt;video&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=XPYIPa9B5Cs:rB1uOVO3FGY:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=XPYIPa9B5Cs:rB1uOVO3FGY:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=XPYIPa9B5Cs:rB1uOVO3FGY:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=XPYIPa9B5Cs:rB1uOVO3FGY:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=XPYIPa9B5Cs:rB1uOVO3FGY:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Tests That Test Your Tests</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/whVu9eKe5Lg/tests-that-test-your-tests.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-8660572596257843069</id>
		<updated>2010-08-06T01:46:37+00:00</updated>
		<content type="html">I just had an interesting experience with Steve Miller, the technical editor of the Python classes I am writing for &lt;a href=&quot;http://www.oreillyschool.com/&quot;&gt;O'Reilly School of Technology&lt;/a&gt;. We are just getting to the end of the second of four courses, and I like to think that we are moving right along: in the final lesson students write a simple GUI-based program that searches for and displays e-mail messages stored in a MySQL database.&lt;br /&gt;
&lt;br /&gt;
I introduced test-driven development in the second course. Not only does this encourage good habits in the students, it also makes it somewhat easier to test some of their exercises (though I still do not have a good approach to testing Tkinter-based GUI applications). In time-honored fashion we start with tests and a program full of stubs, and then expand the stubs to pass the tests. For the email database the initial API is very simple: there is one function to store messages and two others to retrieve them, by primary key and Message-Id.&lt;br /&gt;
&lt;br /&gt;
In the final chapter I start out with a very simple database table that stores the body of the message as a LONGTEXT column. The only other columns in the table (to start with—it gets more complex later) are the automatically-generated primary key and the Message-Id Header. The tests use a &lt;span class=&quot;Apple-style-span&quot;&gt;setUp()&lt;/span&gt; method that completely re-creates the database table and populates it from messages stored in a bunch of files:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt; FILESPEC = &quot;V:/Python2/Lesson12/MailData/*.eml&quot;  
 class testRealEmail_traffic(unittest.TestCase):  
   def setUp(self):  
     &quot;&quot;&quot;  
     Reads an arbitrary number of mail messages and  
     stores them in a brand new messages table.  
     DANGER: Any existing message table WILL be lost.  
     &quot;&quot;&quot;  
     curs.execute(&quot;DROP TABLE IF EXISTS message&quot;)  
     conn.commit()  
     curs.execute(TBLDEF)  
     conn.commit()  
     files = glob(FILESPEC)  
     self.msgids = {} # Keyed by message_id  
     self.message_ids = {} # keyed by id  
     for f in files:  
       ff = open(f)  
       text = ff.read()  
       msg = message_from_string(text)  
       id = self.msgids[msg['message-id']] = maildb.store(msg)  
       self.message_ids[id] = msg['message-id']  
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
There were two relatively simple tests, one to test each of the retrieval functions in a fairly simplistic way by verifying the correspondence between the primary key values and the Message-Id headers using the &lt;span class=&quot;Apple-style-span&quot;&gt;msgids&lt;/span&gt; and &lt;span class=&quot;Apple-style-span&quot;&gt;message_ids&lt;/span&gt; dicts created during the set-up. The initial stub under test only implemented the &lt;span class=&quot;Apple-style-span&quot;&gt;store()&lt;/span&gt; function, so these tests were initially expected to fail:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;   def test_message_ids(self):  
     &quot;&quot;&quot;  
     Verify that items retrieved by id have the correct Message-ID.  
     &quot;&quot;&quot;   
     for message_id in self.msgids.keys():  
       pk, msg = maildb.msg_by_id(self.msgids[message_id])   
       self.assertEqual(msg['message-id'], message_id)  
   def test_ids(self):  
     &quot;&quot;&quot;  
     Verify that items retrieved by message_id have the correct Message-ID.  
     &quot;&quot;&quot;  
     for id in self.message_ids.keys():  
       pk, msg = maildb.msg_by_message_id(self.message_ids[id])  
       self.assertEqual(msg['message-id'], self.message_ids[id])  
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Steve and I had both run this code under much the same conditions as the students would, and verified that the tests did indeed fail due to the AttributeError exceptions raised by the missing &lt;span class=&quot;Apple-style-span&quot;&gt;msg_by_id()&lt;/span&gt; and &lt;span class=&quot;Apple-style-span&quot;&gt;msg_by_message_id()&lt;/span&gt; functions. Later steps have the student implement these functions, which makes the tests pass.&lt;br /&gt;
&lt;br /&gt;
We were somewhat surprised to find when Steve ran his final checks that the tests were now passing, even though he had reverted to the original module with no implementations of the message retrieval functions! It took me the best part of an hour chatting with Steve to eliminate everything I could think of that might be wrong: no .pyc files left lying around, no odd path settings that allowed import from other copies of the code, and so on.&lt;br /&gt;
&lt;br /&gt;
We finally tracked the issue down to something stupidly simple, as is often the case with bugs that have you scratching your head for an extended period: for production purposes the data files had been moved to an area where all students could share them (each student has their own &lt;span class=&quot;Apple-style-span&quot;&gt;V:&lt;/span&gt; directory). This meant that the &lt;span class=&quot;Apple-style-span&quot;&gt;setUp()&lt;/span&gt; method was not inserting any rows into the newly-created message table. The empty table in turn meant that neither &lt;span class=&quot;Apple-style-span&quot;&gt;test_message_ids()&lt;/span&gt; nor &lt;span class=&quot;Apple-style-span&quot;&gt;test_ids()&lt;/span&gt; was running the the body of the &lt;span class=&quot;Apple-style-span&quot;&gt;for&lt;/span&gt; loop, and consequently no AttributeError exceptions were being raised. The tests were passing even though the functions they were supposed to test had not been implemented!&lt;br /&gt;
&lt;br /&gt;
My solution to this was to add a further test to verify that the table was not empty. That way, even if the other tests passed, this one would fail:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;   def test_not_empty(self):  
     &quot;&quot;&quot;  
     Verify that the setUp method actually created some messages.  
     If it finds no files there will be no messages in the table,  
     the loop bodies in the other tests will never run, and potential  
     errors will never be discovered.  
     &quot;&quot;&quot;  
     curs.execute(&quot;SELECT COUNT(*) FROM message&quot;)  
     messagect = curs.fetchone()[0]  
     self.assertGreater(messagect, 0, &quot;Database message table is empty&quot;)  
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
The check could have been added to one of the other tests but it seemed to make more sense to keep it separate, since several tests relied on the table having been populated.&lt;br /&gt;
&lt;br /&gt;
In this case the error condition was that the test were passing!&amp;nbsp;I am happy about this because it clearly demonstrates the value of test-driven development, even though the result I was getting was normally the desired goal of testing. It has also taught me to be more careful about tests in loops: if there is no guarantee that the loop body will execute then the tests inside it can be completely useless.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/496482-8660572596257843069?l=holdenweb.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=whVu9eKe5Lg:clekP4nap3s:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=whVu9eKe5Lg:clekP4nap3s:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=whVu9eKe5Lg:clekP4nap3s:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/whVu9eKe5Lg&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Wave Goodbye</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/agChWzLjKeo/wave-goodbye.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-8337330493550569525</id>
		<updated>2010-08-05T21:48:37+00:00</updated>
		<content type="html">So Google's &lt;a href=&quot;http://googleblog.blogspot.com/2010/08/update-on-google-wave.html&quot;&gt;blog announced today&lt;/a&gt; that development of Google Wave &quot;as a standalone product&quot; will end because &quot;Wave has not seen the adoption we would like&quot;. It's kind of a shame, because Wave was intriguing, but as an infrequent Wave user I found several issues that made it less than user-friendly. So here are a few points that developers might like to take home from the train-wreck that is Wave (100 developers for two years is a substantial investment, even for Google). The servers will continue to be available &quot;at least until the end of the year&quot;.&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Don't try to replace standard GUI components with inferior and non-intuitive substitutes. The Wave scrollbar was a user interface disaster, and a source of frustration to many of the users I interacted with.&lt;/li&gt;
&lt;li&gt;Don't promote technologies that depend heavily on high-bandwidth connectivity, or at least not for Internet use. Many times I was left frustrated, not knowing whether the Wave had crashed or whether it was simply waiting for a server response.&lt;/li&gt;
&lt;li&gt;Realize that even the best technologies need marketing and publicity. 80%+ of desktop computer users don't use Windows because it's the best system, they use it because it's the best alternative they know about. If people don't know about your technology they won't use it, and techies alone probably aren't the right user base to make a product viral. &lt;/li&gt;
&lt;/ol&gt;In some ways I am sorry that the Wave didn't succeed as so many techies apparently thought it would. In other ways I am disappointed that the technology didn't really deliver on its promise. It's one of those things that needs to be ubiquitous to succeed.&lt;br /&gt;
&lt;br /&gt;
Google's &lt;a href=&quot;http://www.computerworld.com/s/article/9158858/Google_slapped_with_class_action_lawsuit_over_Buzz&quot;&gt;misstep with Buzz&lt;/a&gt; earlier this year probably didn't help either - it led to distrust about Google's intentions with regard to (or, worse, competence at securing) users' personal data.&lt;br /&gt;
&lt;br /&gt;
So whatever the next big thing on the Web is going to be, it isn't going to be Google Wave. RIP.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/496482-8337330493550569525?l=holdenweb.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=agChWzLjKeo:CkkSAkqNop4:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=agChWzLjKeo:CkkSAkqNop4:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=agChWzLjKeo:CkkSAkqNop4:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/agChWzLjKeo&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">DjangoCon US is International</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/NY-_J6oxB24/djangocon-us-is-international.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-4475360640117780686</id>
		<updated>2010-08-05T18:58:38+00:00</updated>
		<content type="html">As registrations for &lt;a href=&quot;http://djangocon.us/&quot;&gt;DjangoCon US&lt;/a&gt; grow it's been interesting to see where people are coming from. I originally thought that it would be US-only. While US delegates dominate the lists as you might expect, we have people coming from all over the world. Here's a graphic showing the distribution of delegates across the globe. &lt;br /&gt;
&lt;div class=&quot;separator&quot;&gt;&lt;a href=&quot;http://4.bp.blogspot.com/_JT1n2tt-4Wg/TFsxI92jhXI/AAAAAAAAAW4/XgU-4EM1ORg/s1600/DelegateDistribution.png&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;222&quot; src=&quot;http://4.bp.blogspot.com/_JT1n2tt-4Wg/TFsxI92jhXI/AAAAAAAAAW4/XgU-4EM1ORg/s400/DelegateDistribution.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;I think it's a measure of Django's excellence that DjangoCon attracts people from so far away. I well remember when Jacob Kaplan-Moss and Adrian Holovaty first came to PyCon in Washington DC to describe the system they were putting together. At that stage Django wasn't open source, and the encouragement of the enthusiastic PyCon audience was a major factor in its becoming so. The software has come a huge distance in a relatively short time, and is now a major Python success story.&lt;br /&gt;
&lt;br /&gt;
There are still places left at the conference if you would like to &lt;a href=&quot;http://djangocon.us/tickets/&quot;&gt;register&lt;/a&gt;. Portland is an intriguing city that offers a warm welcome to visitors, and the Doubletree is a green hotel with excellent accommodation. The conference room rate is only guaranteed until August 13, so make sure to &lt;a href=&quot;http://doubletree.hilton.com/en/dt/groups/personalized/RLLC-DT-DJA-20100905/index.jhtml?WT.mc_id=POG&quot;&gt;book your accommodation&lt;/a&gt; soon.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/496482-4475360640117780686?l=holdenweb.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=NY-_J6oxB24:aCuXL3_ouaw:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=NY-_J6oxB24:aCuXL3_ouaw:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=NY-_J6oxB24:aCuXL3_ouaw:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/NY-_J6oxB24&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Wanted: Win32-savvy developers for core Python</title>
		<link href="http://ramblings.timgolden.me.uk/2010/08/05/wanted-win32-savvy-developers-for-core-python/"/>
		<id>http://ramblings.timgolden.me.uk/2010/08/05/wanted-win32-savvy-developers-for-core-python/</id>
		<updated>2010-08-05T09:44:54+00:00</updated>
		<content type="html">&lt;p&gt;A &lt;a href=&quot;http://mail.python.org/pipermail/python-dev/2010-August/102788.html&quot;&gt;python-dev post&lt;/a&gt; from &lt;a href=&quot;http://www.blogger.com/profile/15732819755000554717&quot;&gt;Steve Holden&lt;/a&gt; gave rise to a wider discussion about the effectiveness of the buildbot system. But also to the question of having more people involved in core Python development who are knowledgeable about the Windows aspects of the core and the stdlib.&lt;/p&gt;
&lt;p&gt;To get involved you certainly don&amp;#8217;t need to be a Windows guru, nor a Python guru. You don&amp;#8217;t need to have oodles of time on your hands. (Although all of the above would help). You do need a willingness to chase down occasionally obscure failing code paths and propose and implement patches. Or workarounds. Or documentation improvements. At present there is a very small number of us watching and fixing win32 issues and, speaking for myself, I have very little time available to help. The more people there are, each of which may have very little time, the more time is available overall to help Python develop and improve.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;d like to get involved but haven&amp;#8217;t bothered previously, please bother now. &lt;/p&gt;
&lt;p&gt;If you&amp;#8217;d like to get involved but aren&amp;#8217;t sure what to do, ping me or drop into &lt;a href=&quot;http://webchat.freenode.net/?channels=python-dev&quot;&gt;#python-dev on IRC&lt;/a&gt; or just go to the Python bug tracker and look for &lt;a href=&quot;http://bugs.python.org/issue?%40search_text=&amp;#038;ignore=file%3Acontent&amp;#038;title=&amp;#038;%40columns=title&amp;#038;id=&amp;#038;%40columns=id&amp;#038;stage=&amp;#038;creation=&amp;#038;creator=&amp;#038;activity=&amp;#038;%40columns=activity&amp;#038;%40sort=activity&amp;#038;actor=&amp;#038;nosy=&amp;#038;type=&amp;#038;components=15&amp;#038;versions=&amp;#038;dependencies=&amp;#038;assignee=&amp;#038;keywords=&amp;#038;priority=&amp;#038;%40group=priority&amp;#038;status=1&amp;#038;%40columns=status&amp;#038;resolution=&amp;#038;nosy_count=&amp;#038;message_count=&amp;#038;%40pagesize=50&amp;#038;%40startwith=0&amp;#038;%40queryname=&amp;#038;%40old-queryname=&amp;#038;%40action=search&quot;&gt;Windows-related problems&lt;/a&gt;. (That search isn&amp;#8217;t exhaustive as it relies on someone setting the Component field, but it certainly brings some results back).&lt;/p&gt;
&lt;p&gt;Guido&amp;#8217;s &lt;a href=&quot;http://mail.python.org/pipermail/python-dev/2010-July/102306.html&quot;&gt;recently expressed a wish&lt;/a&gt; to give more people commit privileges, and MSDN have in the past generously provided free licences to allow core developers to develop and test on different Windows and Visual Studio versions.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s &lt;a href=&quot;http://www.python.org/dev/&quot;&gt;documentation on python.org&lt;/a&gt; for developers, and a new &lt;a href=&quot;http://docs.pythonsprints.com/core_development/beginners.html&quot;&gt;in-progress document&lt;/a&gt; by Brian Curtin on the Python sprints site.&lt;/p&gt;
&lt;p&gt;Even if your contribution is to confirm that a bug still applies, or has been fixed, or to add tests to an undertested module which you use yourself, or to clarify or add some documentation, it will still be a very useful addition.&lt;/p&gt;</content>
		<author>
			<name>Tim Golden</name>
			<uri>http://ramblings.timgolden.me.uk</uri>
		</author>
		<source>
			<title type="html">Moderate Realism » Tech</title>
			<subtitle type="html">The ramblings of Tim Golden</subtitle>
			<link rel="self" href="http://ramblings.timgolden.me.uk/category/tech/feed"/>
			<id>http://ramblings.timgolden.me.uk/category/tech/feed</id>
			<updated>2010-08-16T17:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-04</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/TQ5eRyCZ2z0/"/>
		<id>http://www.magpiebrain.com/2010/08/04/links-for-2010-08-04/</id>
		<updated>2010-08-04T21:03:43+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.linux.com/news/enterprise/systems-management/335742-open-source-toolchains-for-linux-systems-administrators&quot;&gt;Open Source Toolchains for Linux Systems Administrators&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/devops&quot;&gt;devops&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/agile&quot;&gt;agile&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/toolchain&quot;&gt;toolchain&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/linux&quot;&gt;linux&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=TQ5eRyCZ2z0:6BAKHTy1Abw:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=TQ5eRyCZ2z0:6BAKHTy1Abw:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=TQ5eRyCZ2z0:6BAKHTy1Abw:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=TQ5eRyCZ2z0:6BAKHTy1Abw:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=TQ5eRyCZ2z0:6BAKHTy1Abw:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-03</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/Io2bBC2w3Rc/"/>
		<id>http://www.magpiebrain.com/2010/08/03/links-for-2010-08-03/</id>
		<updated>2010-08-03T21:01:32+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.atariage.com/forums/topic/166916-halo-for-the-2600-released-at-cge-download-the-game-here/page__p__2062848#entry2062848&quot;&gt;Halo for the 2600 Released&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;An interesting description in the rationale and mechanics of creating Halo for the 2600&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/atari&quot;&gt;atari&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/2600&quot;&gt;2600&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/halo&quot;&gt;halo&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/fps&quot;&gt;fps&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/games&quot;&gt;games&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=Io2bBC2w3Rc:Wflz-t3zU8k:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=Io2bBC2w3Rc:Wflz-t3zU8k:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=Io2bBC2w3Rc:Wflz-t3zU8k:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=Io2bBC2w3Rc:Wflz-t3zU8k:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=Io2bBC2w3Rc:Wflz-t3zU8k:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Flying High: OpenGL from Python, Part 2</title>
		<link href="http://tartley.com/?p=1207"/>
		<id>http://tartley.com/?p=1207</id>
		<updated>2010-08-03T09:04:43+00:00</updated>
		<content type="html">&lt;p&gt;&lt;em&gt;This is second in a series of articles about algorithmically generating geometry to drive OpenGL from Python.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;http://tartley.com/?p=1142&quot;&gt;&amp;lt;&amp;lt; Back to part 1&lt;/a&gt;&lt;br /&gt;
&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Last time we got as far as creating some instances of our super-simple Shape class, and having Glyph and Render classes convert those to arrays for OpenGL and render them. This time, we start using that infrastructure to create some more interesting geometries, which means &lt;/em&gt;&lt;em&gt;there&amp;#8217;s less code, and more pretty pictures. &lt;/em&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;&lt;strong&gt;Composite Shapes&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In order to create more complex shapes by composing instances of existing ones, we need a simple composite shape:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
class MultiShape(object):

    def __init__(self):
        self.children = []
        self.matrices = []

    def add(self, child, pos=None, orientation=None):
        self.children.append(child)
        self.matrices.append(Matrix(pos, orientation))
&lt;/pre&gt;
&lt;p&gt;A MultiShape contains a list of child Shapes, and a matrix for each child, indicating the child&amp;#8217;s position and orientation relative to the MultiShape&amp;#8217;s front-and-center.&lt;/p&gt;
&lt;p&gt;This is probably as good a point as any to confess that for the purposes of this demo, I ended up writing my own Matrix class, along with my own Orientation class. Even my Vec3, which earlier I showed you defined as a named tuple, gradually started to sprout some methods, until it became a fully-formed custom vector class. This was pretty silly &amp;#8211; it easily doubled the size of my code-base, and while it felt like rewarding and productive work, it was actually a waste of time. With hindsight, I should have predicted this would happen, and started out using an existing library for things like this, such as Euclid or Numpy. Way it goes.&lt;/p&gt;
&lt;p&gt;Anyhow, if a Multishape is going to be usable wherever a Shape is currently used, it needs to provide the same interface, which luckily is very simple &amp;#8211; it just needs to provide iterables of vertices, faces and face_colors. Here is how MultiShape provides a sequence of vertices, by chaining the vertices of all its children, each vertex transformed by the matrix of the relevant child shape:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
@property
def vertices(self):
    return (
        matrix.transform(vertex)
        for child, matrix in zip(self.children, self.matrices)
        for vertex in child.vertices
    )
&lt;/pre&gt;
&lt;p&gt;There is an inefficiency to this. When MultiShapes are nested, I&amp;#8217;m transforming each vertex once for every branch in the tree. It would be cheaper to just multiply the matrices of nested MultiShapes, and then have the top-level MultiShape apply the resulting transforms to the vertices of each of its children. However, we&amp;#8217;re only performing this work at application start-up, not every frame, so I&amp;#8217;m choosing to eat it for the sake of simple-as-possible code.&lt;/p&gt;
&lt;p&gt;Similar properties are defined on MultiShape to provide sequences of  face indices and face_colors, by aggregating those of its children.&lt;/p&gt;
&lt;p&gt;Using MultiShape, we can now easily compose groups of our basic Shapes. A new factory function composes a bunch of cubes into the same MultiShape:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
def CubeCorners(edge, color1, color2):
    multi = MultiShape()
    multi.add(
        Cube(edge, repeat(color1)),
        position=Origin,
    )
    for pos in list(product(*repeat([-1, +1], 3))):
        multi.add(
            Cube(edge/2, repeat(color2)),
            position=Vec3(*pos) * (edge / 2),
        )
    return multi
&lt;/pre&gt;
&lt;div id=&quot;attachment_1212&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-cube-cluster2.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1212 &quot; title=&quot;A cluster of cubes, rendered in one glDrawElements call&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-cube-cluster2.png&quot; alt=&quot;A cluster of cubes, rendered in one glDrawElements call&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A cluster of cubes, rendered in one glDrawElements call&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Another new factory function, &lt;em&gt;RingOf:&lt;/em&gt;&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
def RingOf(child, radius, number):
    multi = MultiShape()
    angle = 0
    orientation = Orientation()
    delta_angle = 2 * pi / number
    while angle &amp;lt; 2 * pi:
        angle += delta_angle
        pos = Vec3(0, radius * sin(angle), radius * cos(angle))
        orientation.pitch(delta_angle)
        multi.add(child, pos, orientation)
    return multi
&lt;/pre&gt;
&lt;p&gt;returns copies of a given child shape, arranged in a ring:&lt;/p&gt;
&lt;div id=&quot;attachment_1211&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-ring1.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1211&quot; title=&quot;A ring of cubes&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-ring1.png&quot; alt=&quot;A ring of cubes&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A ring of cubes&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;attachment_1213&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-ring2.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1213 &quot; title=&quot;A ring of truncated cubes&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-ring2.png&quot; alt=&quot;A ring of truncated cubes&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A ring of truncated cubes&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;attachment_1215&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-ring3.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1215   &quot; title=&quot;A ring of interpenetrated tetrahedrons. This is just starting to look a bit like a thorny geometric mushie trip, which in this context I'm counting as a success.&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-ring3.png&quot; alt=&quot;A ring of interpenetrated tetrahedrons&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A ring of interpenetrated tetrahedrons&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;If we can compose basic shapes into rings, we can also compose rings into&amp;#8230; um&amp;#8230; &lt;em&gt;tri-axis-rings&lt;/em&gt;:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
def TriRing(edge, radius, number, colors):
    multi = MultiShape()
    ring = RingOf(Cube(edge, colors), radius, number)
    multi.add(ring, orientation=Orientation(XAxis))
    multi.add(ring, orientation=Orientation(YAxis))
    multi.add(ring, orientation=Orientation(ZAxis, XAxis))
    return multi
&lt;/pre&gt;
&lt;div id=&quot;attachment_1216&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-tri-ring.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1216   &quot; title=&quot;Tri-axis rings. If you look carefully, you can make out some depth-buffer fighting where the three rings intersect, but I'm moving to fast to worry about that now.&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-tri-ring.png&quot; alt=&quot;Tri-axis rings&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Tri-axis rings&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Because we&amp;#8217;re drawing each MultiShape using a single iteration of the Render.draw() loop, we&amp;#8217;ve massively reduced the overhead in drawing each Shape, so we can easily add all of these at once into the world at 60fps, although it does form a bit of a visual cacophony:&lt;/p&gt;
&lt;div id=&quot;attachment_1217&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-all-rings-etc.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1217&quot; title=&quot;All the rings, plus some other stuff&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-all-rings-etc.png&quot; alt=&quot;All the rings, plus some other stuff&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;All the rings, plus some other stuff&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;I wonder how much stuff we can add into a MultiShape before it starts to affect the framerate? Let&amp;#8217;s investigate&amp;#8230; How about a spherical glob of red blood cubes:&lt;/p&gt;
&lt;div id=&quot;attachment_1238&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/08/screen-glob-red-cubes2.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1238 &quot; title=&quot;A glob of red blood cubes&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/08/screen-glob-red-cubes2.png&quot; alt=&quot;A glob of red blood cubes&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A glob of red blood cubes&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;It turns out I can get about 14,000 cubes (168,000 triangles) &lt;a href=&quot;http://tartley.com/?feed=rss2#update&quot;&gt;[1]&lt;/a&gt; into a single MultiShape like this before the framerate starts to drop. I&amp;#8217;m still rendering these as regular ctypes arrays, not OpenGL vertex buffers (I don&amp;#8217;t think my hardware supports that), so all the geometry is being sent needlessly over the bus to the GPU every frame.&lt;/p&gt;
&lt;p&gt;How about an alternative, the RgbCubeCluster:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
def RgbCubeCluster(edge, cluster_edge, cube_count):
    cluster = MultiShape()
    for _ in xrange(cube_count):
        color = Color.Random()
        pos = Vec3(
            color.r - 128,
            color.g - 128,
            color.b - 128,
        ) * (cluster_edge / 256)
        cluster.add(
            shape=Cube(edge, repeat(color)),
            position=pos,
        )
        return cluster
&lt;/pre&gt;
&lt;p&gt;This creates a cluster of cubes, each one colored by its position in RGB space.&lt;/p&gt;
&lt;div id=&quot;attachment_1218&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-rgb-cluster.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1218&quot; title=&quot;An RGB cube cluster&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-rgb-cluster.png&quot; alt=&quot;An RGB cube cluster&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;An RGB cube cluster&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;We still have enough &lt;em&gt;oomph&lt;/em&gt; left over to dive the camera right into the midst of the RgbCubeCluster and reveal that all the previous stuff is still in the world too:&lt;/p&gt;
&lt;div id=&quot;attachment_1221&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/08/screen-rgbcluster-and-everything.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1221 &quot; title=&quot;Whirling machinery at the center of an RgbCluster&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/08/screen-rgbcluster-and-everything.png&quot; alt=&quot;Whirling machinery at the center of an RgbCluster&quot; width=&quot;840&quot; height=&quot;672&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Whirling machinery at the center of an RgbCluster&lt;/p&gt;&lt;/div&gt;
&lt;h2&gt;&lt;strong&gt;Recursively Generated Geometry&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Can we make any more interesting recursively-defined geometry? The first thing I thought of  (no doubt this has been done many times before) was the 3D equivalent of a &lt;a href=&quot;http://en.wikipedia.org/wiki/Koch_curve&quot;&gt;Koch curve&lt;/a&gt;: Take a tetrahedron, and for each face, embed a new, smaller tetrahedron sticking out of it. Recursively repeat this for each of the new smaller triangles that have been formed.&lt;/p&gt;
&lt;p&gt;The first time I coded this, successive iterations literally replaced every new surface triangle that was formed by the process, with an arbitrary break after eight or so iterations. I was quite surprised by the result, which turned out to look like a slightly corrugated cube. At first I naturally assumed that a bug in my code was the cause, but after a period of contemplation, I realised this was the correct geometric result. The reason for it can be seen in this Wikimedia diagram of the first three iterations of forming a Koch surface:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/08/Koch_surface_0_through_3.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1224&quot; title=&quot;Koch_surface_0_through_3&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/08/Koch_surface_0_through_3.png&quot; alt=&quot;&quot; width=&quot;600&quot; height=&quot;219&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The first iteration replaces every triangle by sticking a new tetrahedron out of it &amp;#8211; exactly as I had done for every face of my original. The next iteration sticks smaller tetrahedrons onto every new surface, and the edges of these new, smaller tetrahedrons all line up with each other, to form long, contiguous straight seams in the resulting shape. By the third iteration (the final one shown here) the end result is becoming apparent. Each successive iteration merely reduces the size of the ridges &amp;#8211; the overall shape of the surface is unchanged.&lt;/p&gt;
&lt;p&gt;I modified my algorithm to only replace the triangular faces of the newly-formed smaller tetrahedrons, rather than replacing every triangular surface, and the result is this more pleasing snowflake shape.&lt;/p&gt;
&lt;div id=&quot;attachment_1223&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/08/screen-koch-tetra.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1223 &quot; title=&quot;A Koch tetrahedron&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/08/screen-koch-tetra.png&quot; alt=&quot;A Koch tetrahedron&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A Koch tetrahedron&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;This algorithm is about 60 lines of code. A similar operation can be done on a cube, by poking a new, smaller cube out of each of its faces:&lt;/p&gt;
&lt;div id=&quot;attachment_1225&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/08/screen-koch-cube.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1225 &quot; title=&quot;A Koch cube&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/08/screen-koch-cube.png&quot; alt=&quot;A Koch cube&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A Koch cube&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;The deeper red parts are the original cube and the early generations of children. The lighter yellow parts are the later generations.&lt;/p&gt;
&lt;p&gt;The final and best example in this section was supplied by Oscar Lindberg, who was interested enough on my old blog post about this to download the code and produce some shapes of his own. Screenshots can&amp;#8217;t do it justice, but the full stately geometry becomes wonderfully apparent when it&amp;#8217;s in motion. The &lt;em&gt;tetrix&lt;/em&gt;, aka the &lt;a href=&quot;http://en.wikipedia.org/wiki/Sierpinski_triangle&quot;&gt;Sierpinski tetrahedron&lt;/a&gt;:&lt;/p&gt;
&lt;div id=&quot;attachment_1226&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/08/screen-sierpinski.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1226&quot; title=&quot;The tetrix, aka Siepinski Tetrahedron&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/08/screen-sierpinski.png&quot; alt=&quot;The tetrix, aka Siepinski Tetrahedron&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;The tetrix, aka Siepinski Tetrahedron&lt;/p&gt;&lt;/div&gt;
&lt;h2&gt;&lt;strong&gt;Odds and Ends&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;That&amp;#8217;s about all I&amp;#8217;ve got to show you. Overall I&amp;#8217;m really pleased by this, and excited to do some more of the same going forward.&lt;/p&gt;
&lt;p&gt;You may have noticed I&amp;#8217;ve cheated a little in the demo / screenshots &amp;#8211; some of them show clear evidence of the rudimentary lighting shader I added (e.g. topmost faces are slightly lighter in color than other faces.) It would be simple enough to fake this, by providing slightly varying colors for each face of our shapes, but for those of you looking at the code: I didn&amp;#8217;t do that. Instead, I had Glyph generate arrays of surface normals, which is done by Glyph.get_glnormals(), which works pretty much just like all the other Glyph methods we examined in part 1. I was getting tired of explaining how Glyph worked, so I figured you were probably getting tired of it too, and wouldn&amp;#8217;t mind if I skipped a little which wasn&amp;#8217;t strictly necessary.&lt;/p&gt;
&lt;p&gt;I was initially a little disappointed by the performance at rendering many independently positioned and oriented objects, but now it&amp;#8217;s picked up (see footnote &lt;a href=&quot;http://tartley.com/?feed=rss2#update&quot;&gt;[1]&lt;/a&gt;), it&amp;#8217;s perfectly acceptable: a little over 450 separately moving cubes at 60fps. The OpenGL bindings in PyOpenGL wisely choose to prefer correctness and robustness over performance by default, so as a result, calling OpenGL from Python is not fast out of the box. The &lt;a href=&quot;http://pyopengl.sourceforge.net/documentation/&quot;&gt;PyOpenGL documentation&lt;/a&gt; suggests many ways in which this performance can be regained once your program is working and debugged. I&amp;#8217;m not yet using any of these suggestions, so hopefully my sluggish performance could be improved substantially.&lt;/p&gt;
&lt;p&gt;In addition, Richard Jones suggested that the innermost Render.draw() loop could possibly benefit from &lt;a href=&quot;http://www.cython.org/&quot;&gt;Cython&lt;/a&gt; (optional static typing to be added to code written in a less-dynamic subset of Python.) This would not just improve the general performance of the code in that loop, by actually compiling it to C, but in doing so, it would eliminate the Python / C boundary performance penalties, and this is something I&amp;#8217;m excited to try out in the near future.&lt;/p&gt;
&lt;p&gt;&lt;a id=&quot;update&quot;&gt;[1]&lt;/a&gt; &lt;strong&gt;Update:&lt;/strong&gt; A couple of hours after hitting publish on this, I discover that switching from the PyOpenGL bindings to those built into pyglet gives me two to four times the frame rate, for zero code change except the imports. Clearly I don&amp;#8217;t understand how to get the best performance out of PyOpenGL. I&amp;#8217;ve been back and updated the performance stats in this post, and hope to make another post about this at some point when I understand what I was doing wrong.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The demonstrated &lt;/em&gt;&lt;em&gt;code &lt;/em&gt;&lt;em&gt;is available via Mercurial, from &lt;a href=&quot;http://code.google.com/p/flyinghigh-opengl-from-python&quot;&gt;http://code.google.com/p/flyinghigh-opengl-from-python&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content>
		<author>
			<name>Jonathan Hartley</name>
			<uri>http://tartley.com</uri>
		</author>
		<source>
			<title type="html">tartley.com</title>
			<subtitle type="html">A website dedicated to oneself has been described as the greatest act of hubris. Welcome aboard.</subtitle>
			<link rel="self" href="http://tartley.com/?feed=rss2"/>
			<id>http://tartley.com/?feed=rss2</id>
			<updated>2010-09-03T19:22:07+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-08-02</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/9QapOBl5uuk/"/>
		<id>http://www.magpiebrain.com/2010/08/02/links-for-2010-08-02/</id>
		<updated>2010-08-02T21:02:36+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://bldgblog.blogspot.com/2010/07/gunnery-pagodas-manhattan-niagara.html&quot;&gt;BLDGBLOG: Gunnery Pagodas / Manhattan Niagara / The University of War&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;Some rather stagering photmontages. I want this book.&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/photography&quot;&gt;photography&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/art&quot;&gt;art&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/montage&quot;&gt;montage&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/photomontage&quot;&gt;photomontage&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/japanese&quot;&gt;japanese&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/outofprint&quot;&gt;outofprint&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/books&quot;&gt;books&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=9QapOBl5uuk:vJOtvwYIQk0:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=9QapOBl5uuk:vJOtvwYIQk0:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=9QapOBl5uuk:vJOtvwYIQk0:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=9QapOBl5uuk:vJOtvwYIQk0:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=9QapOBl5uuk:vJOtvwYIQk0:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Integrating SQLAlchemy into a CherryPy application</title>
		<link href="http://www.defuze.org/archives/222-integrating-sqlalchemy-into-a-cherrypy-application.html"/>
		<id>http://www.defuze.org/?p=222</id>
		<updated>2010-08-01T08:20:50+00:00</updated>
		<content type="html">&lt;p&gt;Quite often, people come on the &lt;a href=&quot;http://www.cherrypy.org/wiki/CherryPyIrcChannel&quot;&gt;CherryPy IRC channel&lt;/a&gt; asking about the way to use SQLAlchemy with CherryPy. There are a &lt;a href=&quot;http://code.google.com/p/webpyte/source/browse/trunk/webpyte/sqlalchemy_tool.py&quot;&gt;couple&lt;/a&gt; of good &lt;a href=&quot;http://tools.cherrypy.org/wiki/SQLA&quot;&gt;recipes&lt;/a&gt; on the tools wiki but I find them a little complex to begin with. Not to the recipes&amp;#8217; fault, many people don&amp;#8217;t necessarily know about CherryPy &lt;a href=&quot;http://www.cherrypy.org/wiki/CustomTools&quot;&gt;tools&lt;/a&gt; and &lt;a href=&quot;http://www.cherrypy.org/wiki/CustomPlugins&quot;&gt;plugins&lt;/a&gt; at that stage.&lt;/p&gt;
&lt;p&gt;The following recipe will try to make the example complete whilst as simple as possible to allow folks to start up with &lt;a href=&quot;http://www.sqlalchemy.org/&quot;&gt;SQLAlchemy&lt;/a&gt; and &lt;a href=&quot;http://www.cherrypy.org/&quot;&gt;CherryPy&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;span&gt;import&lt;/span&gt; &lt;span&gt;os&lt;/span&gt;, &lt;span&gt;os&lt;/span&gt;.&lt;span&gt;path&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;import&lt;/span&gt; cherrypy
&lt;span&gt;from&lt;/span&gt; cherrypy.&lt;span&gt;process&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; wspbus, plugins
&amp;nbsp;
&lt;span&gt;from&lt;/span&gt; sqlalchemy &lt;span&gt;import&lt;/span&gt; create_engine
&lt;span&gt;from&lt;/span&gt; sqlalchemy.&lt;span&gt;orm&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; scoped_session, sessionmaker
&lt;span&gt;from&lt;/span&gt; sqlalchemy.&lt;span&gt;ext&lt;/span&gt;.&lt;span&gt;declarative&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; declarative_base
&lt;span&gt;from&lt;/span&gt; sqlalchemy &lt;span&gt;import&lt;/span&gt; Column
&lt;span&gt;from&lt;/span&gt; sqlalchemy.&lt;span&gt;types&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; String, Integer
&amp;nbsp;
&lt;span&gt;# Helper to map and register a Python class a db table&lt;/span&gt;
Base = declarative_base&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; Message&lt;span&gt;&amp;#40;&lt;/span&gt;Base&lt;span&gt;&amp;#41;&lt;/span&gt;:
    __tablename__ = &lt;span&gt;'message'&lt;/span&gt;
    &lt;span&gt;id&lt;/span&gt; = Column&lt;span&gt;&amp;#40;&lt;/span&gt;Integer, primary_key=&lt;span&gt;True&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    value =  Column&lt;span&gt;&amp;#40;&lt;/span&gt;String&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, message&lt;span&gt;&amp;#41;&lt;/span&gt;:
        Base.&lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;value&lt;/span&gt; = message
&amp;nbsp;
    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__str__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;value&lt;/span&gt;.&lt;span&gt;encode&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'utf-8'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__unicode__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;value&lt;/span&gt;
&amp;nbsp;
    @&lt;span&gt;staticmethod&lt;/span&gt;
    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;list&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;session&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;return&lt;/span&gt; session.&lt;span&gt;query&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;Message&lt;span&gt;&amp;#41;&lt;/span&gt;.&lt;span&gt;all&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; SAEnginePlugin&lt;span&gt;&amp;#40;&lt;/span&gt;plugins.&lt;span&gt;SimplePlugin&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, bus&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;&amp;quot;&amp;quot;&amp;quot;
        The plugin is registered to the CherryPy engine and therefore
        is part of the bus (the engine *is* a bus) registery.
&amp;nbsp;
        We use this plugin to create the SA engine. At the same time,
        when the plugin starts we create the tables into the database
        using the mapped class of the global metadata.
&amp;nbsp;
        Finally we create a new 'bind' channel that the SA tool
        will use to map a session to the SA engine at request time.
        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        plugins.&lt;span&gt;SimplePlugin&lt;/span&gt;.&lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, bus&lt;span&gt;&amp;#41;&lt;/span&gt;
        &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;sa_engine&lt;/span&gt; = &lt;span&gt;None&lt;/span&gt;
        &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;bus&lt;/span&gt;.&lt;span&gt;subscribe&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;quot;bind&amp;quot;&lt;/span&gt;, &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;bind&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    &lt;span&gt;def&lt;/span&gt; start&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        db_path = &lt;span&gt;os&lt;/span&gt;.&lt;span&gt;path&lt;/span&gt;.&lt;span&gt;abspath&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;os&lt;/span&gt;.&lt;span&gt;path&lt;/span&gt;.&lt;span&gt;join&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;os&lt;/span&gt;.&lt;span&gt;curdir&lt;/span&gt;, &lt;span&gt;'my.db'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;sa_engine&lt;/span&gt; = create_engine&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'sqlite:///%s'&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; db_path, echo=&lt;span&gt;True&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        Base.&lt;span&gt;metadata&lt;/span&gt;.&lt;span&gt;create_all&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;.&lt;span&gt;sa_engine&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    &lt;span&gt;def&lt;/span&gt; stop&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;if&lt;/span&gt; &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;sa_engine&lt;/span&gt;:
            &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;sa_engine&lt;/span&gt;.&lt;span&gt;dispose&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
            &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;sa_engine&lt;/span&gt; = &lt;span&gt;None&lt;/span&gt;
&amp;nbsp;
    &lt;span&gt;def&lt;/span&gt; bind&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, session&lt;span&gt;&amp;#41;&lt;/span&gt;:
        session.&lt;span&gt;configure&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;bind=&lt;span&gt;self&lt;/span&gt;.&lt;span&gt;sa_engine&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; SATool&lt;span&gt;&amp;#40;&lt;/span&gt;cherrypy.&lt;span&gt;Tool&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;&amp;quot;&amp;quot;&amp;quot;
        The SA tool is responsible for associating a SA session
        to the SA engine and attaching it to the current request.
        Since we are running in a multithreaded application,
        we use the scoped_session that will create a session
        on a per thread basis so that you don't worry about
        concurrency on the session object itself.
&amp;nbsp;
        This tools binds a session to the engine each time
        a requests starts and commits/rollbacks whenever
        the request terminates.
        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        cherrypy.&lt;span&gt;Tool&lt;/span&gt;.&lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, &lt;span&gt;'on_start_resource'&lt;/span&gt;,
                               &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;bind_session&lt;/span&gt;,
                               priority=&lt;span&gt;20&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
        &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;session&lt;/span&gt; = scoped_session&lt;span&gt;&amp;#40;&lt;/span&gt;sessionmaker&lt;span&gt;&amp;#40;&lt;/span&gt;autoflush=&lt;span&gt;True&lt;/span&gt;,
                                                  autocommit=&lt;span&gt;False&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    &lt;span&gt;def&lt;/span&gt; _setup&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        cherrypy.&lt;span&gt;Tool&lt;/span&gt;._setup&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        cherrypy.&lt;span&gt;request&lt;/span&gt;.&lt;span&gt;hooks&lt;/span&gt;.&lt;span&gt;attach&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'on_end_resource'&lt;/span&gt;,
                                      &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;commit_transaction&lt;/span&gt;,
                                      priority=&lt;span&gt;80&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    &lt;span&gt;def&lt;/span&gt; bind_session&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        cherrypy.&lt;span&gt;engine&lt;/span&gt;.&lt;span&gt;publish&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'bind'&lt;/span&gt;, &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;session&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        cherrypy.&lt;span&gt;request&lt;/span&gt;.&lt;span&gt;db&lt;/span&gt; = &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;session&lt;/span&gt;
&amp;nbsp;
    &lt;span&gt;def&lt;/span&gt; commit_transaction&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        cherrypy.&lt;span&gt;request&lt;/span&gt;.&lt;span&gt;db&lt;/span&gt; = &lt;span&gt;None&lt;/span&gt;
        &lt;span&gt;try&lt;/span&gt;:
            &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;session&lt;/span&gt;.&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        &lt;span&gt;except&lt;/span&gt;:
            &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;session&lt;/span&gt;.&lt;span&gt;rollback&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;  
            &lt;span&gt;raise&lt;/span&gt;
        &lt;span&gt;finally&lt;/span&gt;:
            &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;session&lt;/span&gt;.&lt;span&gt;remove&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
&amp;nbsp;
&amp;nbsp;
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; Root&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
    @cherrypy.&lt;span&gt;expose&lt;/span&gt;
    &lt;span&gt;def&lt;/span&gt; index&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;# print all the recorded messages so far&lt;/span&gt;
        msgs = &lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;msg&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;for&lt;/span&gt; msg &lt;span&gt;in&lt;/span&gt; Message.&lt;span&gt;list&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;cherrypy.&lt;span&gt;request&lt;/span&gt;.&lt;span&gt;db&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;
        cherrypy.&lt;span&gt;response&lt;/span&gt;.&lt;span&gt;headers&lt;/span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'content-type'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt; = &lt;span&gt;'text/plain'&lt;/span&gt;
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;&amp;quot;Here are your list of messages: %s&amp;quot;&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; &lt;span&gt;'&lt;span&gt;\n&lt;/span&gt;'&lt;/span&gt;.&lt;span&gt;join&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;msgs&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    @cherrypy.&lt;span&gt;expose&lt;/span&gt;
    &lt;span&gt;def&lt;/span&gt; record&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, msg&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;# go to /record?msg=hello world to record a &amp;quot;hello world&amp;quot; message&lt;/span&gt;
        m = Message&lt;span&gt;&amp;#40;&lt;/span&gt;msg&lt;span&gt;&amp;#41;&lt;/span&gt;
        cherrypy.&lt;span&gt;request&lt;/span&gt;.&lt;span&gt;db&lt;/span&gt;.&lt;span&gt;add&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;m&lt;span&gt;&amp;#41;&lt;/span&gt;
        cherrypy.&lt;span&gt;response&lt;/span&gt;.&lt;span&gt;headers&lt;/span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'content-type'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt; = &lt;span&gt;'text/plain'&lt;/span&gt;
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;&amp;quot;Recorded: %s&amp;quot;&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; m
&amp;nbsp;
&lt;span&gt;if&lt;/span&gt; __name__ == &lt;span&gt;'__main__'&lt;/span&gt;:
    SAEnginePlugin&lt;span&gt;&amp;#40;&lt;/span&gt;cherrypy.&lt;span&gt;engine&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;.&lt;span&gt;subscribe&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    cherrypy.&lt;span&gt;tools&lt;/span&gt;.&lt;span&gt;db&lt;/span&gt; = SATool&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    cherrypy.&lt;span&gt;tree&lt;/span&gt;.&lt;span&gt;mount&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;Root&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;, &lt;span&gt;'/'&lt;/span&gt;, &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;span&gt;'/'&lt;/span&gt;: &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;span&gt;'tools.db.on'&lt;/span&gt;: &lt;span&gt;True&lt;/span&gt;&lt;span&gt;&amp;#125;&lt;/span&gt;&lt;span&gt;&amp;#125;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    cherrypy.&lt;span&gt;engine&lt;/span&gt;.&lt;span&gt;start&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    cherrypy.&lt;span&gt;engine&lt;/span&gt;.&lt;span&gt;block&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The general idea is to use the plugin mechanism to register functions on an engine basis and enable a tool that will provide an access to the SQLAlchemy session at request time.&lt;/p&gt;</content>
		<author>
			<name>Sylvain Hellegouarch</name>
			<uri>http://www.defuze.org</uri>
		</author>
		<source>
			<title type="html">defuze.org</title>
			<link rel="self" href="http://www.defuze.org/feed/atom"/>
			<id>http://www.defuze.org/feed/atom</id>
			<updated>2010-08-23T21:22:33+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Flying High: Hobbyist OpenGL from Python</title>
		<link href="http://tartley.com/?p=1142"/>
		<id>http://tartley.com/?p=1142</id>
		<updated>2010-07-31T13:58:30+00:00</updated>
		<content type="html">&lt;p&gt;&lt;em&gt;This is a transcript-from-memory (what I wish I&amp;#8217;d said) of the talk I just gave at &lt;a href=&quot;http://www.europython.eu/&quot;&gt;EuroPython&lt;/a&gt; 2010, for which I owe a debt of gratitude to Richard Jones for his last-minute moral support while wrestling with projectors and refresh rates; and to the whole team of hard-working volunteers, especially John Pinner &amp;amp; Richard Taylor, who gave so much time and effort to make EuroPython in the UK brilliant once again.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The demonstrated &lt;/em&gt;&lt;em&gt;code &lt;/em&gt;&lt;em&gt;is available via Mercurial, from &lt;a href=&quot;http://code.google.com/p/flyinghigh-opengl-from-python&quot;&gt;http://code.google.com/p/flyinghigh-opengl-from-python&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;hr /&gt;With this talk I want to give an overview of creating 3D graphics in OpenGL from Python. Instead of covering topics already covered by a thousand OpenGL tutorials, I want to shift attention towards some ideas of how to generate the input to your renderer &amp;#8211; how to algorithmically create geometry. I&amp;#8217;ll show that with just a paltry few hundred lines of relatively simple code, you can generate some interestingly chunky shapes &amp;#8211; virtual sculptures, if you will. Since this talk has the word &lt;em&gt;hobbyist&lt;/em&gt; in the title, I want to emphasise how easy this is, and I want to have some fun with the pretty pictures.
&lt;p&gt;Out of interest, how many people here are already expert OpenGL users &lt;em&gt;(a few hands hesitantly go up, then some think about it and go down again&lt;/em&gt;) err, I mean how many have already used OpenGL to do anything at all &lt;em&gt;(about half the people raise their hand&lt;/em&gt;.) Alright, well, I want you all to leave here enthused to go generate your own images or animations or games.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Inspirations&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;As the field of computer graphics advances, there&amp;#8217;s an understandable tendency for more photorealism, This is laudable, but I also feel that the effort expended on achieving this technical goal is often undertaken without considering whether photorealism is the best aesthetic choice for a particular project.&lt;/p&gt;
&lt;p&gt;In the past, games and other applications adopted particular visual styles out of technical necessity. As is often the case, these restrictions resulted in a diverse blossoming of creative ideas, producing an enormous set of distinctive visual styles and experiences.&lt;/p&gt;
&lt;div id=&quot;attachment_1148&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;img class=&quot;size-full wp-image-1148&quot; title=&quot;Non-photo-realistic Quake&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/nprquake.jpg&quot; alt=&quot;Non-photo-realistic Quake&quot; width=&quot;640&quot; height=&quot;480&quot; /&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Non-photo-realistic Quake&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Crucially, the most successful and memorable examples of these were projects that found ways to work in harmony with the restrictions of the medium, rather than attempting to gloss over them.&lt;/p&gt;
&lt;div id=&quot;attachment_1150&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;img class=&quot;size-full wp-image-1150&quot; title=&quot;Rez HD&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/RezHDA.jpg&quot; alt=&quot;Rez HD&quot; width=&quot;640&quot; height=&quot;359&quot; /&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Rez HD&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Advances in computing power and technique provide modern games and applications with a far wider range of options in how to present themselves visually, and yet the greater proportion of them seem content with a conventional and unimaginative &amp;#8216;near-photorealistic&amp;#8217; appearance. This disappoints me, because I feel that projects that opt for a more highly stylised look, when appropriately chosen, can create a vastly more striking and memorable artistic experiences. This is true in movies and all kinds of art.&lt;/p&gt;
&lt;div id=&quot;attachment_1153&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;img class=&quot;size-full wp-image-1153&quot; title=&quot;Waking Life&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/wakinglife1.jpg&quot; alt=&quot;Waking Life&quot; width=&quot;640&quot; height=&quot;386&quot; /&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Waking Life&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;As an amateur graphics programmer, I don&amp;#8217;t have large resources nor much experience to throw at the problem, so my options and my abilities are limited. But, like a good artist, I believe it should still be possible to create things that are both strikingly beautiful and highly functional, either by working with the restrictions of the medium, or by finding creative ways to exploit or extend them.&lt;/p&gt;
&lt;div id=&quot;attachment_1151&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;img class=&quot;size-full wp-image-1151&quot; title=&quot;Love&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/love.jpg&quot; alt=&quot;Love&quot; width=&quot;640&quot; height=&quot;274&quot; /&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Love&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;In particular, the kind of minimal, clean-lined aesthetic that amateur OpenGL programs take on by default are useful for their crisp precision, as charting and visualisation tools. But above that, I love them for their stark minimalism, their clean lines and homogeneous fields of colour.&lt;/p&gt;
&lt;div id=&quot;attachment_1147&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;img class=&quot;size-full wp-image-1147&quot; title=&quot;Tron Legacy&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/tron.jpg&quot; alt=&quot;Tron Legacy&quot; width=&quot;640&quot; height=&quot;264&quot; /&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Tron Legacy&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;I wish more professional game developers had an incentive to aim for less conventional aesthetics &amp;#8211; whether they be deliberately retro, or else striking out in some new direction of their own. It&amp;#8217;s that brave minority of projects which do this which form my inspiration.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Starting Point&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;m assuming we already have a minimal OpenGL application, that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Opens a window&lt;/li&gt;
&lt;li&gt;Provides an OpenGL context for us to render to&lt;/li&gt;
&lt;li&gt;Sets appropriate 3D projection matrix&lt;/li&gt;
&lt;li&gt;Sets the initial modelview matrix state based on the position and orientation of a &amp;#8216;camera&amp;#8217; object&lt;/li&gt;
&lt;li&gt;Calls our empty &amp;#8216;draw&amp;#8217; function once per monitor refresh.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This results in a blank screen, at 60fps. Here&amp;#8217;s a screenshot, so you can see exactly what it&amp;#8217;s doing:&lt;/p&gt;
&lt;div id=&quot;attachment_1156&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/blank1.png&quot;&gt;&lt;img class=&quot;size-large wp-image-1156  &quot; title=&quot;A blank screen&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/blank1-1024x640.png&quot; alt=&quot;A blank screen&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A blank screen&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;I&amp;#8217;m using pyglet &amp;amp; PyOpenGL for this, but this isn&amp;#8217;t important. Any framework that provides the above abilities, such as PyGame, along with bindings to OpenGL, will be just fine. Whichever framework you use, this minimal application might take on the order of about 150 lines of code, and is covered in countless tutorials all over the web.&lt;/p&gt;
&lt;p&gt;From here on in I plan to show (or at least describe) pretty much all of the code that I add on top of this minimal OpenGL loop.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Goal&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;To begin with, I&amp;#8217;m going to lead you as quickly as I can through a Shape class, that model 3D shapes, in a way useful for the creation of geometry, and then a Glyph class that converts these geometries into arrays for OpenGL. Finally these arrays get passed into a Render class, which simply calls glDrawElements to render them.&lt;/p&gt;
&lt;div id=&quot;attachment_1158&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/fun-stuff.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1158 &quot; title=&quot;Our Goal&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/fun-stuff.png&quot; alt=&quot;Our Goal&quot; width=&quot;492&quot; height=&quot;246&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Our Goal&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Once the above infrastructure is in place, we can have some fun generating interesting shapes to make pretty pictures with. The conventional way to provide geometry to your OpenGL code is by  loading your data from files. Today though, I want to stick with generating  geometry from code, to see where that leads.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Modelling Polyhedra&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;A polyhedron is a 3D shape with flat faces and straight edges. We can model coloured polyhedra using a simple Shape class:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
Vec3 = namedtuple('Vec3', 'x y z')
Color = namedtuple('Color', 'r g b a')

class Shape(object):

    def __init__(self, vertices, faces, face_colors):
        # list of Vec3s
        self.vertices = vertices

        # list of faces, each face is a list of indices into 'vertices'
        self.faces = faces

        # List of colors, one per face
        self.face_colors = face_colors
&lt;/pre&gt;
&lt;p&gt;An instance of this class, for example, might represent a yellow cube, or a tetrahedron with green and black faces, or any other coloured polyhedron we can imagine.&lt;/p&gt;
&lt;p&gt;To demonstrate how classes Shape, Glyph and Render hang together, let&amp;#8217;s examine an even simpler example, a yellow triangle joined to a red square:&lt;/p&gt;
&lt;div id=&quot;attachment_1159&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;img class=&quot;size-full wp-image-1159 &quot; title=&quot;Red Triangle &amp;amp; Yellow Square&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/triangle-square.png&quot; alt=&quot;Red Triangle &amp;amp; Yellow Square&quot; width=&quot;300&quot; height=&quot;265&quot; /&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Red Triangle &amp;amp; Yellow Square&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;You can see this geometry features five vertices (v0 to v4), which are used by the two faces. This might be represented by an instance of Shape:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
v0 = Vec3( 1,  1, 0)
v1 = Vec3( 1, -1, 0)
v2 = Vec3(-1, -1, 0)
v3 = Vec3(-1   1, 0)
v4 = Vec3( 1,  0, 2)

red = Color(255, 0, 0, 255)
yellow = Color(255, 255, 0, 255)

shape = Shape(
    vertices=[v0, v1, v2, v3, v4],
    faces=[
        [2, 3, 4],    # f0, triangle
        [0, 1, 2, 3], # f1, square
    ],
    face_colors=[red, yellow],
)
&lt;/pre&gt;
&lt;p&gt;The integers in the &amp;#8216;faces&amp;#8217; member are indices into the vertices list. So the triangular face, for example, is formed by linking vertices 2, 3 and 4.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Step 1. Creating a Ctypes Vertex array&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In order to render our Shape, we need to convert it to some ctypes arrays that OpenGL will eat:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;glvertices &amp;#8211; an array of GLfloats (three for each vertex)&lt;/li&gt;
&lt;li&gt;glindices &amp;#8211; an array of GLubytes (one for each index of each face)&lt;/li&gt;
&lt;li&gt;glcolors &amp;#8211; an array of GLubytes (four for each vertex)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To generate glvertices, we need to dereference the indices in Shape.faces, to produce a new list of vertices, rearranged into the order they are going to be drawn:&lt;/p&gt;
&lt;div id=&quot;attachment_1164&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/dereference-indices.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1164 &quot; title=&quot;Step 1. Dereference indices&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/dereference-indices.png&quot; alt=&quot;Step 1. Dereference indices&quot; width=&quot;457&quot; height=&quot;316&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Step 1. Dereference indices&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;The most visible aspect of this change is that the vertices are re-ordered, such that the indices now simply read &amp;#8217;0, 1, 2, 3, 4, 5&amp;#8230;&amp;#8217;. However that isn&amp;#8217;t actually necessary. The important part of this transformation is that vertices which are re-used are now duplicated in the vertex list. For example v0 now occurs twice. As a result of this vertex duplication, one the two instances of &amp;#8217;0&amp;#8242; in the faces lists now instead reads &amp;#8217;3&amp;#8242; (referencing the new second copy of v0).&lt;/p&gt;
&lt;p&gt;This duplication of vertices is required, because when v0 is used for the first time, it is as part of the red triangle, and when it is used the second time it is as part of the yellow square. The color of the vertex changes from one occurrence to the next. All the attributes of a vertex (position, color, texture co-ords, normals, etc) are treated as an atomic unit, so whenever any attribute changes, as the color is changing here, the vertex position needs to be redundantly specified again, so as to create a new unique vertex with its own unique attribute values. Even if the color of v0 in our example was identical for each use, we will see later that other vertex attributes such as surface normals will still differ. Don&amp;#8217;t sweat trying to eliminate these redundancies, they are necessary, unless every single attribute of the re-used vertex (including surface normals) are identical.&lt;/p&gt;
&lt;p&gt;The code in Glyph.get_glverts() performs this dereferencing step:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
class Glyph(object):

    def get_glverts(self, shape, num_glverts):
        glverts = chain.from_iterable(
            shape.vertices[index]
            for face in shape.faces
            for index in face
        )
        ArrayType = GLfloat * (num_glverts * 3)
        return ArrayType(*glverts)
&lt;/pre&gt;
&lt;p&gt;This uses a generator to produce the vertices in the order that we need them. &amp;#8216;ArrayType&amp;#8217; shows the standard idiom to create a ctypes array &amp;#8211; we take the datatype of the array elements, in this case GLfloat since our vertex positions consist of three floats, and multiply it by the required length of the array. This yields a new array type. The final return statement instantiates this array type using the data supplied by the glverts generator.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Step 2. Creating Ctypes Index Arrays&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The second job Glyph has to do is create a ctypes indices array, which is derived from the Shape&amp;#8217;s faces. In doing this, it has to break the Shape&amp;#8217;s faces down into individual triangles.&lt;/p&gt;
&lt;div id=&quot;attachment_1165&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/tessellate-indices.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1165 &quot; title=&quot;Step 2. Tessellate indices&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/tessellate-indices.png&quot; alt=&quot;Step 2. Tessellate indices&quot; width=&quot;577&quot; height=&quot;316&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Step 2. Tessellate indices&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;The vertex list is unchanged by this step, and the first face &amp;#8211; the triangle &amp;#8211; is also unchanged. The second face, the square, has been broken into two triangles.&lt;/p&gt;
&lt;p&gt;There are well-known algorithms for breaking an arbitrary polygon down into individual triangles. Using the utility functions found in the GLU library, this can be done in about 150 lines of Python. But in the interests of keeping it simple, I decided to restrict our code to just handling convex faces. Tessellating these faces can be done using a considerably simpler algorithm:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
def tessellate(face):
    '''
    Break the given face into triangles.
    e.g. [0, 1, 2, 3, 4] -&amp;gt;
    [[0, 1, 2], [0, 2, 3], [0, 3, 4]]
    Does not work on concave faces.
    '''
    return (
        [face[0], face[i], face[i + 1]]
        for i in xrange(1, len(face) - 1)
    )
&lt;/pre&gt;
&lt;p&gt;We again use a generator, to simply join up the face&amp;#8217;s first vertex with all the other vertices, like this:&lt;/p&gt;
&lt;div id=&quot;attachment_1166&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/tessellation.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1166 &quot; title=&quot;Tessellation of convex faces&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/tessellation.png&quot; alt=&quot;Tessellation of convex faces&quot; width=&quot;446&quot; height=&quot;197&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Tessellation of convex faces&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Now we have our tessellate function, Glyph can now create the glindices array in much the same way as it generated the glvertices. I wasn&amp;#8217;t smart enough to write this as a generator first time around, I presume it would require more than one generator to do it (anyone?), so I&amp;#8217;m needlessly creating an in-memory copy of the sequence, but it turns out I need to take its length right afterwards anyway, so what the heck:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
class Glyph(object):

    def get_glindices(self, faces):
        glindices = []
        face_offset = 0
        for face in faces:
            indices = xrange(face_offset, face_offset + len(face))
            glindices.extend(chain(*tessellate(indices)))
            face_offset += len(face)
        ArrayType = GLubyte * len(glindices)
        return ArrayType(glindices)
&lt;/pre&gt;
&lt;p&gt;This is more complex than get_glvertices because it is performing both of the transformations described in steps 1 and 2. But it&amp;#8217;s still pretty straightforward. Note that the type of the index array will have change from GLubytes to GLushorts (or GLuints) if the number of vertices rises above 256 (or 65,536.)&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Step 3. Creating Ctypes Color Arrays&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Finally, we need an array of vertex colors. This is the simplest of the lot, generated by repeating the face_color for each face, once per vertex:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
class Glyph(object):

    def get_glcolors(self, faces, face_colors, num_glvertices):
        glcolors = chain.from_iterable(
            repeat(color, len(face))
            for face, color in izip(faces, face_colors)
        )
        ArrayType = GLubyte * (num_glvertices * 4)
        return ArrayType(chain(*glcolors))
&lt;/pre&gt;
&lt;h2&gt;&lt;strong&gt;First Light&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;It&amp;#8217;s might seem like a teensy bit of a slog to get here, but it hasn&amp;#8217;t been more than sixty lines of code, and now we&amp;#8217;re in a position to pass our ctypes arrays into OpenGL&amp;#8217;s drawElements. This happens in our Render.draw() method:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
class Render(object):

    def draw(self, world):
        for item in world:
            glVertexPointer(3, GL_FLOAT, 0, item.glyph.glvertices)
            glColorPointer(4, GL_UNSIGNED_BYTE, 0, item.glyph.glcolors)

            # TODO: handle the item's position and orientation

            glDrawElements(
                GL_TRIANGLES,
                len(item.glyph.glindices),
                GL_UNSIGNED_BYTE,
                item.glyph.glindices
            )
&lt;/pre&gt;
&lt;p&gt;This is canonical OpenGL render code, so I&amp;#8217;m not going to dissect it, but now we get some actual visible output:&lt;/p&gt;
&lt;div id=&quot;attachment_1168&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-triangle-square.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1168 &quot; title=&quot;Red triangle, yellow square&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-triangle-square.png&quot; alt=&quot;Red triangle, yellow square&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Red triangle, yellow square&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Hooray! \o/ We can move our camera position around, and view this 3D object from different angles.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s a minor wrinkle here that I&amp;#8217;m glossing over. I&amp;#8217;ve turned on backface culling, so the triangle and square aren&amp;#8217;t visible if we view them from the back. For all our future examples I plan on using closed polyhedra, so we won&amp;#8217;t be able to see the &amp;#8216;backs&amp;#8217; of the faces &amp;#8211; those will be on the inside of the polyhedron.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Fun Stuff&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;So now we&amp;#8217;ve got all our infrastructure in place, we can start creating factory functions to churn out some Shapes. Let&amp;#8217;s start with something straightforward, a tetrahedron (triangle-based pyramid):&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
def Tetrahedron(edge, face_colors=None):
    size = edge / sqrt(2)/2
    vertices = [
        (+size, +size, +size),
        (-size, -size, +size),
        (-size, +size, -size),
        (+size, -size, -size),
    ]
    faces = [ [0, 2, 1], [1, 3, 0], [2, 3, 1], [0, 3, 2] ]
    return Shape(vertices, faces, face_colors)
&lt;/pre&gt;
&lt;p&gt;Which produces:&lt;/p&gt;
&lt;div id=&quot;attachment_1176&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-tetrahedron.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1176&quot; title=&quot;A tetrahedron&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-tetrahedron.png&quot; alt=&quot;A tetrahedron&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A tetrahedron&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Then a cube factory:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
def Cube(edge, face_colors=None):
    e2 = edge / 2
    verts = list(itertools.product(*repeat([-e2, +e2], 3)))
    faces = [
        [0, 1, 3, 2], # left
        [4, 6, 7, 5], # right
        [7, 3, 1, 5], # front
        [0, 2, 6, 4], # back
        [3, 7, 6, 2], # top
        [1, 0, 4, 5], # bottom
    ]
    return Shape(verts, faces, face_colors)
&lt;/pre&gt;
&lt;p&gt;The six faces are quite evident, but the use of &lt;em&gt;itertools.product&lt;/em&gt; to produce the list of vertices perhaps deserves a bit of exposition. It&amp;#8217;s an inspired tip from &lt;a rel=&quot;external nofollow&quot; href=&quot;http://tzotzioy.blogspot.com/&quot;&gt;ΤΖΩΤΖΙΟΥ&lt;/a&gt;. Just to spell it out in longhand:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
&amp;gt;&amp;gt;&amp;gt; from itertools import repeat, product
&amp;gt;&amp;gt;&amp;gt; list(product(*repeat([-1, +1], 3)))
[(-1, -1, -1), (-1, -1, 1), (-1, 1, -1), (-1, 1, 1),
 (1, -1, -1), (1, -1, 1), (1, 1, -1), (1, 1, 1)]
&lt;/pre&gt;
&lt;p&gt;So there are the eight vertices of the cube, and that gets us the following:&lt;/p&gt;
&lt;div id=&quot;attachment_1177&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-cube.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1177 &quot; title=&quot;A cube&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-cube.png&quot; alt=&quot;A cube&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A cube&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;We can add a few more vertices and faces, to make ourselves a truncated cube:&lt;/p&gt;
&lt;div id=&quot;attachment_1187&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-truncated-cube.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1187&quot; title=&quot;A truncated cube&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-truncated-cube.png&quot; alt=&quot;A truncated cube&quot; width=&quot;840&quot; height=&quot;672&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A truncated cube&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Once we&amp;#8217;ve got truncated cubes, we might as well add one last face to form the entrance:&lt;/p&gt;
&lt;div id=&quot;attachment_1188&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-space-station.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1188     &quot; title=&quot;A truncated cube with entrance: This is a reference to the space stations from the 1984 computer game 'Elite'.&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-space-station.png&quot; alt=&quot;A truncated cube with entrance&quot; width=&quot;840&quot; height=&quot;672&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A truncated cube with entrance&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;There&amp;#8217;s nothing to stop us adding several of these shapes into the world at once, but since we haven&amp;#8217;t yet moved any of them away from the origin, they just sit there, embedded within one another:&lt;/p&gt;
&lt;div id=&quot;attachment_1196&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-cube-tetra.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1196 &quot; title=&quot;A cube and tetrahedron interpenetrate&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-cube-tetra.png&quot; alt=&quot;A cube and tetrahedron interpenetrate&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A cube and tetrahedron interpenetrate&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;attachment_1197&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-trunccube-two-tetras.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1197 &quot; title=&quot;A truncated cube with two tetrahedrons&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-trunccube-two-tetras.png&quot; alt=&quot;A truncated cube with two tetrahedrons&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;A truncated cube with two tetrahedrons&lt;/p&gt;&lt;/div&gt;
&lt;h2&gt;&lt;strong&gt;Moving objects around&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In our earlier Render.draw() method, we left a &amp;#8216;TODO&amp;#8217; comment in place, to note that we weren&amp;#8217;t yet handling item positions and orientations. Here&amp;#8217;s what Render.draw looks like when we fill that code in:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
class Render(object):

    def draw(self, world):
        for item in world:
            glVertexPointer(3, GL_FLOAT, 0, item.glyph.glvertices)
            glColorPointer(4, GL_UNSIGNED_BYTE, 0, item.glyph.glcolors)

            glPushMatrix()
            glTranslatef(*item.position)
            glMultMatrixf(item.orientation.matrix)

            glDrawElements(
                GL_TRIANGLES,
                len(item.glyph.glindices),
                GL_UNSIGNED_BYTE,
                item.glyph.glindices
            )
            glPopMatrix()
&lt;/pre&gt;
&lt;p&gt;Again, this is very standard OpenGL usage. To set an item&amp;#8217;s &lt;em&gt;position&lt;/em&gt; attribute, I&amp;#8217;m going to use a bit of code that I already snuck into the demo without telling you about. It&amp;#8217;s the code that moves the camera around in space.  A simplified version is here, class Orbit, which will return a new position each time it gets called. The locus of this position is an orbit around the origin:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
class Orbit(object):
    def __init__(self, distance, speed, phase=None):
        self.distance = distance
        self.speed = speed
        if phase is None:
            phase = random.uniform(0, 2 * pi)
        self.phase = phase

    def __call__(self, time):
        bearing = time * self.speed + self.phase
        x = self.distance * math.sin(bearing)
        z = self.distance * math.cos(bearing)
        return Vec3(x, 0, z)
&lt;/pre&gt;
&lt;p&gt;The actual camera uses a slightly longer version I call WobblyOrbit (not shown), which operates in exactly the same way.  Any &amp;#8216;mover&amp;#8217; class, i.e. one that returns a Vec3 position when called, can be used to move the camera, or any other item, around in space:&lt;/p&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
class GameItem(object):
    def __init__(self, ** kwargs):
       self.__dict__.update(** kwargs)

world.add( GameItem(
    shape=Cube(1, repeat(red)),
    mover=Orbit(distance=20, speed=4),
) )

# then, in world.update():
for item in self.items:
    if item.mover:
        item.position = item.mover(self.time)
&lt;/pre&gt;
&lt;p&gt;Similarly, we can spin items using &amp;#8216;spinner&amp;#8217; classes, that tweak an item&amp;#8217;s orientation as time goes by.&lt;/p&gt;
&lt;p&gt;With these all in place, we can now add many Shapes to the world, each moving and rotating independently:&lt;/p&gt;
&lt;div id=&quot;attachment_1199&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-several-shapes.png&quot;&gt;&lt;img class=&quot;size-full wp-image-1199 &quot; title=&quot;Several independantly positioned and oriented shapes&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/screen-several-shapes.png&quot; alt=&quot;Several independantly positioned and oriented shapes&quot; width=&quot;840&quot; height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Several independently positioned and oriented shapes&lt;/p&gt;&lt;/div&gt;
&lt;h2&gt;&lt;strong&gt;Next week: Composite Shapes&amp;#8230;&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;This is all great as far as it goes, but it turns out we have a performance problem. Adding more than about 450 shapes at once starts to slow down below 60fps (This is all on my trusty 2005-era Thinkpad T60 laptop.) The bottleneck turns out to be in our Render.draw() loop. Each of those OpenGL functions are from (wrappers around) the OpenGL C library, and calling across the Python / C boundary like this incurs a per-function call overhead. Also, a second looming problem is that creating more interesting shapes is going to become more onerous and error-prone, as we create longer and more complex lists of vertices and faces in our code.&lt;/p&gt;
&lt;p&gt;One partial solution to both these problems is to use composite shapes, in which we can compose many copies of our basic shapes into one single, more complex shape. This will allow us to use algorithmic means to produce more fun geometry, and will also help us draw more complex shapes, composed of many simpler shapes, without requiring several separate OpenGL function calls for each of the simple shapes.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://tartley.com/?p=1207&quot;&gt;On to Part 2 &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;</content>
		<author>
			<name>Jonathan Hartley</name>
			<uri>http://tartley.com</uri>
		</author>
		<source>
			<title type="html">tartley.com</title>
			<subtitle type="html">A website dedicated to oneself has been described as the greatest act of hubris. Welcome aboard.</subtitle>
			<link rel="self" href="http://tartley.com/?feed=rss2"/>
			<id>http://tartley.com/?feed=rss2</id>
			<updated>2010-09-03T19:22:07+00:00</updated>
		</source>
	</entry>

	<entry>
		<title type="html">A plugin system for unittest(2)</title>
		<link href="http://feedproxy.google.com/~r/voidspace/~3/btNzVL8kGAM/arch_d7_2010_07_24.shtml"/>
		<id>http://feedproxy.google.com/~r/voidspace/~3/btNzVL8kGAM/arch_d7_2010_07_24.shtml</id>
		<updated>2010-07-30T12:15:19+00:00</updated>
		<content type="html">One of the big problems with unittest, which I have been maintaining for well over a year now, is how hard it is to extend. For a long time I've been saying that my &amp;quot;big task&amp;quot; with unittest was to implement a plugin system. ... [838 words]&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/voidspace?a=btNzVL8kGAM:lQb9H6BLbiE:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/voidspace?i=btNzVL8kGAM:lQb9H6BLbiE:F7zBnMyn0Lo&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/voidspace?a=btNzVL8kGAM:lQb9H6BLbiE:V_sGLiPBpWU&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/voidspace?i=btNzVL8kGAM:lQb9H6BLbiE:V_sGLiPBpWU&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/voidspace?a=btNzVL8kGAM:lQb9H6BLbiE:gIN9vFwOqvQ&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/voidspace?i=btNzVL8kGAM:lQb9H6BLbiE:gIN9vFwOqvQ&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/voidspace?a=btNzVL8kGAM:lQb9H6BLbiE:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/voidspace?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/voidspace/~4/btNzVL8kGAM&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Fuzzyman</name>
			<uri>http://www.voidspace.org.uk/python/weblog/index.shtml</uri>
		</author>
		<source>
			<title type="html">The Voidspace Techie Blog</title>
			<subtitle type="html">Python Programming, news on the Voidspace Python Projects and all things techie.</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/voidspace"/>
			<id>http://feeds.feedburner.com/voidspace</id>
			<updated>2010-07-30T17:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-07-28</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/gaJaAZu3_Yg/"/>
		<id>http://www.magpiebrain.com/2010/07/28/links-for-2010-07-28/</id>
		<updated>2010-07-28T21:02:52+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://ietfreport.isoc.org/idref/draft-nottingham-http-cache-channels/&quot;&gt;nottingham-http-cache-channels-01.txt&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/cache&quot;&gt;cache&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/squid&quot;&gt;squid&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/http&quot;&gt;http&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/ietf&quot;&gt;ietf&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.mnot.net/blog/2008/01/04/cache_channels&quot;&gt;mnot’s Weblog: Cache Channels&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/cache&quot;&gt;cache&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/squid&quot;&gt;squid&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/http&quot;&gt;http&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=gaJaAZu3_Yg:W0aEtoqmCcQ:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=gaJaAZu3_Yg:W0aEtoqmCcQ:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=gaJaAZu3_Yg:W0aEtoqmCcQ:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=gaJaAZu3_Yg:W0aEtoqmCcQ:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=gaJaAZu3_Yg:W0aEtoqmCcQ:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Links for 2010-07-27 [del.icio.us]</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/tWtN3bB7B8k/steve.holden"/>
		<id>http://del.icio.us/steve.holden#2010-07-27</id>
		<updated>2010-07-28T07:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nogod.org.nz/wp-content/uploads/2010/07/billboard-in-the-beginning-man-created-god.png&quot;&gt;billboard-in-the-beginning-man-created-god.png (PNG Image, 1920x960 pixels) - Scaled (67%)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://softwarecreation.org/2009/three-dimensions-of-a-software-programmer-how-to-get-things-done/&quot;&gt;Three Dimensions of a Software Programmer: How to get things done&lt;/a&gt;&lt;br /&gt;
Excellent post on the programming craft&lt;/li&gt;
&lt;/ul&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/tWtN3bB7B8k&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content>
		<author>
			<name>Steve</name>
			<email>noreply@blogger.com</email>
			<uri>http://holdenweb.blogspot.com/</uri>
		</author>
		<source>
			<title type="html">For Some Value of &quot;Magic&quot;</title>
			<subtitle type="html">Python, software, open source, plus odd rants about almost anything</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2010-09-03T11:22:30+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-07-27</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/a50bhiYd17A/"/>
		<id>http://www.magpiebrain.com/2010/07/27/links-for-2010-07-27/</id>
		<updated>2010-07-27T21:02:32+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://itchyi.squarespace.com/thelatest/2010/7/20/the-longest-photographic-exposures-in-history.html?SSScrollPosition=232&quot;&gt;The worlds longest photo exposure&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/photography&quot;&gt;photography&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/longexposure&quot;&gt;longexposure&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/pinhole&quot;&gt;pinhole&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=a50bhiYd17A:In-35fpi7yk:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=a50bhiYd17A:In-35fpi7yk:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=a50bhiYd17A:In-35fpi7yk:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=a50bhiYd17A:In-35fpi7yk:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=a50bhiYd17A:In-35fpi7yk:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">rnalexander</title>
		<link href="http://rnalexander.wordpress.com/2010/07/24/barcle-fail/"/>
		<id>http://rnalexander.wordpress.com/?p=70</id>
		<updated>2010-07-24T18:28:37+00:00</updated>
		<content type="html">&lt;ul&gt;
&lt;li&gt;In your online registration, if you&amp;#8217;re only going to accept a specific subset of characters for the password be very clear what they are.&lt;/li&gt;
&lt;li&gt;If the person registering should get that wrong tell them that in the error message, instead of telling them that you can&amp;#8217;t process their application repeated times, and then let them find out about said restrictions when they go through the call centre.&lt;/li&gt;
&lt;li&gt;Also, in your online registration, if you&amp;#8217;re going to offer people &amp;#8216;extra keys&amp;#8217; for your system, please be clear that for each &amp;#8216;extra key&amp;#8217; a person orders, they will also be charged for an &amp;#8216;extra period charge&amp;#8217; as well.  This will prevent your potential clients from being horribly surprised when they see a charge for nearly £200 going through instead of about £50.&lt;/li&gt;
&lt;li&gt;Speaking of charging, give people a confirmation screen before you charge them.  In other words, the first time they see the actual total of what they are about to be charged should not be on the &amp;#8216;Verified by VISA screen&amp;#8217;&lt;/li&gt;
&lt;li&gt;Further to the speaking of charging, when you call people back from a call centre that shows up on their phone as a blocked number, just use the security data they provided, do not also ask the people you call back to give you their credit card number, and their expiration date.&lt;/li&gt;
&lt;li&gt;Further again to the speaking of credit card numbers, do not have someone from the call centre read back a persons credit card number and expiration date to attempt to reassure them.  This is not reassuring, it is, in fact, the opposite of reassuring.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But hey, it&amp;#8217;s early days, and a few mistakes are to be expected.  I&amp;#8217;d only really worry if this kind of behaviour was in some way associated with a bank, I mean, that would really make me uncomfortable.&lt;/p&gt;
&lt;br /&gt;  &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gocomments/rnalexander.wordpress.com/70/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/comments/rnalexander.wordpress.com/70/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godelicious/rnalexander.wordpress.com/70/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/delicious/rnalexander.wordpress.com/70/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gostumble/rnalexander.wordpress.com/70/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/stumble/rnalexander.wordpress.com/70/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godigg/rnalexander.wordpress.com/70/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/digg/rnalexander.wordpress.com/70/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/goreddit/rnalexander.wordpress.com/70/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/reddit/rnalexander.wordpress.com/70/&quot; /&gt;&lt;/a&gt; &lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=rnalexander.wordpress.com&amp;amp;blog=408743&amp;amp;post=70&amp;amp;subd=rnalexander&amp;amp;ref=&amp;amp;feed=1&quot; /&gt;</content>
		<author>
			<name>Ryan Alexander</name>
			<uri>http://rnalexander.wordpress.com</uri>
		</author>
		<source>
			<title type="html">Ryan Alexander</title>
			<subtitle type="html">Expat tech activist and low-budget bon vivant.</subtitle>
			<link rel="self" href="http://rnalexander.wordpress.com/feed/"/>
			<id>http://rnalexander.wordpress.com/feed/</id>
			<updated>2010-07-24T19:22:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-07-22</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/PBDTBxbx82g/"/>
		<id>http://www.magpiebrain.com/2010/07/22/links-for-2010-07-22/</id>
		<updated>2010-07-22T21:01:28+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.debian-administration.org/article/Unattended_Encrypted_Incremental_Network_Backups_Part_1&quot;&gt;Unattended, Encrypted, Incremental Network Backups: Part 1&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/s3&quot;&gt;s3&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/aws&quot;&gt;aws&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/duplicity&quot;&gt;duplicity&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/backup&quot;&gt;backup&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/incremental&quot;&gt;incremental&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/sysadmin&quot;&gt;sysadmin&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/debian&quot;&gt;debian&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://blog.damontimm.com/bash-script-incremental-encrypted-backups-duplicity-amazon-s3/&quot;&gt;Bash Script: Incremental Encrypted Backups with Duplicity (Amazon S3) « damontimm.com&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/s3&quot;&gt;s3&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/aws&quot;&gt;aws&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/duplicity&quot;&gt;duplicity&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/backup&quot;&gt;backup&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/incremental&quot;&gt;incremental&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/sysadmin&quot;&gt;sysadmin&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=PBDTBxbx82g:-awIHfRZ6NM:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=PBDTBxbx82g:-awIHfRZ6NM:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=PBDTBxbx82g:-awIHfRZ6NM:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=PBDTBxbx82g:-awIHfRZ6NM:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=PBDTBxbx82g:-awIHfRZ6NM:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-07-21</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/s3UjJlZJZ7I/"/>
		<id>http://www.magpiebrain.com/2010/07/21/links-for-2010-07-21/</id>
		<updated>2010-07-21T21:02:52+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://nikonpages.heymanphotography.com/tcmod/&quot;&gt;Christophe Heyman Photography &amp;#8211; Nikon Pages&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;Modifying Nikon teleconvertors to take a wider variety of lenses&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/nikon&quot;&gt;nikon&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/teleconvertors&quot;&gt;teleconvertors&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/diy&quot;&gt;diy&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.naturfotograf.com/lens_spec.html&quot;&gt;Special Lenses For Nikon &amp;#039;F&amp;#039; Mount&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;A greta selection of the more exotic Nikon F Mount lens. Including an f/075&amp;#8230;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/nikon&quot;&gt;nikon&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/photography&quot;&gt;photography&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.naturfotograf.com/lens_converter.html&quot;&gt;Teleconverters for Nikon &amp;#039;F&amp;#039; Mount&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/nikon&quot;&gt;nikon&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/teleconvertors&quot;&gt;teleconvertors&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/review&quot;&gt;review&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/photography&quot;&gt;photography&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=s3UjJlZJZ7I:uUj1CaRmXIc:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=s3UjJlZJZ7I:uUj1CaRmXIc:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=s3UjJlZJZ7I:uUj1CaRmXIc:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=s3UjJlZJZ7I:uUj1CaRmXIc:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=s3UjJlZJZ7I:uUj1CaRmXIc:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">AWS: S3 vs EBS-backed instances</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/sX523G95pqk/"/>
		<id>http://www.magpiebrain.com/?p=870</id>
		<updated>2010-07-19T20:09:20+00:00</updated>
		<content type="html">&lt;p&gt;As part of the day job at &lt;a href=&quot;http://www.thoughtworks.com/&quot;&gt;ThoughtWorks&lt;/a&gt;, I&amp;#8217;m involved with &lt;a href=&quot;http://www.thoughtworks.com/aws-training&quot;&gt;training courses&lt;/a&gt; we run in partnership with Amazon, giving people an overview of the AWS service offerings. One of the things we cover that can often cause some confusion is the different types of images &amp;#8211; specifically the difference between S3 and EBS-backed images. I tend to give specific advice over what type of instance I prefer, but before then some detail is in order. &lt;/p&gt;
&lt;h3&gt;S3-hosted Images&lt;/h3&gt;
&lt;p&gt;Instances launched from S3-hosted images use the local disk for the root partition. Once spun up, if you shut down machine down the state of the operating system is lost. The only way to persist data is to store it off-instance &amp;#8211; for example on an attached EBS volume, on S3 or elsewhere. Aside from the lack of persistence of the state of the OS, these images are limited to being 10GB in size &amp;#8211; not a problem for most Linux distros I know of, but a non-starter for some Microsoft images.&lt;/p&gt;
&lt;p&gt;There is also a time delaying spinning these images up, due to the time taken to copy the Image from S3 to the physical machine &amp;#8211; the whole image has to be downloaded before the instance can start the boot up process. In practice, popular images seem to be pretty well cached and so that the delay may not be an issue for you. As with everything in AWS, the barrier to entry is so low it is worth testing this yourself to understand if this is going to be a deal breaker.&lt;/p&gt;
&lt;h3&gt;EBS-backed Images&lt;/h3&gt;
&lt;p&gt;An EBS-backed instance is an EC2 instance which uses such a device as its root partition, rather than local disk. EBS-backed images can boot in seconds (as opposed to minutes for less-well cached S3 images) as they just need to stream enough of the image to start the boot process. They also can be up to 1TB in size &amp;#8211; in other words the max size of any EBS volume. EBS volumes also have different performance characteristics than local drives, which may need to be taken into account depending on your particular use. &lt;/p&gt;
&lt;p&gt;The key benefit is that EBS-backed instances can be &amp;#8216;suspended&amp;#8217; &amp;#8211; by stopping an EBS-backed instance, you can resume it later, with all EBS-backed state (e.g. the OS state) being maintained. In this way it is more akin to the slices at slicehost, or a real, physical machine.&lt;/p&gt;
&lt;p&gt;There is one out and out downside when compared to S3-hosted images &amp;#8211; your charges will be higher. You will be charged for IO, which could mount up depending on your particular usage patterns. You&amp;#8217;re also charged for the allocated size of the EBS volume too.&lt;/p&gt;
&lt;h3&gt;So which is best?&lt;/h3&gt;
&lt;p&gt;Aside from the increased cost, and the differing benefits of a block-storage rather than local disk in terms of performance characteristics, there is one key downside to an EBS. It encourages you to think of EC2 instances as persistent, stable entities which are around forever. In general, I believe you&amp;#8217;ll gain far more from embracing the &amp;#8216;everything fails, deal with it&amp;#8217; ethos &amp;#8211; that is, have your machines configure themselves afresh atop vanilla gold S3-backed AMIs on boot (e.g. using EC2 instance data to download &amp;amp; install your software). This means you cannot fall back into the old thought patterns of constantly patching, tweaking an OS, to the point where attempting to recreate it would be akin to an act of sysadmin archeology.&lt;/p&gt;
&lt;p&gt;There will remain scenarios where EBS-backed instances make sense (and those of you using Windows Server 2008 have no choice), but I always recommend that people moving to AWS limit their use and instead adopt their practices to use the S3 &amp;#8211; thereby also embracing more of the promise of the AWS stack as a whole.&lt;/p&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=sX523G95pqk:aMBLsSoATog:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=sX523G95pqk:aMBLsSoATog:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=sX523G95pqk:aMBLsSoATog:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=sX523G95pqk:aMBLsSoATog:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=sX523G95pqk:aMBLsSoATog:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Loving EuroPython Tutorials</title>
		<link href="http://tartley.com/?p=1137"/>
		<id>http://tartley.com/?p=1137</id>
		<updated>2010-07-18T23:08:53+00:00</updated>
		<content type="html">&lt;p&gt;I&amp;#8217;ve been loving the two days of tutorials preceding the EuroPython conference. This morning I attended &lt;a href=&quot;http://www.mechanicalcat.net/richard/log&quot;&gt;Richard Jones&lt;/a&gt;&amp;#8216; splendid &lt;em&gt;Introduction to Game Programming&lt;/em&gt;. It was an absolute pleasure to be walked through the creation of an example game like this, using Python game libraries like &lt;a href=&quot;http://pyglet.org/&quot;&gt;pyglet&lt;/a&gt; and &lt;a href=&quot;http://cocos2d.org/&quot;&gt;Cocos&lt;/a&gt;, by someone who really knows what he&amp;#8217;s doing. Also, it&amp;#8217;s nice to have something visible to show after a morning&amp;#8217;s work:&lt;/p&gt;
&lt;div id=&quot;attachment_1138&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;img class=&quot;size-full wp-image-1138  &quot; title=&quot;intro-to-game-programming&quot; src=&quot;http://tartley.com/wp-content/uploads/2010/07/intro-to-game-programming.jpg&quot; alt=&quot;My asteroids. Michael your idea of making engine thrust always visible was exactly what I needed to help me capture the screenshot.&quot; width=&quot;744&quot; height=&quot;489&quot; /&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;My asteroids&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;The code is based very heavily on samples that Richard provided and talked us through in great detail, so although I now understand it pretty thoroughly, I can&amp;#8217;t take much credit. Excepting, that is, for a handful of minor tweaks I couldn&amp;#8217;t resist making along the way, like the flickery animated engine thrust, that made me gurgle with delight.&lt;/p&gt;
&lt;p&gt;For the artwork, I stole the shuttle icon (sssshhhhhh!), added the engine thrust, and created the asteroids themselves entirely from scratch in Gimp. They are just rotatable bitmaps, albeit designed in homage of vector graphics of yore, complete with simulated CRT glow. Brilliant!&lt;/p&gt;</content>
		<author>
			<name>Jonathan Hartley</name>
			<uri>http://tartley.com</uri>
		</author>
		<source>
			<title type="html">tartley.com</title>
			<subtitle type="html">A website dedicated to oneself has been described as the greatest act of hubris. Welcome aboard.</subtitle>
			<link rel="self" href="http://tartley.com/?feed=rss2"/>
			<id>http://tartley.com/?feed=rss2</id>
			<updated>2010-09-03T19:22:07+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">EuroPython 2010</title>
		<link href="http://ianozsvald.com/2010/07/17/europython-2010/"/>
		<id>http://ianozsvald.com/?p=1005</id>
		<updated>2010-07-17T22:17:08+00:00</updated>
		<content type="html">&lt;p&gt;I&amp;#8217;m hugely looking forward to &lt;a href=&quot;http://www.europython.eu/&quot;&gt;EuroPython&lt;/a&gt; in Birmingham from Monday. I&amp;#8217;m driving up Monday very early (I wish I&amp;#8217;d booked the hotel room for Sunday night too&amp;#8230;). Browsing through the &lt;a href=&quot;http://www.europython.eu/talks/talk_abstracts/&quot;&gt;abstracts&lt;/a&gt; I&amp;#8217;d say all the following look darned interesting!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;C++ integration&lt;/li&gt;
&lt;li&gt;concurrent sequential processes&lt;/li&gt;
&lt;li&gt;Arduino hacking&lt;/li&gt;
&lt;li&gt;javascript&lt;/li&gt;
&lt;li&gt;OpenData&lt;/li&gt;
&lt;li&gt;aerodynamics&lt;/li&gt;
&lt;li&gt;PyPy and Unladen Swallow&lt;/li&gt;
&lt;li&gt;game programming&lt;/li&gt;
&lt;li&gt;OpenGL&lt;/li&gt;
&lt;li&gt;Pyjamas&lt;/li&gt;
&lt;li&gt;idiomatic Python&lt;/li&gt;
&lt;li&gt;MediaCore&lt;/li&gt;
&lt;li&gt;Twisted and gevent&lt;/li&gt;
&lt;li&gt;science and maths&lt;/li&gt;
&lt;li&gt;SHOGUN machine learning&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;ll bring &lt;a href=&quot;http://blog.aicookbook.com/2010/06/building-a-face-tracking-robot-headroid1-with-python-in-an-afternoon/&quot;&gt;Headroid&lt;/a&gt; along and I hope to organise a Birds of a Feather session on Artificial Intelligence and robotics. If you&amp;#8217;re interested in these topics, I&amp;#8217;d love to say hi!&lt;/p&gt;
&lt;hr /&gt;
Ian applies Artificial Intelligence for companies (&lt;a href=&quot;http://morconsulting.com&quot; title=&quot;Artificial Intelligence consultant&quot;&gt;Mor Consulting&lt;/a&gt;), programs Python, 
produces professional screencasts (&lt;a href=&quot;http://procasts.co.uk/examples.html&quot; title=&quot;Professional screencast production&quot;&gt;ProCasts&lt;/a&gt;), writes &lt;a href=&quot;http://TheScreencastingHandbook.com&quot; title=&quot;Screencasting Tutorial eBook&quot;&gt;The Screencasting Handbook&lt;/a&gt; and is also a sea-side dweller and consumer of fine coffees.

&lt;!--
google_ad_client = &quot;pub-9428211972348006&quot;;
/* 300x250, created 8/6/10 */
google_ad_slot = &quot;2197971840&quot;;
google_ad_width = 300;
google_ad_height = 250;
//--&gt;</content>
		<author>
			<name>Ian Ozsvald</name>
			<uri>http://ianozsvald.com</uri>
		</author>
		<source>
			<title type="html">Entrepreneurial Geekiness » Python</title>
			<subtitle type="html">My thoughts on screencasting, ProCasts and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2010-09-01T17:22:21+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">links for 2010-07-14</title>
		<link href="http://feedproxy.google.com/~r/Magpiebrain/~3/6EGr7UmCbCo/"/>
		<id>http://www.magpiebrain.com/2010/07/14/links-for-2010-07-14/</id>
		<updated>2010-07-14T21:01:21+00:00</updated>
		<content type="html">&lt;ul class=&quot;delicious&quot;&gt;
&lt;li&gt;
&lt;div class=&quot;delicious-link&quot;&gt;&lt;a href=&quot;http://www.igniterealtime.org/projects/openfire/&quot;&gt;Ignite Realtime: Openfire Server&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;delicious-extended&quot;&gt;An OS &amp;quot;Real Time Collaboration&amp;quot; server &amp;#8211; so Jabber with some cool features and plugins&lt;/div&gt;
&lt;div class=&quot;delicious-tags&quot;&gt;(tags: &lt;a href=&quot;http://delicious.com/padark/jabber&quot;&gt;jabber&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/irc&quot;&gt;irc&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/im&quot;&gt;im&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/team&quot;&gt;team&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/collaboration&quot;&gt;collaboration&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/communication&quot;&gt;communication&lt;/a&gt; &lt;a href=&quot;http://delicious.com/padark/opensource&quot;&gt;opensource&lt;/a&gt;)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=6EGr7UmCbCo:cnlIcx_ZQLE:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=6EGr7UmCbCo:cnlIcx_ZQLE:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=6EGr7UmCbCo:cnlIcx_ZQLE:D7DqB2pKExk&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?i=6EGr7UmCbCo:cnlIcx_ZQLE:D7DqB2pKExk&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?a=6EGr7UmCbCo:cnlIcx_ZQLE:dnMXMwOfBR0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Magpiebrain?d=dnMXMwOfBR0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content>
		<author>
			<name>Sam Newman</name>
			<uri>http://www.magpiebrain.com</uri>
		</author>
		<source>
			<title type="html">Magpiebrain</title>
			<subtitle type="html">The blog of Sam Newman</subtitle>
			<link rel="self" href="http://feeds.feedburner.com/Magpiebrain"/>
			<id>http://feeds.feedburner.com/Magpiebrain</id>
			<updated>2010-09-02T21:22:05+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">22,937* faster Python math using pyCUDA</title>
		<link href="http://ianozsvald.com/2010/07/14/22937-faster-python-math-using-pycuda/"/>
		<id>http://ianozsvald.com/?p=992</id>
		<updated>2010-07-14T11:52:10+00:00</updated>
		<content type="html">&lt;p&gt;I&amp;#8217;ve just uploaded a new Mandelbrot.py demo for pyCUDA, it adds a new calculation routine that straddles the numpy (C based math) and the pure-CUDA implementations. In total there are 4 variants to choose from. The speed differences are huge!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; &amp;#8211; this &lt;a href=&quot;http://www.reddit.com/r/Python/comments/cpfaa/22937_faster_python_math_using_pycuda/&quot;&gt;Reddit thread&lt;/a&gt; has more details including real-world timings for two client problems (showing 10-3,677* speed-ups over a C task).&lt;/p&gt;
&lt;p&gt;This post builds upon my earlier &lt;a href=&quot;http://ianozsvald.com/2010/01/26/pycuda-on-windows-and-mac-for-super-fast-python-math-using-cuda/&quot;&gt;pyCUDA on Windows and Mac for super-fast Python math using CUDA&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You&amp;#8217;ll need &lt;a href=&quot;http://developer.nvidia.com/object/cuda_3_1_downloads.html&quot;&gt;CUDA&lt;/a&gt; 3.1 and &lt;a href=&quot;http://mathema.tician.de/software/pycuda&quot;&gt;pyCUDA&lt;/a&gt; installed with a compatible NVIDIA graphics card. This version of the Mandelbrot code forces single precision math &amp;#8211; this means it&amp;#8217;ll work on all CUDA cards (even the older ones &amp;#8211; &lt;a href=&quot;http://www.nvidia.com/object/cuda_gpus.html&quot;&gt;full list&lt;/a&gt;). It runs on my MacBook (Leopard) and Windows, the Windows machines use a 9800 GT and GTX 480. Here&amp;#8217;s what it generates:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/54145418@N00/4793065042/&quot;&gt;&lt;img class=&quot;aligncenter&quot; title=&quot;Mandelbrot.py result for pyCUDA&quot; src=&quot;http://farm5.static.flickr.com/4120/4793065042_0cea04fa97_m.jpg&quot; alt=&quot;&quot; width=&quot;228&quot; height=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The big-beast graphics card for my physics client is a &lt;a href=&quot;http://www.nvidia.com/object/product_geforce_gtx_480_us.html&quot;&gt;GTX 480&lt;/a&gt; &amp;#8211; this is NVIDIA&amp;#8217;s top of the line consumer card (costing £420GBP in the UK a few weeks back). It is huge &amp;#8211; it covers two slots, uses one PCIe 2.0&amp;#215;16 slot and has a requirement for 300-400W of power (I&amp;#8217;m using a 750W PSU to be safe on a Gigabyte GA H55M S2H motherboard):&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/54145418@N00/4793201874/&quot;&gt;&lt;img class=&quot;aligncenter&quot; title=&quot;GTX 480 CUDA card on motherboard&quot; src=&quot;http://farm5.static.flickr.com/4114/4793201874_0fdf5f7c34_m.jpg&quot; alt=&quot;&quot; width=&quot;180&quot; height=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://wiki.tiker.net/PyCuda/Examples/Mandelbrot&quot;&gt;mandelbrot.py&lt;/a&gt; demo has four options (e.g. &amp;#8216;python mandelbrot.py gpu&amp;#8217;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;#8216;gpu&amp;#8217; is a pure CUDA solution on the GPU&lt;/li&gt;
&lt;li&gt;&amp;#8216;gpuarray&amp;#8217; uses a numpy-like CUDA wrapper in Python on the GPU&lt;/li&gt;
&lt;li&gt;&amp;#8216;numpy&amp;#8217; is a pure Numpy (C-based) solution on the CPU&lt;/li&gt;
&lt;li&gt;&amp;#8216;python&amp;#8217; is a pure Python solution on the CPU with numpy arrays&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The default problem is a 1000*1000 Mandelbrot plot with 1000 max iterations. I&amp;#8217;m running this on a 2.9GHz dual core Windows XP SP3 with Python 2.6 (only 1 thread is used for all CPU tests). The timings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;#8216;gpu&amp;#8217; &amp;#8211; 0.07 seconds&lt;/li&gt;
&lt;li&gt;&amp;#8216;gpuarray&amp;#8217; &amp;#8211; 3.45 seconds &amp;#8211; 49* slower than GPU version&lt;/li&gt;
&lt;li&gt;&amp;#8216;numpy&amp;#8217; &amp;#8211; 43.4 seconds &amp;#8211; 620* slower than GPU version&lt;/li&gt;
&lt;li&gt;&amp;#8216;python&amp;#8217; &amp;#8211; 1605.6 seconds &amp;#8211; 22,937* slower than GPU version&lt;/li&gt;
&lt;li&gt;&amp;#8216;python&amp;#8217; with psyco.full() &amp;#8211; 1428.3 seconds &amp;#8211; 20,404* slower than GPU version&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By default mandelbrot.py forces single precision for all the math. Interestingly on my box if I let numpy default to numpy.complex128 (two double precision floating point numbers rather than numpy.complex64 with two single precision floats) then the Python result is faster:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;#8216;numpy&amp;#8217; &amp;#8211; 34.0 seconds (double precision)&lt;/li&gt;
&lt;li&gt;&amp;#8216;python&amp;#8217; &amp;#8211; 627 seconds (double precision) &amp;#8211; 2.5* faster than the single precision version&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &amp;#8217;22,937*&amp;#8217; figure is a little unfair in light of the 627 second result (which is 8,957* slower) but I wanted to use only single precision math for consistency and compatibility across all CUDA cards (the older cards can only do single precision math).&lt;/p&gt;
&lt;p&gt;On my older dual core 2.66GHz machine with a 9800 GT I get:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;#8216;gpu&amp;#8217; &amp;#8211; 1.5 seconds&lt;/li&gt;
&lt;li&gt;&amp;#8216;gpuarray&amp;#8217; &amp;#8211; 7.1 seconds &amp;#8211; 4.7* slower than GPU version&lt;/li&gt;
&lt;li&gt;&amp;#8216;numpy&amp;#8217; &amp;#8211; 51 seconds &amp;#8211; 34* slower than GPU version&lt;/li&gt;
&lt;li&gt;&amp;#8216;python&amp;#8217; &amp;#8211; 1994.3 seconds &amp;#8211; 1,329* slower than GPU version&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we compare the 0.07 seconds for the GTX 480 against the 1.5 seconds for the 9800 GT (albeit on different machines but the runtime is just measuring the GPU work) then the GTX 480 is 21* faster than the 9800 GT. That&amp;#8217;s not a bad speed-up for a couple of years difference in architectures.&lt;/p&gt;
&lt;p&gt;If you take a look at the source code you&amp;#8217;ll see that the &amp;#8216;gpu&amp;#8217; option uses a lump of C-like CUDA code, behind the scenes all pyCUDA code is converted into this C-like code and then down to &lt;a href=&quot;http://en.wikipedia.org/wiki/Parallel_Thread_Execution&quot;&gt;PTX&lt;/a&gt; via their compiler. This is the way to go if you understand the memory model and you want to write very fast code.&lt;/p&gt;
&lt;p&gt;The gpuarray option uses a numpy-like interface to pyCUDA which, behind the scenes, is converted into CUDA code. Because it is compiled from Python code the resulting CUDA code isn&amp;#8217;t as efficient &amp;#8211; the compiler can&amp;#8217;t make the same assumptions about memory usage as I can make when hand-crafting CUDA code (at least &amp;#8211; that&amp;#8217;s my best understanding at present!).&lt;/p&gt;
&lt;p&gt;The numpy version uses C-based math running on the CPU &amp;#8211; generally it is regarded as being &amp;#8216;pretty darned fast&amp;#8217;. The python version uses numpy arrays with straight Python arithmetic, this makes it awfully slow. Psyco 2.0.0 makes it a bit faster.&lt;/p&gt;
&lt;p&gt;Feedback and extensions are welcomed via the &lt;a href=&quot;http://wiki.tiker.net/PyCuda/Examples&quot;&gt;wiki&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;If you want to get started then make sure you have a &lt;a href=&quot;http://www.nvidia.com/object/cuda_gpus.html&quot;&gt;compatible CUDA card&lt;/a&gt;, get pyCUDA (&lt;a href=&quot;http://wiki.tiker.net/PyCuda/Installation&quot;&gt;installation instructions&lt;/a&gt;), compile pyCUDA (takes 30 minutes from scratch if you&amp;#8217;re on a well-known system), try the examples and run &lt;a href=&quot;http://wiki.tiker.net/PyCuda/Examples/Mandelbrot&quot;&gt;mandelbrot.py&lt;/a&gt;. The &lt;a href=&quot;http://lists.tiker.net/listinfo/pycuda&quot;&gt;mailing list&lt;/a&gt; is helpful.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;d be nice to see some comparisons with PyPy, ShedSkin and other Python implementations. You&amp;#8217;ll find links in my older &lt;a href=&quot;http://ianozsvald.com/2008/11/17/making-python-math-196-faster-with-shedskin/&quot;&gt;ShedSkin&lt;/a&gt; post. It&amp;#8217;ll also be interesting to tie this in to some of the A.I. projects in the &lt;a href=&quot;http://aicookbook.com/&quot;&gt;A.I. Cookbook&lt;/a&gt;, I&amp;#8217;ll have to ponder some of the problems that might be tackled.&lt;/p&gt;
&lt;p&gt;Books:&lt;/p&gt;
&lt;p&gt;The following two books will be useful if you&amp;#8217;re new to CUDA. The first is very friendly, I&amp;#8217;m still finding it very useful.&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;td&gt;

&lt;/td&gt;


&lt;hr /&gt;
Ian applies Artificial Intelligence for companies (&lt;a href=&quot;http://morconsulting.com&quot; title=&quot;Artificial Intelligence consultant&quot;&gt;Mor Consulting&lt;/a&gt;), programs Python, 
produces professional screencasts (&lt;a href=&quot;http://procasts.co.uk/examples.html&quot; title=&quot;Professional screencast production&quot;&gt;ProCasts&lt;/a&gt;), writes &lt;a href=&quot;http://TheScreencastingHandbook.com&quot; title=&quot;Screencasting Tutorial eBook&quot;&gt;The Screencasting Handbook&lt;/a&gt; and is also a sea-side dweller and consumer of fine coffees.

&lt;!--
google_ad_client = &quot;pub-9428211972348006&quot;;
/* 300x250, created 8/6/10 */
google_ad_slot = &quot;2197971840&quot;;
google_ad_width = 300;
google_ad_height = 250;
//--&gt;</content>
		<author>
			<name>Ian Ozsvald</name>
			<uri>http://ianozsvald.com</uri>
		</author>
		<source>
			<title type="html">Entrepreneurial Geekiness » Python</title>
			<subtitle type="html">My thoughts on screencasting, ProCasts and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2010-09-01T17:22:21+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Undocumented feature of the week: $PIP_DOWNLOAD_CACHE</title>
		<link href="http://tartley.com/?p=1133"/>
		<id>http://tartley.com/?p=1133</id>
		<updated>2010-07-13T11:46:15+00:00</updated>
		<content type="html">&lt;p&gt;Use Python? You should be using &lt;a href=&quot;http://pypi.python.org/pypi/pip&quot;&gt;&lt;em&gt;Pip&lt;/em&gt;&lt;/a&gt;. A replacement for &lt;em&gt;easy_install&lt;/em&gt;, that supports uninstalling and plays nice with &lt;a href=&quot;http://pypi.python.org/pypi/virtualenv&quot;&gt;&lt;em&gt;virtualenv&lt;/em&gt;&lt;/a&gt;. An &lt;em&gt;apt-get&lt;/em&gt; for Python packages, if you will.&lt;/p&gt;
&lt;p&gt;It has a marvellous undocumented feature. Set the environment variable PIP_DOWNLOAD_CACHE to prevent re-downloading the same packages repeatedly when setting up environments on the same machine:&lt;/p&gt;
&lt;pre&gt;&lt;strong&gt;&amp;gt; set | grep PIP&lt;/strong&gt;
&lt;strong&gt;&lt;span&gt;PIP&lt;/span&gt;&lt;/strong&gt;_DOWNLOAD_CACHE=C:\Documents and Settings\jhartley\.&lt;strong&gt;&lt;span&gt;pip&lt;/span&gt;&lt;/strong&gt;_download_cache

&lt;strong&gt;&amp;gt; pip install mock&lt;/strong&gt;
Downloading/unpacking mock
Creating supposed download cache at C:\Documents and Settings\jhartley\.pip_download_cache
 Downloading mock-0.7.0b2.zip (242Kb): 242Kb downloaded
 Storing download in cache at c:\documents and settings\jhartley\.pip_download_cache\http%3a%2f%2fpypi.python.org%2fpackages%2fsource%2fm%2fmock%2fmock-0.7.0b2.zip
&lt;span&gt;[snip]&lt;/span&gt;
Successfully installed mock

&lt;strong&gt;&amp;gt; pip uninstall mock&lt;/strong&gt;
&lt;span&gt;[snip]&lt;/span&gt;
 Successfully uninstalled mock

&lt;strong&gt;&amp;gt; pip install mock&lt;/strong&gt;
Downloading/unpacking mock
 Using download cache from C:\Documents and Settings\jhartley\.pip_download_cache\http%3A%2F%2Fpypi.python.org%2Fpackages%2Fsource%2Fm%2Fmock%2Fmock-0.7.0b2.zip
&lt;span&gt;[snip]&lt;/span&gt;
Successfully installed mock
&lt;/pre&gt;
&lt;p&gt;(This text is copied from my unholy bastardised shell of choice at work, Windows CMD shell with Cygwin binaries foremost on the PATH.)&lt;/p&gt;
&lt;p&gt;Using the download cache like this is substantially faster. Exactly what you need if you&amp;#8217;re continually setting up environments under various version of Python for testing or what-have-you.&lt;/p&gt;
&lt;p&gt;The directory is created if it doesn&amp;#8217;t exist. Network access is still required when installing like this, presumably for the version checks.&lt;/p&gt;
&lt;p&gt;Thanks to the irrepressible &lt;a href=&quot;http://www.voidspace.org.uk/python/weblog/arch_d7_2010_07_10.shtml#e1185&quot;&gt;fuzzyman&lt;/a&gt; for bringing this to my attention.&lt;/p&gt;</content>
		<author>
			<name>Jonathan Hartley</name>
			<uri>http://tartley.com</uri>
		</author>
		<source>
			<title type="html">tartley.com</title>
			<subtitle type="html">A website dedicated to oneself has been described as the greatest act of hubris. Welcome aboard.</subtitle>
			<link rel="self" href="http://tartley.com/?feed=rss2"/>
			<id>http://tartley.com/?feed=rss2</id>
			<updated>2010-09-03T19:22:07+00:00</updated>
		</source>
	</entry>

</feed>
