<?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>2013-06-19T00:22:15+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">Demonstrating the first Brand Disambiguator (a hacky, crappy classifier that does something useful)</title>
		<link href="http://ianozsvald.com/2013/06/17/demonstrating-the-first-brand-disambiguator-a-hacky-crappy-classifier-that-does-something-useful/"/>
		<id>http://ianozsvald.com/?p=1865</id>
		<updated>2013-06-17T19:13:44+00:00</updated>
		<content type="html">&lt;p&gt;Last week I had the pleasure of talking at both &lt;a href=&quot;http://brightonpy.org/meetings/2013-06-11/&quot;&gt;BrightonPython&lt;/a&gt; and &lt;a href=&quot;http://www.meetup.com/Data-Science-London/events/123032212/&quot;&gt;DataScienceLondon&lt;/a&gt; to about 150 people in total (Robin East &lt;a href=&quot;https://robineast.wordpress.com/2013/06/14/data-science-london-meetup-june-2013/&quot;&gt;wrote-up&lt;/a&gt; the DataScience night). The &lt;a href=&quot;https://github.com/ianozsvald/social_media_brand_disambiguator&quot;&gt;updated code&lt;/a&gt; is in github.&lt;/p&gt;
&lt;p&gt;The goal is to disambiguate the &lt;a href=&quot;https://en.wikipedia.org/wiki/Word_sense&quot;&gt;word-sense&lt;/a&gt; of a token (e.g. &amp;#8220;Apple&amp;#8221;) in a tweet as being either the-brand-I-care-about (in this case &amp;#8211; Apple Inc.) or anything-else (e.g. apple sauce, Shabby Apple clothing, apple juice etc). This is related to named entity recognition, I&amp;#8217;m exploring simple techniques for disambiguation. In both talks people asked if this could classify an arbitrary tweet as being &amp;#8220;about Apple Inc or not&amp;#8221; and whilst this is possible, for this project I&amp;#8217;m restricting myself to the (achievable, I think) goal of robust disambiguation within the 1 month timeline I&amp;#8217;ve set myself.&lt;/p&gt;
&lt;p&gt;Below are the &lt;a href=&quot;https://speakerdeck.com/ianozsvald/detecting-the-right-apples-and-oranges-1-hour-talk-on-python-for-brand-disambiguation-using-scikit-learn-at-brightonpython-june-2013&quot;&gt;slides&lt;/a&gt; from the longer of the two talks at BrightonPython:&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;As noted in the slides for week 1 of the project I built a trivial &lt;a href=&quot;http://scikit-learn.org/stable/modules/linear_model.html#logistic-regression&quot;&gt;LogisticRegression&lt;/a&gt; classifier using the default &lt;a href=&quot;http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer&quot;&gt;CountVectorizer&lt;/a&gt;, applied a threshold and tested the resulting model on a held-out validation set. Now I have a few more weeks to build on the project before returning to &lt;a href=&quot;http://morconsulting.com/&quot;&gt;consulting work&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Currently I use a JSON file of tweets filtered on the term &amp;#8216;apple&amp;#8217;, obtained using the free streaming API from Twitter using cURL. I then annotate the tweets as being in-class (apple-the-brand) or out-of-class (any other use of the term &amp;#8220;apple&amp;#8221;). I used the &lt;a href=&quot;https://pypi.python.org/pypi/chromium_compact_language_detector&quot;&gt;Chromium Language Detector&lt;/a&gt; to filter non-English tweets and also discard English tweets that I can&amp;#8217;t disambiguate for this data set. In total I annotated 2014 tweets. This set contains many duplicates (e.g. retweets) which I&amp;#8217;ll probably thin out later, possibly they over-represent the real frequency of important tokens.&lt;/p&gt;
&lt;p&gt;Next I built a validation set using 100 in- and 100 out-of-class tweets at random and created a separate test/train set with 584 tweets of each class (a balanced set from the two classes but ignoring the issue of duplicates due to retweets inside each class).&lt;/p&gt;
&lt;p&gt;To convert the tweets into a dense matrix for learning I used the CountVectorizer with all the defaults (simple tokenizer [which is not great for tweets], minimum document frequency=1, unigrams only).&lt;/p&gt;
&lt;p&gt;Using the simplest possible approach that could work &amp;#8211; I trained a LogisticRegression classifier with all its defaults on the dense matrix of 1168 inputs. I then apply this classifier to the held-out validation set using a confidence threshold (&amp;gt;92% for in-class, anything less is assumed to be out-of-class). It classifies 51 of the 100 in-class examples as in-class and makes no errors (100% precision, 51% recall). This threshold was chosen arbitrarily on the validation set rather than deriving it from the test/train set (poor hackery on my part), but it satisfied me that this basic approach was learning something useful from this first data set.&lt;/p&gt;
&lt;p&gt;The strong (but not generalised at all!) result for the very basic LogisticRegression classifier will be due to token artefacts in the time period I chose (March 13th 2013 around 7pm for the 2014 tweets). Extracting the top features from LogisticRegression shows that it is identifying terms like &amp;#8220;Tim&amp;#8221;, &amp;#8220;Cook&amp;#8221;, &amp;#8220;CEO&amp;#8221; as significant features (along with other features that you&amp;#8217;d expect to see like &amp;#8220;iphone&amp;#8221; and &amp;#8220;sauce&amp;#8221; and &amp;#8220;juice&amp;#8221;) &amp;#8211; this is due to their prevalence in this small dataset (in this set examples like &lt;a href=&quot;https://twitter.com/trendblognet/statuses/311959699010502656&quot;&gt;this&lt;/a&gt; are very frequent). Once a larger dataset is used this advantage will disappear.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve added some TODO items to the &lt;a href=&quot;https://github.com/ianozsvald/social_media_brand_disambiguator/blob/master/README.md&quot;&gt;README&lt;/a&gt;, maybe someone wants to tinker with the code? Building an interface to the open source &lt;a href=&quot;http://dbpedia-spotlight.github.io/demo/&quot;&gt;DBPediaSpotlight&lt;/a&gt; (based on WikiPedia data using e.g. this &lt;a href=&quot;https://github.com/newsgrape/pyspotlight&quot;&gt;python wrapper&lt;/a&gt;) would be a great start for validating progress, along with building some naive classifiers (a capital-letter-detecting one and a more complex heuristic-based one, to use as controls against the machine learning approach).&lt;/p&gt;
&lt;p&gt;Looking at the data 6% of the out-of-class examples are retweets and 20% of the in-class examples are retweets. I suspect that the repeated strings are distorting each class so I think they need to be thinned out so we just have one unique example of each tweet.&lt;/p&gt;
&lt;p&gt;Counting the number of capital letters in-class and out-of-class might be useful, in this set a count of &amp;lt;5 capital letters per tweet suggests an out-of-class example:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/06/nbr_capitals_scikit_testtrain_apple.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1869&quot; alt=&quot;nbr_capitals_scikit_testtrain_apple&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/06/nbr_capitals_scikit_testtrain_apple-300x226.png&quot; width=&quot;300&quot; height=&quot;226&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
This histogram of tweet lengths for in-class and out-of-class tweets might also suggest that shorter tweets are more likely to be out-of-class (though the evidence is much weaker):&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/06/histogram_tweet_lengths_scikit_testtrain_apple.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1870&quot; alt=&quot;histogram_tweet_lengths_scikit_testtrain_apple&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/06/histogram_tweet_lengths_scikit_testtrain_apple-300x226.png&quot; width=&quot;300&quot; height=&quot;226&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next I need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Update the docs so that a contributor can play with the code, this includes exporting a list of tweet-ids and class annotations so the data can be archived and recreated&lt;/li&gt;
&lt;li&gt;Spend some time looking at the most-important features (I want to properly understand the numbers so I know what is happening), I&amp;#8217;ll probably also use a Decision Tree (and maybe RandomForests) to see what they identify (since they&amp;#8217;re much easier to debug)&lt;/li&gt;
&lt;li&gt;Improve the tokenizer so that it respects some of the structure of tweets (preserving #hashtags and @users would be a start, along with URLs)&lt;/li&gt;
&lt;li&gt;Build a bigger data set that doesn&amp;#8217;t exhibit the easily-fitted unigrams that appear in the current set&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Longer term I&amp;#8217;ve got a set of Homeland tweets (to disambiguate the TV show vs references to the US Department and various sayings related to the term) which I&amp;#8217;d like to play with &amp;#8211; I figure making some progress here opens the door to analysing media commentary in tweets.&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">In Python you sort with a tuple</title>
		<link href="http://www.peterbe.com/plog/in-python-you-sort-with-a-tuple"/>
		<id>http://www.peterbe.com/plog/in-python-you-sort-with-a-tuple</id>
		<updated>2013-06-14T01:34:53+00:00</updated>
		<content type="html">&lt;p&gt;My colleague &lt;a href=&quot;https://twitter.com/axelhecht&quot;&gt;Axel Hecht&lt;/a&gt; showed me something I didn't know about sorting in Python.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;In Python you can sort with a tuple. It's best illustrated with a simple example:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'B'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'A'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'A'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'B'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'a'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'B'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'a'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'A'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'B'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'A'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default the &lt;code&gt;sort&lt;/code&gt; and the &lt;code&gt;sorted&lt;/code&gt; built-in function notices that the items are tuples so it sorts on the first element first and on the second element second.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;However, notice how you get &lt;code&gt;(0, 'B')&lt;/code&gt; appearing before &lt;code&gt;(0, 'a')&lt;/code&gt;. That's because upper case comes before lower case characters. However, suppose you wanted to apply some &quot;humanization&quot; on that and sort case insensitively. You might try:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Traceback&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;most&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;ne&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;descriptor&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'lower'&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'str'&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;received&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'tuple'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;which is an error we deserve because this won't work for the first part of each tuple.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;We could try to write a lambda function (e.g. &lt;code&gt;sorted(items, key=lambda x: x.lower() if isinstance(x, str) else x)&lt;/code&gt;) but that's not going to work because you'll only ever get to apply that to the first item.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Without further ado, here's how you do it. A lambda function that returns a tuple:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'a'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'B'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'A'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'B'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'A'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And there you have it! Thanks for sharing Axel!&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;As a bonus item for people still reading...&lt;br /&gt;
I'm sure you know that you can reverse a sort order simply by passing in &lt;code&gt;sorted(items, reverse=True, ...)&lt;/code&gt; but what if you want to have different directions depend on the key that you're sorting on.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Using the technique of a lambda function that returns a tuple, here's how we sort a slightly more advanced structure:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;peeps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Bill'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Bill'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Ted'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And now, sort with a lambda function returning a tuple:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;peeps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Bill'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Bill'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Ted'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Makes sense, right? &lt;code&gt;Bill&lt;/code&gt; comes before &lt;code&gt;Ted&lt;/code&gt; and 500 comes before 1000. But how do you sort it like that on the name &lt;em&gt;but reverse on the salary&lt;/em&gt;? Simple, negate it:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;peeps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Bill'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Bill'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'salary'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Ted'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry>
		<title type="html">How to unit test tornado ioloop callbacks</title>
		<link href="http://www.obeythetestinggoat.com/how-to-unit-test-tornado-ioloop-callbacks.html"/>
		<id>tag:www.obeythetestinggoat.com,2013-06-10:how-to-unit-test-tornado-ioloop-callbacks.html</id>
		<updated>2013-06-10T18:11:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;em&gt;WARNING: this is not battle-tested wisdom of a massively experienced tornado
tester. Today was the first time we ever tried to test something that actually
uses the ioloop, and we've probably got it all totally backwards.  Still, in
case it helps...&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Async. It's always hard to wrap your head around, so perhaps it's not
surprising that it took us a few goes at &lt;a href=&quot;http://www.pythonanywhere.com&quot;&gt;work&lt;/a&gt;
today before we got the hang of it.&lt;/p&gt;
&lt;p&gt;Here's a bit of code that adds a callback to the tornado ioloop:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sort_that_out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;IOLoop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mess&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;How might one naively write a test for it?&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TestSortingStuffOut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_stuff_get_sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sort_that_out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Well, that doesn't work: &lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;AssertionError&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Lists&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;differ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;A little head-scratching will get you to the fact that it's because the tornado
IOLoop hasn't actually been started, so our callback never gets run.  So, let's fix that:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_stuff_get_sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sort_that_out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;IOLoop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;What about now?  The test hangs, and a little Ctrl-C based profiling tells us where the
busy loop is:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;  &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;/tmp/t.py&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_stuff_get_sorted&lt;/span&gt;     
    &lt;span class=&quot;n&quot;&gt;IOLoop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;/usr/local/lib/python2.7/site-packages/tornado/ioloop.py&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;627&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;event_pairs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_impl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;poll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;poll_timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;KeyboardInterrupt&lt;/span&gt; 
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Right.  &lt;code&gt;start()&lt;/code&gt; on the IOLoop is a blocking call, and just assumes the loop should 
be run forever.  At this point we ventured over to the &lt;a href=&quot;http://www.tornadoweb.org/en/stable/testing.html&quot;&gt;official tornado
testing docs&lt;/a&gt; but they seem
to suggest a lot of overcomplicated things: using a &lt;code&gt;self.wait&lt;/code&gt;, overriding
&lt;code&gt;get_new_ioloop&lt;/code&gt; to return the singleton...&lt;/p&gt;
&lt;p&gt;Actually, all you really need to do is this:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_stuff_get_sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;sort_that_out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;IOLoop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IOLoop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;IOLoop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We just add our own callback, telling the loop to shut itself down, making sure
that it's the last callback added before we start the loop.  Voila!&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;----------------------------------------------------------------------&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;Ran&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.001&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt; 
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Well, that was our first foray into writing a test for tornado that actually used the IOLoop 
(all our other tests have just mocked everything).  No doubt the tornado tools come in useful
for other use cases.  And you'd probably want to use a &lt;code&gt;tearDown&lt;/code&gt; or &lt;code&gt;addCleanup&lt;/code&gt; that made 
sure the IOLoop got shut down even when your test doesn't behave as expected....&lt;/p&gt;
&lt;p&gt;But I though I'd post this in case anybody else has a simple requirement to
test a tornado async callback, and finds the docs a little hard-going. Hope it helps!&lt;/p&gt;</content>
		<author>
			<name>Harry</name>
			<uri>http://www.obeythetestinggoat.com/</uri>
		</author>
		<source>
			<title type="html">Obey the Testing Goat!</title>
			<link rel="self" href="http://www.obeythetestinggoat.com/feeds/all.atom.xml"/>
			<id>http://www.obeythetestinggoat.com/</id>
			<updated>2013-06-10T20:22:06+00:00</updated>
		</source>
	</entry>

	<entry>
		<title type="html">Using the built-in views and forms for new user registration in Django</title>
		<link href="http://www.obeythetestinggoat.com/using-the-built-in-views-and-forms-for-new-user-registration-in-django.html"/>
		<id>tag:www.obeythetestinggoat.com,2013-06-09:using-the-built-in-views-and-forms-for-new-user-registration-in-django.html</id>
		<updated>2013-06-09T00:10:00+00:00</updated>
		<content type="html">&lt;p&gt;Have been digging into the built-in forms and views from
django.contrib.auth.  I always knew you could get generic views for login,
logout, even password reset, but I didn't know you could actually handle
new user creation as well!&lt;/p&gt;
&lt;p&gt;There's a form in &lt;code&gt;django.contrib.auth.forms&lt;/code&gt;, and a class-based view for
creating new objects called &lt;code&gt;CreateView&lt;/code&gt;, and I believe this is all you
need for a working registration form/view:&lt;/p&gt;
&lt;div class=&quot;codehilite&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.views.generic.edit&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CreateView&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.contrib.auth.forms&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserCreationForm&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;urlpatterns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patterns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'^register/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CreateView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;as_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;template_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'register.html'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;form_class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UserCreationForm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;success_url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'/'&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'^accounts/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'django.contrib.auth.urls'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# rest of your URLs as normal&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then, in &lt;em&gt;register.html&lt;/em&gt; (which you do have to create yourself), you get a 
&lt;code&gt;{{ form }}&lt;/code&gt; you can use, including a username, password and password
confirmation, and it handles validation errors and EVERYTHING.&lt;/p&gt;
&lt;p&gt;Obviously it doesn't include registering (and validating) an email address 
for the user, but still, I'm pretty excited.  Did everyone else already
know about this?&lt;/p&gt;</content>
		<author>
			<name>Harry</name>
			<uri>http://www.obeythetestinggoat.com/</uri>
		</author>
		<source>
			<title type="html">Obey the Testing Goat!</title>
			<link rel="self" href="http://www.obeythetestinggoat.com/feeds/all.atom.xml"/>
			<id>http://www.obeythetestinggoat.com/</id>
			<updated>2013-06-10T20:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Python meets BoA</title>
		<link href="http://ramblings.timgolden.me.uk/2013/06/07/python-meets-boa/"/>
		<id>http://ramblings.timgolden.me.uk/2013/06/07/python-meets-boa/</id>
		<updated>2013-06-07T09:47:32+00:00</updated>
		<content type="html">&lt;p&gt;[tl;dr photos &lt;a href=&quot;https://plus.google.com/u/0/photos/106787463903193769812/albums/5886522053645083105&quot;&gt;here&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;Last night&amp;#8217;s London Python Dojo was held, for the first time, at the very spacious &lt;a href=&quot;http://www.worldtravelimages.net/HPIM0766.JPG&quot;&gt;Canary Wharf offices&lt;/a&gt; of the Bank of America. They&amp;#8217;re big users of Python and, as we were told in an brief introductory, were keen to give something back to the Community.&lt;/p&gt;
&lt;p&gt;They certainly did it in style. Their main reception is about the same size as Ealing Common. The meet-and-greet bar area where we had Pizza on classy platters &amp;#038; Beer served by bar staff is not much smaller than the whole of the offices of &lt;a href=&quot;http://www.fry-it.com/&quot;&gt;Fry IT&lt;/a&gt;, our long-standing default hosts. And the area below where a few of us gathered feels like a swimming pool with a long slide-like flight of stairs leading down. The function room where the main business of the evening was transacted was spacious with large tables (and *lots* of pencils!). &lt;/p&gt;
&lt;p&gt;The guys at BoA had really done their prep work: power strips were already in place and every possible laptop-to-screen adapter was available. (For those who haven&amp;#8217;t done this kind of thing: there&amp;#8217;s *always* some kind of mismatch between a screen which can only take DVI-I and a Mac user who doesn&amp;#8217;t have the Mini-HDMI-to-DisplayPort adapter. Or whatever: I use Windows which never has these problems ;) ).&lt;/p&gt;
&lt;p&gt;As well as the friendly intro from one of the BoA guys, we had an enthusiastic lightning talk on Bitcoin from &lt;a href=&quot;https://twitter.com/samphippen&quot;&gt;Sam Phippen&lt;/a&gt; (who comes in from Winchester or Bristol for the Dojos!). With over 30 people present, we had about 15 suggestions for the evening&amp;#8217;s challenge, including old favourites (How does 20 Questions work, Nicholas?) and new ideas, some around the theme of banking. After the usual two rounds we settled on &lt;a href=&quot;http://en.wikipedia.org/wiki/Steganography&quot;&gt;Steganography&lt;/a&gt; and made use of the generous table space (and pencils) which our hosts had provided.&lt;/p&gt;
&lt;p&gt;The results are &lt;a href=&quot;https://github.com/ldnpydojo/steganography&quot;&gt;on Github&lt;/a&gt; (or will be, depending on when you&amp;#8217;re reading this) as pull requests come in and are honoured. In short, two (three?) teams went for piggybacking on image bits; two teams (including the one I was with) encoded bits in the extraneous whitespace of a text document; and the last team tried to use the Python&amp;#8217;s indentation to carry information in some way which I couldn&amp;#8217;t quite understand at the time. I think that every team bar the Python-indentation one had a working result[*]; ours even had unittests!&lt;/p&gt;
&lt;p&gt;FWIW my first idea for our team was to encode the characters in Morse code (using spaces &amp;#038; tabs as dots &amp;#038; dashes). We finally settled on binary but I still think Morse would have been cooler &amp;#8212; and we could have played the message out as a midi file for extra points!&lt;/p&gt;
&lt;p&gt;Of course at the end we had a draw for O&amp;#8217;Reilly&amp;#8217;s &lt;a href=&quot;http://shop.oreilly.com/product/0636920025696.do&quot;&gt;usual generous contribution&lt;/a&gt; to proceedings along with an added bonus: an historical map of programming languages. Appropriately enough, the book was won by &lt;a href=&quot;https://plus.google.com/u/0/106787463903193769812/about&quot;&gt;Sal&lt;/a&gt; who&amp;#8217;d been the driving force behind Bank of America hosting the Dojo this month.&lt;/p&gt;
&lt;p&gt;Next month we&amp;#8217;ll probably delay by a week to come in after Europython. Not sure where we&amp;#8217;ll be yet, but follow &lt;a href=&quot;https://twitter.com/ldnpydojo&quot;&gt;@ldnpydojo&lt;/a&gt; or look out on &lt;a href=&quot;http://mail.python.org/mailman/listinfo/python-uk&quot;&gt;python-uk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And, of course, big thanks to Bank of America for being our hosts this time round.&lt;/p&gt;
&lt;p&gt;TJG&lt;/p&gt;
&lt;p&gt;[*] And they may have got things working after a live &amp;#8220;Aha!&amp;#8221; moment by &lt;a href=&quot;https://twitter.com/theheadofabroom&quot;&gt;Al&lt;/a&gt; who was demo-ing. [&lt;strong&gt;UPDATE&lt;/strong&gt;: Al was actually in another team per his comment below; so many teams, so short a memory span&amp;#8230;]&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>2013-06-07T12:22:13+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">IMAPClient 0.10</title>
		<link href="http://freshfoo.com/blog/imapclient-0.10"/>
		<id>http://freshfoo.com/blog/2013/06/06/imapclient-0.10</id>
		<updated>2013-06-05T23:15:00+00:00</updated>
		<content type="html">&lt;p&gt;IMAPClient 0.10 has just been released. This is an important release
because it's the first to support Python 3!&lt;/p&gt;
&lt;p&gt;Here's the highlights:&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Python 3.2 and 3.3 are now officially supported. This release also
means that Python versions older than 2.6 are no longer
supported. Be sure to see the &lt;a class=&quot;reference external&quot; href=&quot;https://bitbucket.org/mjs0/imapclient/src/tip/NEWS.rst&quot;&gt;NEWS.rst&lt;/a&gt; file for more information on
this change.&lt;/li&gt;
&lt;li&gt;The &lt;tt class=&quot;docutils literal&quot;&gt;HIGHESTMODSEQ&lt;/tt&gt; item in &lt;tt class=&quot;docutils literal&quot;&gt;SELECT&lt;/tt&gt; responses is now parsed correctly&lt;/li&gt;
&lt;li&gt;Fixed daylight saving handling in FixedOffset class&lt;/li&gt;
&lt;li&gt;Fixed &lt;tt class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;--port&lt;/span&gt;&lt;/tt&gt; command line bug in imapclient.interact when SSL
connections are made.&lt;/li&gt;
&lt;li&gt;Michael Foord's excellent Mock library is now longer included with
the IMAPClient package (it is listed as external test dependency)&lt;/li&gt;
&lt;li&gt;Live tests that aren't UID related are now only run once per run&lt;/li&gt;
&lt;li&gt;Live tests now perform far less logins to the server under test&lt;/li&gt;
&lt;li&gt;Unit tests can now be run for all supported Python versions using &lt;tt class=&quot;docutils literal&quot;&gt;tox&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;&lt;tt class=&quot;docutils literal&quot;&gt;python setup.py test&lt;/tt&gt; now runs the unit tests&lt;/li&gt;
&lt;li&gt;Many documentation fixes and improvements.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A massive thank you to Mathieu Agopian for his massive contribution to
getting the Python 3 support finished. His changes and ideas feature
heavily in this release.&lt;/p&gt;
&lt;p&gt;See the &lt;a class=&quot;reference external&quot; href=&quot;https://bitbucket.org/mjs0/imapclient/src/tip/NEWS.rst&quot;&gt;NEWS.rst&lt;/a&gt; file and &lt;a class=&quot;reference external&quot; href=&quot;http://imapclient.readthedocs.org/&quot;&gt;manual&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;IMAPClient can be installed from PyPI (&lt;tt class=&quot;docutils literal&quot;&gt;pip install imapclient&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;.&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>2013-06-19T00:22:11+00:00</updated>
			<rights type="html">Copyright 2009 Menno Smits</rights>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Social Media Brand Disambiguator first steps</title>
		<link href="http://ianozsvald.com/2013/06/03/social-media-brand-disambiguator-first-steps/"/>
		<id>http://ianozsvald.com/?p=1838</id>
		<updated>2013-06-03T19:24:14+00:00</updated>
		<content type="html">&lt;p&gt;As noted a few days back I&amp;#8217;m spending June working on a &lt;a href=&quot;http://ianozsvald.com/2013/05/05/june-project-disambiguating-brands-in-social-media/&quot;&gt;social-media focused brand disambiguator&lt;/a&gt; using Python, NLTK and scikit-learn. This project has grown out of frustrations using existing Named Entity Recognition tools (like OpenCalais and DBPediaSpotlight) to recognise brands in social media messages. These tools are generally trained to work on long-form clean text and tweets are anything but long or cleanly written!&lt;/p&gt;
&lt;p&gt;The problem is this: in a short tweet (e.g. &amp;#8220;Loving my apple, like how it werks with the iphon&amp;#8221;) we have little context to differentiate the sense of the word &amp;#8220;apple&amp;#8221;. As a human we see the typos and deliberate spelling errors and know that this use of &amp;#8220;apple&amp;#8221; is for the brand, not for the fruit. Existing APIs don&amp;#8217;t make this distinction, typically they want a lot more text with fewer text errors. I&amp;#8217;m hypothesising that with a supervised learning system (using scikit-learn and NLTK) and hand tagged data I can outperform the existing APIs.&lt;/p&gt;
&lt;p&gt;I started on Saturday (freshly back from honeymoon), a very small &lt;a href=&quot;https://github.com/ianozsvald/social_media_brand_disambiguator&quot;&gt;github repo&lt;/a&gt; is online. Currently I can ingest tweets from a JSON file (captured &lt;a href=&quot;http://mike.teczno.com/notes/streaming-data-from-twitter.html&quot;&gt;using curl&lt;/a&gt;), marking the ones with a brand and those with the same word but not-a-brand (in-class and out-of-class) in a SQLite db. I&amp;#8217;ll benchmark my results against my hand-tagged Gold Standard to see how I do.&lt;/p&gt;
&lt;p&gt;Currently I&amp;#8217;m using my &lt;a href=&quot;https://github.com/ianozsvald/python_template_with_config&quot;&gt;Python template&lt;/a&gt; to allow environment-variable controlled configurations, simple logging, argparse and unittests. I&amp;#8217;ll also be using the &lt;a href=&quot;https://pypi.python.org/pypi/twitter-text-python/&quot;&gt;twitter text python&lt;/a&gt; module that I&amp;#8217;m now supporting to parse some structure out of the tweets.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll be presenting my progress next week at &lt;a href=&quot;http://brightonpy.org/meetings/2013-06-11/&quot;&gt;Brighton Python&lt;/a&gt;, my goal is to have a useful MIT-licensed tool that is pre-trained with some obvious brands (e.g. Apple, Orange, Valve, Seat) and software names (e.g. Python, vine, Elite) by the end of this month, with instructions so anyone can train their own models. Assuming all goes well I can then plumb it into my planned &lt;a href=&quot;http://annotate.io/&quot;&gt;annotate.io&lt;/a&gt; online service later.&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">How Does Python Handle Signals (on Windows)?</title>
		<link href="http://ramblings.timgolden.me.uk/2013/05/31/how-does-python-handle-signals-on-windows/"/>
		<id>http://ramblings.timgolden.me.uk/2013/05/31/how-does-python-handle-signals-on-windows/</id>
		<updated>2013-05-31T13:55:58+00:00</updated>
		<content type="html">&lt;p&gt;(Background: I&amp;#8217;ve &lt;a href=&quot;http://bugs.python.org/issue18040&quot;&gt;recently&lt;/a&gt; and &lt;a href=&quot;http://bugs.python.org/issue1677&quot;&gt;less recently&lt;/a&gt; worked through a couple of issues with Python&amp;#8217;s Ctrl-C handling under Windows. These required me to dig into the corners of Python&amp;#8217;s signal-handling mechanism as interpreted on Windows. This post is something of an &lt;em&gt;aide memoire&lt;/em&gt; for myself for the next time I have to dig.).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009696699/basedefs/signal.h.html&quot;&gt;Signals&lt;/a&gt; are a Posix mechanism whereby User-space code can be called by Kernel-space code as a result of some event (which might itself have been &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/009695399/functions/kill.html&quot;&gt;initiated&lt;/a&gt; by other User-space code). At least, that&amp;#8217;s the understanding of this ignorant Windows-based developer.&lt;/p&gt;
&lt;p&gt;For practical purposes, it means you can set up your code to be called asynchronously by installing a signal handler for a particular signal. Lots more information, of course, &lt;a href=&quot;http://en.wikipedia.org/wiki/Unix_signal&quot;&gt;over at Wikipedia&lt;/a&gt;. Windows (which is not short of &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx&quot;&gt;native IPC mechanisms&lt;/a&gt;, asynchronous and otherwise) offers an emulation of the Posix signals via the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/xdkz3x12(v=vs.90).aspx&quot;&gt;C runtime library&lt;/a&gt;, and this is what Python mostly uses.&lt;/p&gt;
&lt;p&gt;However, as you&amp;#8217;ll see from the &lt;a href=&quot;http://docs.python.org/3/library/signal.html#execution-of-python-signal-handlers&quot;&gt;Python docs&lt;/a&gt; Python doesn&amp;#8217;t allow arbitrary code to be called directly by the OS. Instead, it keeps track of what handlers you&amp;#8217;ve set up &lt;a href=&quot;http://docs.python.org/3/library/signal.html#signal.signal&quot;&gt;via the signal module&lt;/a&gt; and then calls them when it&amp;#8217;s got a moment. The &amp;#8220;when it&amp;#8217;s got a moment&amp;#8221; means, essentially, that &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c#l1313&quot;&gt;Modules/signalmodule.c:PyErr_CheckSignals&lt;/a&gt; is called all over the place, but especially is called via the eval-loop&amp;#8217;s &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Python/ceval.c#l537&quot;&gt;pending calls mechanism&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So what does this mean in term&amp;#8217;s of Python&amp;#8217;s codebase?&lt;/p&gt;
&lt;p&gt;* The heart of the signal handling mechanism is in &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c&quot;&gt;Modules/signalmodule.c&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;* The signal module keeps track in a &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c#l88&quot;&gt;Handlers structure&lt;/a&gt; of the Python handlers registered via the &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c#l282&quot;&gt;signal.signal&lt;/a&gt; function. When the mechanism &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c#l1312&quot;&gt;fires up&lt;/a&gt;, it pulls the appropriate function out of that structure and calls it.&lt;/p&gt;
&lt;p&gt;* Python registers &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c#l195&quot;&gt;Modules/signalmodule.c:signal_handler&lt;/a&gt;  with the OS as a global signal handler which, when fired by the OS, calls &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c#l177&quot;&gt;Modules/signalmodule.c:trip_signal&lt;/a&gt; which indicates that the corresponding Python signal handler should be called at the next available point.&lt;/p&gt;
&lt;p&gt;* The signal can be delivered by the OS (to the internal signal_handler function) at any point but the registered Python handler will only be run when &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c#l1312&quot;&gt;PyErr_CheckSignals&lt;/a&gt; is run. This means that, at the very least, the Python signal handlers will not be run while a system call is blocking. It may be that whatever caused the signal will have caused the kernel to abort the blocking call, at which point Python takes over again and can check the signals. (This is what happens &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/_io/bufferedio.c#l1946&quot;&gt;at&lt;/a&gt; &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/_io/bufferedio.c#l2085&quot;&gt;points&lt;/a&gt; in the IO read/write loops). But if some uninterruptible device read hangs then Python will not regain control and no signal handler will execute.&lt;/p&gt;
&lt;p&gt;* The  &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Python/ceval.c#l789&quot;&gt;main eval loop&lt;/a&gt; will check for raised signals via its pending calls mechanism, a &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Python/ceval.c#l487&quot;&gt;C-level stack&lt;/a&gt; from which a function call can be popped &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Python/ceval.c#l1226&quot;&gt;every so often&lt;/a&gt; around the loop. The  &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c#l177&quot;&gt;trip_signal&lt;/a&gt; function (called by the global signal_handler) adds to the queue of pending functions a wrapped call to PyErr_CheckSignals. This should result in the signals being checked a few moments later during the eval loop.&lt;/p&gt;
&lt;p&gt;OK; so much for the whistlestop tour. How about Windows? &lt;/p&gt;
&lt;p&gt;Well, for the most part, Windows operates just the same way courtesy of the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/xdkz3x12(v=vs.71).aspx&quot;&gt;C runtime library&lt;/a&gt;. But the signals which are raised and trapped are limited. And they probably resolve to the more Windows-y Ctrl-C and Ctrl-Break. I&amp;#8217;m not going to touch on Ctrl-Break here, but the default Ctrl-C handling in Python is a bit of a mixed bag. We currently have a mixture of three things interacting with each other: the signal handling described above (where the &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c#l157&quot;&gt;default SIGINT handler&lt;/a&gt; raises PyErr_KeyboardInterrupt); the &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Parser/myreadline.c#l34&quot;&gt; internal wrapper&lt;/a&gt; around the C runtime&amp;#8217;s implementation of &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/c37dh6kf.aspx&quot;&gt;fgets&lt;/a&gt; which returns specific error codes if the line-read was interrupted; and some recently-added &lt;a href=&quot;http://hg.python.org/cpython/file/0ebc9005cb00/Modules/signalmodule.c#l234&quot;&gt;Windows event-handling&lt;/a&gt; which makes it easier to interrupt sleeps and other kernel objects from within Python).&lt;/p&gt;
&lt;p&gt;That really was quick and I&amp;#8217;ve brushed over a whole load of details; as I say, it&amp;#8217;s more to remind me the next time I look at a related issue. But, hopefully it&amp;#8217;ll give other interested people a headstart if they want to see how Python does things.(Background: I&amp;#8217;ve &lt;a href=&quot;http://bugs.python.org/issue18040&quot;&gt;recently&lt;/a&gt; and &lt;a href=&quot;http://bugs.python.org/issue1677&quot;&gt;less recently&lt;/a&gt; worked through a couple of issues with Python&amp;#8217;s Ctrl-C handling under Windows. These required me to dig into the corners of Python&amp;#8217;s signal-handling mechanism as interpreted on Windows. This post is something of an &lt;em&gt;aide memoire&lt;/em&gt; for myself for the next time I have to dig.).&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>2013-06-07T12:22:13+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">premailer now excludes pseudo selectors by default</title>
		<link href="http://www.peterbe.com/plog/premailer-now-excludes-pseudo-selectors-by-default"/>
		<id>http://www.peterbe.com/plog/premailer-now-excludes-pseudo-selectors-by-default</id>
		<updated>2013-05-27T00:47:56+00:00</updated>
		<content type="html">&lt;p&gt;Thanks to Igor who emailed me and made me aware, you can't put pseudo classes in style attributes in HTML. I.e. this does not work:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;color:pink :hover{color:red}&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Sample Link&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;See for yourself: &lt;a href=&quot;http://www.peterbe.com/rss.xml?oc=Python&amp;amp;oc=Zope&quot;&gt;Sample Link&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Note how it does not become red when you hover over the link above.&lt;br /&gt;
This is what &lt;a href=&quot;https://pypi.python.org/pypi/premailer&quot;&gt;premailer&lt;/a&gt; &lt;strong&gt;used&lt;/strong&gt; to do. Until yesterday.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;BEFORE:&lt;br /&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;/div&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;premailer&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'''&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... &amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... &amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... a { color: pink }&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... a:hover { color: red }&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... &amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... &amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Sample Link&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... &amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... '''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{color:pink} :hover{color:red}&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sample&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;&lt;br /&gt;

&lt;p&gt;AFTER:&lt;br /&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;/div&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;premailer&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'''&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... &amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... &amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... a { color: pink }&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... a:hover { color: red }&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... &amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... &amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Sample Link&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... &amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;... '''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hover&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;red&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;color:pink&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Sample&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;&lt;br /&gt;

&lt;p&gt;That's because the new default is &lt;a href=&quot;https://github.com/peterbe/premailer/blob/129ae59fadf55a268b03b74ac300c2cdcb0ceb1e/premailer/premailer.py#L100&quot;&gt;&lt;strong&gt;exclude&lt;/strong&gt; pseudo classes by default&lt;/a&gt;.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Thanks Igor for making me aware! &lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry>
		<title type="html">What to say about deployment?</title>
		<link href="http://www.obeythetestinggoat.com/what-to-say-about-deployment.html"/>
		<id>tag:www.obeythetestinggoat.com,2013-05-15:what-to-say-about-deployment.html</id>
		<updated>2013-05-15T06:37:00+00:00</updated>
		<content type="html">&lt;p&gt;My book has got to the stage of a minimum viable site.  I want the next chapter
to be about actually deploying the site, even though it's ridiculously early --
to encourage the habit of &quot;deploy early, deploy often&quot;.&lt;/p&gt;
&lt;p&gt;But how to introduce deployment in a beginner-friendly way?  It's a very simple
site, so we don't need to cover all the complexities of deployment, but what's 
the minimum? Here's what I've got so far..&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Deploying a site to a live web server can be a tricky topic.  Oft heard in 
office corridors, IRC and tech forums is the forlorn cry -- &lt;em&gt;&quot;but it works on my machine&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Some of the danger areas of deployment include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;static files&lt;/strong&gt; (CSS, javascript, images etc): web servers usually need special
  configuration for serving these&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;database&lt;/strong&gt;: there can be permissions and path issues, and we need to be
  careful about preserving data between deploys&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;dependencies&lt;/strong&gt;: we need to make sure that the packages are software relies on
  are installed on the server, and have the correct versions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But there are solutions to all of these.  In order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using a &lt;strong&gt;staging site&lt;/strong&gt;, on the same infrastructure as the production site, can
  help us test out our deployments and get things right before we go to the
  &quot;real&quot; site&lt;/li&gt;
&lt;li&gt;We can also &lt;strong&gt;run our functional tests against the staging site&lt;/strong&gt;. They could
  include some smoke tests that, eg, CSS is loaded correctly.&lt;/li&gt;
&lt;li&gt;We can write a special functional &lt;strong&gt;test that checks the deploy process&lt;/strong&gt;, for
  example making sure database data is preserved (later, we can talk about South &lt;/li&gt;
&lt;li&gt;data migrations...)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Virtualenvs&lt;/strong&gt; are a useful tool for managing packages and dependencies on a
  server that's not entirely under your own control&lt;/li&gt;
&lt;li&gt;And finally, automation, automation, automation.  By using an &lt;strong&gt;automated
  script&lt;/strong&gt; to deploy new versions, and by using the same script to deploy to
  staging and production, we can reassure ourselves that staging is as much
  like live as possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;So far, so good (at least, I think.  feel free to pick holes!)&lt;/p&gt;
&lt;p&gt;But the question is: now what?  What platform to choose to deploy to?  What
should be in my automated deploy script?&lt;/p&gt;
&lt;p&gt;Platform:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Obviousy I think &lt;a href=&quot;http://www.pythonanywhere.com&quot;&gt;PythonAnywhere&lt;/a&gt; is the
  natural choice and the easiest and the best and stuff. But I would say that.
  So I can't say that&lt;/li&gt;
&lt;li&gt;Heroku / Dotcloud et al are an option, but they involve quite a lot of
  specific config.  The precise tools used to deploy are all different, and
  might change by the time the book comes out&lt;/li&gt;
&lt;li&gt;How about &quot;a generic VPS&quot;?  Assuming the user has SSH access, I could use
  fabric to deploy...  That would let people use AWS, Digital Ocean, Linode or
  whoever. But then I get into the mess of apache / nginx / uwsgi config... and
  the trend these days seems to be to try and let users avoid that sort of
  hassle... Also, I really want to make sure people &lt;em&gt;actually&lt;/em&gt; do this, and
  deploy their site, and I'd rather they were able to do it somewhere free...&lt;/li&gt;
&lt;li&gt;Can I make some instructions generic enough that they apply to all platforms?
  I'm not sure...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, your suggestions much appreciated! How do you do your deploys?  Fabric?
FTP?  Git hooks?  Something else?  What do you think would work as a simple
solution for beginners?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;[update 2013-06-09] I've had a first bash at it, and the solution involves the
reader starting up their own server, provisioning nginx + gunicorn + upstart,
and deploying using fabric, git and virtualenvs.  comments welcomed!  You
can find the &lt;a href=&quot;http://chimera.labs.oreilly.com/books/1234000000754/ch08.html&quot;&gt;current draft here&lt;/a&gt;]&lt;/em&gt;&lt;/p&gt;</content>
		<author>
			<name>Harry</name>
			<uri>http://www.obeythetestinggoat.com/</uri>
		</author>
		<source>
			<title type="html">Obey the Testing Goat!</title>
			<link rel="self" href="http://www.obeythetestinggoat.com/feeds/all.atom.xml"/>
			<id>http://www.obeythetestinggoat.com/</id>
			<updated>2013-06-10T20:22:06+00:00</updated>
		</source>
	</entry>

	<entry>
		<title type="html">A lovely review! &quot;like sitting down to pair-program with the author&quot;</title>
		<link href="http://www.obeythetestinggoat.com/review-like-sitting-down-to-pair-program-with-the-author.html"/>
		<id>tag:www.obeythetestinggoat.com,2013-05-13:review-like-sitting-down-to-pair-program-with-the-author.html</id>
		<updated>2013-05-13T07:35:00+00:00</updated>
		<content type="html">&lt;p&gt;Jason, whom I met at PyCon this year, wrote a lovely review of my book &lt;a href=&quot;http://shop.oreilly.com/product/0636920029533.do&quot;&gt;on the
O'Reily site&lt;/a&gt;. I'm very grateful because I think
he actually helped me to see some things I didn't realise myself about the book.  I'll reproduce
it here, for which I hope my publisher will forgive me:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Programming books often fall into a few, easy to define categories. There are beginner's books, advanced books, reference books, books on specific libraries/frameworks, cookbooks, etc. &quot;Test-Driven Web Development with Python&quot; is none of the above; it's best described as a conversation with a developer.&lt;/p&gt;
&lt;p&gt;Reading the book is like sitting down to pair-program with the author, starting from scratch and building a basic web app. Along the way you'll obviously use Django, unit tests, and Selenium but you'll also use Git and other tools.&lt;/p&gt;
&lt;p&gt;I find far too many programming books compartmentalize the material, each section is separate and abstract. Rather, this book's strength is in the broad use and application of these tools. By the end of this book you won't be a master with these tools but you will have used them enough to build a good foundation for starting your own projects and into the habit of test, code, refactor, commit.&lt;/p&gt;
&lt;p&gt;For example, if you are new to open source development you'll hear about writing unit tests or using Git and want to use them yourself. But what's the next step, read a the unit test documentation or ProGit cover to cover? I don't need to be an expert, I just need someone to show me enough to get up and running. At that point I'll have completed a project and have the confidence and skills to tackle problems on my own.&lt;/p&gt;
&lt;p&gt;Like the answer to a job interview question, the book's biggest strength is also it's biggest weakness. Writing a book that covers so many tools the author must, by necessity, make assumptions about what the reader knows, and that's very, very hard.&lt;/p&gt;
&lt;p&gt;I came to the book without ever touching Django before. It wasn't always obvious how things worked nor why were doing them, particularly later in the book where there's more magic going on. I had to sit back and blindly follow along. At one point I got hung up because I mis-typed my URL, omitting a a forward-slash (&quot;/&quot;) at the beginning, and my tests kept failing but I couldn't figure out why.&lt;/p&gt;
&lt;p&gt;Do URLs start with a forward slash? As a beginner, I don't know, and it's not obvious because Django does a lot of stuff for you. The code in the book was right, but I mis-typed it. I think had I come to the table with more Django experience I wouldn't have made that mistake.&lt;/p&gt;
&lt;p&gt;So while that's a particularly nasty typo, which really frustrated me, I can't say that a beginner should go off and read a Django book before attempting this one. In fact, quite the opposite. Because I got a survey of how everything works, covering so many tools so quickly, I'm in a much better position to troubleshoot and solve the problem myself. For example, &quot;we've been writing a lot of unit tests, how can I write a unit test to help debug this unexpected failure?&quot;&lt;/p&gt;
&lt;p&gt;Lastly, as I mentioned, the book is written like a conversation with a fellow developer at your side. There are numerous jokes and cultural references (e.g. refactoring cat, testing goat, etc.). This really lightens the tone (who doesn't joke with a co-worker?) as well as introduce the reader into the culture of open source development so that when you are walking around PyCon and someone has a stuffed goat or makes a &quot;baaah&quot; goat noise you'll fit right in! &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Writing the book in the style of a pair-programming conversation came naturally, since it's what
I do every day.  It's also the way that I learnt pretty much everything I'm writing about, so
it's natural that I should use it as a teaching style. Where Jason really has a point is that my
book isn't enough -- it's not a reference book, so you won't be able to use it as a reference
book.  It won't teach you everything about Django, or even everything about unit testing -- on
several occasions in the book I say &quot;you should go and read the Django documentation&quot;, or &quot;you
should take a look at the other assertion methods from the unittest module&quot;, and I think some
readers have found that frustrating.  &quot;Why should I go elsewhere to learn?&quot;...&lt;/p&gt;
&lt;p&gt;So I think this is something I need to set expectations about better, perhaps in the intro.
&quot;This isn't a reference book&quot;.&lt;/p&gt;
&lt;p&gt;Any thoughts? From current readers, do you agree with Jason?  Do you think the current style and
content of the book are working?&lt;/p&gt;</content>
		<author>
			<name>Harry</name>
			<uri>http://www.obeythetestinggoat.com/</uri>
		</author>
		<source>
			<title type="html">Obey the Testing Goat!</title>
			<link rel="self" href="http://www.obeythetestinggoat.com/feeds/all.atom.xml"/>
			<id>http://www.obeythetestinggoat.com/</id>
			<updated>2013-06-10T20:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Just in case you thought it was easy…</title>
		<link href="http://ramblings.timgolden.me.uk/2013/05/10/just-in-case-you-thought-it-was-easy/"/>
		<id>http://ramblings.timgolden.me.uk/2013/05/10/just-in-case-you-thought-it-was-easy/</id>
		<updated>2013-05-10T07:25:05+00:00</updated>
		<content type="html">&lt;p&gt;From time to time, the idea of a standard Python &amp;#8220;Enum&amp;#8221; object is raised on the Python lists. You know the kind of thing: a lightweight means of mapping numbers to labels so you can do set_colour(Colours.red) without having a long module of manifest constants or magic numbers lying around all over your codebase.&lt;/p&gt;
&lt;p&gt;It all sounds very straightforward, and Barry Warsaw had &lt;a href=&quot;http://pythonhosted.org/flufl.enum/&quot;&gt;an existing module&lt;/a&gt; which seemed like a fairly good starting point, so&lt;a href=&quot;http://www.python.org/dev/peps/pep-0435/&quot;&gt; PEP 435&lt;/a&gt; was started and it all looked like it was just a formality.&lt;/p&gt;
&lt;p&gt;Now, literally *hundreds* of mailing list posts and endless, endless threads later, GvR has just &lt;a href=&quot;http://mail.python.org/pipermail/python-dev/2013-May/126112.html&quot;&gt;pronounced his approval&lt;/a&gt; of the PEP and it&amp;#8217;s good to go.&lt;/p&gt;
&lt;p&gt;If you &amp;#8212; like me &amp;#8212; thought &amp;#8220;this one won&amp;#8217;t be controversial&amp;#8221;, then just point your search engine of choice at mail.python.org/pipermail/python-dev and look for &amp;#8220;enum&amp;#8221; or &amp;#8220;435&amp;#8243;, or just look at the &lt;a href=&quot;http://mail.python.org/pipermail/python-dev/2013-May/&quot;&gt;archive for May&lt;/a&gt; alone (which only represents the final few days of details being thrashed out) to realise just how much discussion and work is involved in what appears to be quite a simple thing.&lt;/p&gt;
&lt;p&gt;Of course, part of the problem is precisely the fact that the idea is so simple. I&amp;#8217;m sure most people have rolled their own version of something like this. I know I have. You can get up and running with a simple &amp;#8220;bunch&amp;#8221; class, possibly throw in a few convenience methods to map values to names and then just get on with life. But when something&amp;#8217;s got to go into the stdlib then it all becomes a lot more difficult, because everyone has slightly (or very) different needs; and everyone has slightly (or very) different ideas about what constitutes the most convenient interface. &lt;/p&gt;
&lt;p&gt;And there&amp;#8217;s always the danger of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Parkinson's_law_of_triviality&quot;&gt;&amp;#8220;bikeshed&amp;#8221; effect&lt;/a&gt;. If a PEP is proposing something perhaps quite fundamental but outside most people&amp;#8217;s experience, then only people with sufficient  interest and knowledge are likely to contribute. (Or argue). But an enum: everyone&amp;#8217;s done that, and everyone&amp;#8217;s got an interest, and an idea about how it should be done.&lt;/p&gt;
&lt;p&gt;But, bikesheds aside, I&amp;#8217;m glad that the Python community is prepared to refine its ideas to get the best possible solution into the standard library. As a developer, one naturally feels that one&amp;#8217;s own ideas and needs represent everyone else&amp;#8217;s. It&amp;#8217;s only when you expose your ideas to the sometimes harsh winds of the community critique that you discover just how many different angles there are to something you thought was simple. &lt;/p&gt;
&lt;p&gt;Thankfully, we have a BDFL (or, sometimes, a PEP Czar) to make the final decision. And, ultimately, that means that some people won&amp;#8217;t see their needs being served in the way they want. But I think that that&amp;#8217;s far preferable to a design-by-committee solution which tries to please everybody and ends up being cluttered.&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>2013-06-07T12:22:13+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">A Statement from Adria Richards</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/2SvdL7Tgy2k/a-statement-from-adria-richards.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-779872142500764125</id>
		<updated>2013-05-07T14:18:10+00:00</updated>
		<content type="html">Having remained silent since PyCon, Adria Richards has now &lt;a href=&quot;http://allthingsd.com/20130327/fired-sendgrid-developer-evangelist-adria-richards-speaks-out/&quot; target=&quot;_blank&quot;&gt;published a statement&lt;/a&gt;&amp;nbsp;reflecting on those events, though sensibly without going into specifics. I think it's important that her retrospective view gets some air, so I am reproducing it here with my own comments.&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
Those who know me well in the the developer and tech community recognize that I have always tried to conduct myself in a way that builds bridges for everyone. My central aim is to do everything I can to help create new, inclusive inroads for all, no matter who they are, where they come from or what they believe. Development is about innovation, creativity, and in a grand sense, the betterment of human society through technology. So, it stands to reason that everyone should have a seat at the table, and everyone involved in this vital community should feel welcome, safe and respected. In essence, the worldwide community of developers can and should function as a reflection of what our wider society strives to be.&lt;/blockquote&gt;
I don't know Adria, so I take her opening statement at face value. Those who disagree may do so elsewhere. Garann Means recently &lt;a href=&quot;https://speakerdeck.com/garann/bacon-is-bad-for-you&quot; target=&quot;_blank&quot;&gt;made a fairly good case&lt;/a&gt; that the denizens of the technology world don't act in a way that inspires respect from other communities. I think it's fair to say (and some of the comments in forums like Hacker News amply demonstrate) that there is plenty of room for improvement in what's considered acceptable conduct in the technology world.&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
I cannot comment at this time on the specifics of what occurred at PyCon on March 17, and the subsequent events of the following days, but I can offer some general thoughts. I don’t think anyone who was part of what happened at PyCon that day could possibly have imagined how this issue would have exploded into the public consciousness the way it has. I certainly did not, and now that the severest of consequences have manifested, all I wish to do is find the good in what has been one of the most challenging weeks of my life.&lt;/blockquote&gt;
This positive attitude is to be admired. I have been through similarly shitty situations in my own life (as most of us have at one time or another) and while it's good to move on I like to extract lessons that will help me try to avoid making the same mistakes. If I can find those I can feel more positive about the experience.&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
And I do believe there is good to be found in this situation. Debate and recrimination can and must give way to dialog that explores the root causes of these issues in the tech industry. As developers and members of the startup community, we can welcome newcomers, women and people of color who, as of now, are under-represented in our ranks. And, all of us can learn a great deal from those who are well-established in the field. We can solidify the values of our workplaces (yes, conference spaces are workplaces!), and set new, positive and inclusive examples for other professional disciplines.&lt;/blockquote&gt;
This is a good idea. PyCon was started to try and provide an inclusive space where everyone with interests in Python can come together for the betterment of all. I would be suspicious of those who don't support the above as an ideal. We surely have to accept that there's still along way to go to get there. So dialog is a good idea.&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
What happened at PyCon has cast a spotlight on a range of deep issues and problems in the developer world. As ugly as this situation has become, all of these issues have reasonable, and, I think, easily reached solutions that will help us cast conflict aside and construct a more cohesive and welcoming professional environment based on respect, trust and open communication. I do not, at this time, wish to concentrate on the fallout of the last several days. Instead, I want to be an integral part of a diverse, core group of individuals that comes together in a spirit of healing and openness to devise answers to the many questions that have arisen in the last week. Together, we can work to make the tech world a better place to work for everyone, and in doing so, we make the wider world a better place for all.&lt;/blockquote&gt;
It's interesting that this episode happened at PyCon. When we started to talk seriously about Codes of Conduct in the Python world there was a lot of kick-back, and people said things like &quot;but this is the Python community&quot; (implying that &lt;i&gt;we&lt;/i&gt;&amp;nbsp;are such nice people that we won't have the same issues) and &quot;but that's just normal behavior&quot; (not even implying, but specifically stating, that anyone who needed a Code of Conduct to condition their behavior shouldn't be going to conferences anyway).&lt;br /&gt;
&lt;br /&gt;
We pressed ahead none the less, refining the code to improve its expression of our ideals of openness and inclusivity. When issues had to be addressed (and you can read the reports in the PyCon blog if you need to refresh your memory) the code of conduct was applied, and to my mind it worked. The fact that two people lost their jobs as a result of the fall-out was nothing to do with the code of conduct, and yet there were many who felt that the blame should be laid at PyCon's door. I shudder to think what the result would have been at an event with no explicit code.&lt;br /&gt;
&lt;br /&gt;
I hope that Adria can come back to PyCon without being subjected to any hostility. She expresses a great ideal, one that we should all be striving for. Now we just have to work out how to achieve it. But that's an implementation detail, right? I wish!&lt;br /&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=2SvdL7Tgy2k:HFQXFQeefZc: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=2SvdL7Tgy2k:HFQXFQeefZc:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=2SvdL7Tgy2k:HFQXFQeefZc:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/2SvdL7Tgy2k&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">&quot;Any sufficiently advanced technology is indistinguishable from magic&quot; -- Arthur C Clarke
&lt;br /&gt;
Musings from the technological frontier</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2013-05-16T00:22:18+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Raspberry Pi: driving a VU meter using a digital-to-analog converter</title>
		<link href="http://freshfoo.com/blog/raspberry_pi_vu_meter"/>
		<id>http://freshfoo.com/blog/2013/05/06/raspberry_pi_vu_meter</id>
		<updated>2013-05-06T22:40:00+00:00</updated>
		<content type="html">&lt;p&gt;As I've mentioned in previous &lt;a class=&quot;reference external&quot; href=&quot;http://freshfoo.com/blog/pulseaudio_monitoring&quot;&gt;blog&lt;/a&gt; &lt;a class=&quot;reference external&quot; href=&quot;http://freshfoo.com/blog/overengineered_blinking_leds&quot;&gt;articles&lt;/a&gt;, my wife and I have
been working on driving an analog VU meter based on the sound going
out the Raspberry Pi's audio outputs. This now works!&lt;/p&gt;
&lt;p&gt;Here's a video demonstrating the result:&lt;/p&gt;


&lt;p&gt;The music &lt;a class=&quot;footnote-reference&quot; href=&quot;http://freshfoo.com/blog/index.atom#id2&quot; id=&quot;id1&quot;&gt;[1]&lt;/a&gt; is playing from a Raspberry Pi, with software running
on the Pi digitally sampling the peak output audio level and writing
that out to an 8-bit &lt;a class=&quot;reference external&quot; href=&quot;http://en.wikipedia.org/wiki/Digital-to-analog_converter&quot;&gt;digital-to-analog converter&lt;/a&gt; (DAC). The DAC
output is then used to drive the analog meter. If you're interesting
in knowing how all this hangs together, keep reading.&lt;/p&gt;
&lt;a href=&quot;http://freshfoo.com/blog/raspberry_pi_vu_meter&quot;&gt;Read more...&lt;/a&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>2013-06-19T00:22:11+00:00</updated>
			<rights type="html">Copyright 2009 Menno Smits</rights>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">June project: Disambiguating “brands” in Social Media</title>
		<link href="http://ianozsvald.com/2013/05/05/june-project-disambiguating-brands-in-social-media/"/>
		<id>http://ianozsvald.com/?p=1822</id>
		<updated>2013-05-05T13:32:00+00:00</updated>
		<content type="html">&lt;p&gt;Having returned from Chile last year, settled in to consulting in London, got married and now on honeymoon I&amp;#8217;m planning on a change for June.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m taking the month off from clients to work on my own project, an open sourced brand disambiguator for social media. As an example this will detect that the following tweet mentions Apple-the-brand:&lt;br /&gt;
&amp;#8220;I love my apple, though leopard can be a pain&amp;#8221;&lt;br /&gt;
and that this tweet does not:&lt;br /&gt;
&amp;#8220;Really enjoying this apple, very tasty&amp;#8221;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve used AlchemyAPI, OpenCalais, DBPedia Spotlight and others for client projects and it turns out that these APIs expect long-form text (e.g. Reuters articles) written with good English.&lt;/p&gt;
&lt;p&gt;Tweets are short-form, messy, use colloquialisms, can be compressed (e.g. using contractions) and rely on local context (both local in time and social group). Linguistically a lot is expressed in 140 characters and it doesn&amp;#8217;t look like&amp;#8221;good English&amp;#8221;.&lt;/p&gt;
&lt;p&gt;A second problem with existing APIs is that they cannot be trained and often don&amp;#8217;t know about European brands, products, people and places. I plan to build a classifier that learns whatever you need to classify.&lt;/p&gt;
&lt;p&gt;Examples for disambiguation will include &lt;em&gt;Apple&lt;/em&gt; vs apple (brand vs e.g. fruit/drink/pie), &lt;em&gt;Seat&lt;/em&gt; vs seat (brand vs furniture), cold vs cold (illness vs temperature), ba (when used as an abbreviation for British Airways).&lt;/p&gt;
&lt;p&gt;The goal of the June project will be to out-perform existing Named Entity Recognition APIs for well-specified brands on Tweets, developed openly with a liberal licence. The aim will be to solve new client problems that can&amp;#8217;t be solved with existing APIs.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll be using Python, NLTK, scikit-learn and Tweet data. I&amp;#8217;m speaking on progress at BrightonPy and DataScienceLondon in June.&lt;/p&gt;
&lt;p&gt;Probably for now I should focus on having no computer on my honeymoon&amp;#8230;&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry>
		<title type="html">Day against DRM and this book's copyright</title>
		<link href="http://www.obeythetestinggoat.com/day-against-drm-copyright.html"/>
		<id>tag:www.obeythetestinggoat.com,2013-05-03:day-against-drm-copyright.html</id>
		<updated>2013-05-03T17:35:00+00:00</updated>
		<content type="html">&lt;p&gt;Hooray for O'Reilly, who are giving away ebooks half-price in celebration of the FSF's &quot;Day against DRM&quot;!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.kqzyfj.com/click-7089628-11364391&quot; target=&quot;_top&quot;&gt;
&lt;img src=&quot;http://www.ftjcfx.com/image-7089628-11364391&quot; width=&quot;200&quot; height=&quot;200&quot; alt=&quot;Save 50% on all Ebooks and Videos to celebrate Day Against DRM&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When I was first speaking to publishers about this book, I was a bit nervous.
I'm very intersed in digital rights and copyright reform, and in fact I'm
a reasonably active member of Pirate Party UK (or I was until this little 
project sucked up all my spare time!)... Could I find a publishing deal that
would be compatible with my views?  One of my colleagues in the German Pirate
Party came in for a lot of criticism when she wrote a book and discovered her
publisher sending out DMCA notices to filesharing sites...&lt;/p&gt;
&lt;p&gt;I support a manifesto that asks for a 10-year limit on copyright, and for all
non-commercial filesharing to be legal.  Could I find a publishing deal that
was at all consistent with that?  The first publisher I spoke to was having
none of it...&lt;/p&gt;
&lt;p&gt;That's why I was so glad when O'Reilly said they had absolutely no problem
with me distributing the book under a CC license...  After a bit of haggling,
they even agree to a clause in the contract that would say that the book would
revert to a CC-0 Public Domain license after 10 years.  Even if you think
the policy of 10 years is too short for many domains, it's certainly enough
for commercial exploitation of a technical book.&lt;/p&gt;
&lt;p&gt;So, hooray for my beloved publisher, hooray for Creative Commons, and hooray 
for the FSF!&lt;/p&gt;</content>
		<author>
			<name>Harry</name>
			<uri>http://www.obeythetestinggoat.com/</uri>
		</author>
		<source>
			<title type="html">Obey the Testing Goat!</title>
			<link rel="self" href="http://www.obeythetestinggoat.com/feeds/all.atom.xml"/>
			<id>http://www.obeythetestinggoat.com/</id>
			<updated>2013-06-10T20:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">So Long, and Thanks for All the Fish</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/-xGkCjGmzSo/so-long-and-thanks-for-all-fish.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-7113295657257455662</id>
		<updated>2013-04-29T01:34:35+00:00</updated>
		<content type="html">A notable transition point in my life, by any measure. Interesting things are happening in all directions, many of them (I am delighted to day) heavily involving Python. So this is definitely &lt;i&gt;not&lt;/i&gt;&amp;nbsp;goodbye. My time on the Foundation's board has been a wonderful and interesting ride. I hope I have lived up to Tim O'Reilly's ethic of creating more value than I extract.&lt;br /&gt;&lt;div&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-Xkq-9wjjbMA/UX4C3BZv5pI/AAAAAAAABo0/oqG_87y9sUc/s1600/2013-04-28_15-36-04.png&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;63&quot; src=&quot;http://1.bp.blogspot.com/-Xkq-9wjjbMA/UX4C3BZv5pI/AAAAAAAABo0/oqG_87y9sUc/s400/2013-04-28_15-36-04.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=-xGkCjGmzSo:A9ZCS4HaxdM: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=-xGkCjGmzSo:A9ZCS4HaxdM:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=-xGkCjGmzSo:A9ZCS4HaxdM:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/-xGkCjGmzSo&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">&quot;Any sufficiently advanced technology is indistinguishable from magic&quot; -- Arthur C Clarke
&lt;br /&gt;
Musings from the technological frontier</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2013-05-16T00:22:18+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Why Tuples?</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/IERINDcToYQ/why-tuples.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-8629313830167737814</id>
		<updated>2013-04-28T05:23:08+00:00</updated>
		<content type="html">A frequent question from new and even not-so-new Python programmers is &quot;why does the language have both tuples (which, if you know Python, you will recall are immutable) and lists?&quot; You might almost say there are two kinds of Python programmers, those who know what tuples are for and those whose mathematical education has been limited. I know this sounds like an awfully snobbish thing to say, but it isn't meant that way. The fact is that I learned most of my programming in eight years of working experience before I started my degree studies, and I am therefore of the very definite opinion that people with little mathematical background can be excellent programmers.&lt;br /&gt;
&lt;br /&gt;
It's just that I myself only came across the word &lt;i&gt;tuple&lt;/i&gt;&amp;nbsp;when I started studying college-level mathematics and had to come to terms with things like&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;div&gt;
An&amp;nbsp;&lt;i&gt;NFA&lt;/i&gt;&amp;nbsp;is represented formally by a&amp;nbsp;&lt;a class=&quot;mw-redirect&quot; href=&quot;http://en.wikipedia.org/wiki/N-tuple&quot; title=&quot;N-tuple&quot;&gt;5-tuple&lt;/a&gt;, (&lt;i&gt;Q&lt;/i&gt;, Σ, Δ,&amp;nbsp;&lt;i&gt;q&lt;sub&gt;0&lt;/sub&gt;&lt;/i&gt;,&amp;nbsp;&lt;i&gt;F&lt;/i&gt;), consisting of&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;a finite&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Set_(mathematics)&quot; title=&quot;Set (mathematics)&quot;&gt;set&lt;/a&gt;&amp;nbsp;of states&amp;nbsp;&lt;i&gt;Q&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;a finite set of&amp;nbsp;&lt;a class=&quot;mw-redirect&quot; href=&quot;http://en.wikipedia.org/wiki/Input_symbol&quot; title=&quot;Input symbol&quot;&gt;input symbols&lt;/a&gt;&amp;nbsp;Σ&lt;/li&gt;
&lt;li&gt;a transition&amp;nbsp;&lt;a class=&quot;mw-redirect&quot; href=&quot;http://en.wikipedia.org/wiki/Relation_(logic)&quot; title=&quot;Relation (logic)&quot;&gt;relation&lt;/a&gt;&amp;nbsp;Δ&amp;nbsp;:&amp;nbsp;&lt;i&gt;Q&lt;/i&gt;&amp;nbsp;× Σ →&amp;nbsp;&lt;i&gt;P&lt;/i&gt;(&lt;i&gt;Q&lt;/i&gt;).&lt;/li&gt;
&lt;li&gt;an&amp;nbsp;&lt;i&gt;initial&lt;/i&gt;&amp;nbsp;(or&amp;nbsp;&lt;i&gt;start&lt;/i&gt;) state&amp;nbsp;&lt;i&gt;q&lt;/i&gt;&lt;sub&gt;0&lt;/sub&gt;&amp;nbsp;∈&amp;nbsp;&lt;i&gt;Q&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;a set of states&amp;nbsp;&lt;i&gt;F&lt;/i&gt;&amp;nbsp;distinguished as&amp;nbsp;&lt;i&gt;accepting&lt;/i&gt;&amp;nbsp;(or&amp;nbsp;&lt;i&gt;final&lt;/i&gt;)&amp;nbsp;&lt;i&gt;states&lt;/i&gt;&amp;nbsp;&lt;i&gt;F&lt;/i&gt;&amp;nbsp;⊆&amp;nbsp;&lt;i&gt;Q&lt;/i&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
Now this has a very definite meaning. It tells us that an (ordered - &lt;i&gt;i.e.&lt;/i&gt;&amp;nbsp;positionally-identified) set of five things is sufficient to define the behavior of a specific type of object (in this case a non-deterministic finite state automaton (NFA), though for all you need to know about those I might just as well be describing a flux capacitor).&lt;br /&gt;
&lt;br /&gt;
If we wanted to encapsulate an NFA as a Python data structure, then we might at some point in our code write in our Python code something like&lt;br /&gt;
&lt;br /&gt;
&lt;span&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; nfa = (states, symbols, transition, initial, accepting_states)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
though in actual fact you would be more likely to want to incorporate behavior in a class and so write instead&lt;br /&gt;
&lt;br /&gt;
&lt;span&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; nfa = NFA(states, symbols, transition, initial, accepting_states)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Now even though you may not know what an NFA is, you will surely perceive that the set of its possible states is a very different thing from the function that determines how a current state and a set of inputs are mapped into new states. So there is simply no way that it would be meaningful to write&lt;br /&gt;
&lt;br /&gt;
&lt;span&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; for thing in (states, symbols, transition, initial, accepting_states):&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; do_something_with(thing)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
unless you were, for example, trying to save its state during a pickling operation or some more obscure book-keeping metacode.&lt;br /&gt;
&lt;br /&gt;
And that, best beloved, is what tuples are for: they are ordered collections of objects, and each of the objects has, according to its position, a specific meaning (sometimes referred to as its&amp;nbsp;&lt;i&gt;semantics&lt;/i&gt;). If no behaviors are required then a tuple is &quot;about the simplest thing that could work.&quot;&lt;br /&gt;
&lt;br /&gt;
This is why you often hear people informally say tuples are for &quot;collections of things you don't need to iterate over&quot; or &quot;tuples are for sequences of dissimilar objects&quot;. My advice would be to stay away from such discussions. One might reasonably argue that including them in the language discouraged people from using objects with named attributes, which are always easier to deal with.&lt;br /&gt;
&lt;br /&gt;
The problem with the tuple is that once we have constructed our NFA the only way to refer to the states in code is with the rather unedifying expression&lt;br /&gt;
&lt;br /&gt;
&lt;span&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; nfa[0]&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
which doesn't actually tell the reader much about&amp;nbsp;the&amp;nbsp;programmer's intention. The sequence nature of the tuple means that our accesses to the elements are difficult to imbue with meaning in our code. This latterly became such an obvious shortcoming that it prompted Raymond Hettinger to create the &lt;b&gt;&lt;a href=&quot;http://docs.python.org/3/library/collections.html#collections.namedtuple&quot; target=&quot;_blank&quot;&gt;namedtuple&lt;/a&gt;&lt;/b&gt; object that allows you to easily specify a tuple whose elements can also be referred to by name.&lt;br /&gt;
&lt;br /&gt;
It would be interesting to see whether users of namedtuple objects actually use them as tuples at all. I would guess that the sequence behaviors are rarely used, in which case perhaps it's time to either remove namedtuple's&amp;nbsp;&lt;i&gt;__getitem__()&lt;/i&gt;&amp;nbsp;and similar methods or implement a similar object without the sequence behaviors.&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=IERINDcToYQ:hEk54ybLI9w: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=IERINDcToYQ:hEk54ybLI9w:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=IERINDcToYQ:hEk54ybLI9w:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/IERINDcToYQ&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">&quot;Any sufficiently advanced technology is indistinguishable from magic&quot; -- Arthur C Clarke
&lt;br /&gt;
Musings from the technological frontier</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2013-05-16T00:22:18+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Visualising London, Brighton and the UK using Geo-Tweets</title>
		<link href="http://ianozsvald.com/2013/04/17/visualising-london-brighton-and-the-uk-using-geo-tweets/"/>
		<id>http://ianozsvald.com/?p=1776</id>
		<updated>2013-04-17T10:38:31+00:00</updated>
		<content type="html">&lt;p&gt;Recently I&amp;#8217;ve been grabbing Tweets some some natural language processing analysis (in Python using NetworkX and NLTK) &amp;#8211; see this &lt;a href=&quot;http://ianozsvald.com/2013/03/18/semantic-map-of-pycon2013-twitter-topics/&quot;&gt;PyCon&lt;/a&gt; and &lt;a href=&quot;http://ianozsvald.com/2013/03/22/analysing-pydata-london-and-brighton-tweets-for-concept-mapping/&quot;&gt;PyData&lt;/a&gt; conversation analysis. Using the London dataset (visualised in the PyData post) I wondered if the geo-tagged tweets would give a good-looking map of London. It turns out that it does:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/london_all_r1_nomap.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1791&quot; alt=&quot;london_all_r1_nomap&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/london_all_r1_nomap-300x225.png&quot; width=&quot;300&quot; height=&quot;225&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see the bright centre of London, the Thames is visible wiggling left-to-right through the centre. The black region to the left of the centre is &lt;a href=&quot;https://en.wikipedia.org/wiki/Hyde_Park,_London&quot;&gt;Hyde Park&lt;/a&gt;. If you look around the edges you can even see the M25 motorway circling the city. This is about a week&amp;#8217;s worth of geo-filtered Tweets from the Twitter 10% firehose. It is easier to locate using the following Stamen tiles:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/london_all_r5.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1792&quot; alt=&quot;london_all_r5&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/london_all_r5-300x265.png&quot; width=&quot;300&quot; height=&quot;265&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Can you see Canary Wharf and the O2 arena to its east? How about Heathrow to the west edge of the map? And the string of reservoirs heading north north east from Tottenham?&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a zoom around Victoria and London Bridge, we see a lot of Tweets around the railway stations, Oxford Street and Soho. I&amp;#8217;m curious about all the dots in the Thames &amp;#8211; presumably people Tweeting about their pleasure trips?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/centrallondon_r3_map.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1793&quot; alt=&quot;centrallondon_r3_map&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/centrallondon_r3_map-300x231.png&quot; width=&quot;300&quot; height=&quot;231&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a zoom around the Shoreditch/Tech City area. I was surprised by the cluster of Tweets in the roundabout (Old Street tube station), there&amp;#8217;s a cluster in Bonhill Street (where &lt;a href=&quot;http://www.campuslondon.com/&quot;&gt;Google&amp;#8217;s Campus&lt;/a&gt; is located &amp;#8211; I work above there in &lt;a href=&quot;http://www.centralworking.com/&quot;&gt;Central Working&lt;/a&gt;). The cluster off of Old Street onto Rivington Street seems to be at the location of the new and fashionable outdoor eatery spot (with &lt;a href=&quot;http://www.burgeraddict.org/2013/01/greedy-bear-burger-bear-london.html&quot;&gt;Burger Bear&lt;/a&gt;). Further to the east is a more pubby/restauranty area.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/london_shoreditch_all.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1794&quot; alt=&quot;london_shoreditch_all&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/london_shoreditch_all-266x300.png&quot; width=&quot;266&quot; height=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve yet to analyse the content of these tweets (doing something like phrase extraction from the PyCon/PyData tweets onto this map would be great). As such I&amp;#8217;m not sure what&amp;#8217;s being discussed, probably a bunch of the banal along with chitchat between people (&amp;#8220;I&amp;#8221;m on my way&amp;#8221;&amp;#8230;). Hopefully some of it discusses the nearby environment.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m using &lt;a href=&quot;http://www.sethoscope.net/heatmap/&quot;&gt;Seth&amp;#8217;s Python heatmap&lt;/a&gt; (inspired by his lovely visuals). In addition I&amp;#8217;m using &lt;a href=&quot;http://maps.stamen.com/#terrain/12/37.7706/-122.3782&quot;&gt;Stamen&lt;/a&gt; map tiles (via OpenStreetMap). I&amp;#8217;m using curl to consume the Twitter firehose via a geo-defined area for London, saving the results to a JSON file which I consume later (shout if you&amp;#8217;d like the code and I&amp;#8217;ll put it in github) &amp;#8211; here&amp;#8217;s a &lt;a href=&quot;http://mike.teczno.com/notes/streaming-data-from-twitter.html&quot;&gt;tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;During London Fashion Week I grabbed the tagged tweets (for &amp;#8220;#lfw&amp;#8217; and those mentioning &amp;#8220;london fashion week&amp;#8221; in the London area), if you zoom on the &lt;a href=&quot;http://www.londonfashionweek.co.uk/Map_EventsList.aspx&quot;&gt;official event map&lt;/a&gt; you&amp;#8217;ll see that the primary Tweet locations correspond to the official venue sites.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/lfw.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1795&quot; alt=&quot;lfw&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/lfw-300x275.png&quot; width=&quot;300&quot; height=&quot;275&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What about &lt;a href=&quot;https://en.wikipedia.org/wiki/Brighton&quot;&gt;Brighton&lt;/a&gt;? Down on the south coast (about 1 hour on the train south of London), it is where I&amp;#8217;ve spent the last 10 years (before my &lt;a href=&quot;http://ianozsvald.com/2012/11/25/startupchile-round-2-1-all-finished-thoughts/&quot;&gt;recent move&lt;/a&gt; to London). You can see the coastline, also Sussex University&amp;#8217;s campus (north east corner). Western Road (the thick line running west a little way back from the sea) is the main shopping street with plenty of bars.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/brighton_gps_to0103_nomap.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1796&quot; alt=&quot;brighton_gps_to0103_nomap&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/brighton_gps_to0103_nomap-300x225.png&quot; width=&quot;300&quot; height=&quot;225&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#8217;ll make more sense with the Stamen tiles, Brighton Marina (south east corner) is clear along with the small streets in the centre of Brighton:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/brighton_gps_to0403_map.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1797&quot; alt=&quot;brighton_gps_to0403_map&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/brighton_gps_to0403_map-300x253.png&quot; width=&quot;300&quot; height=&quot;253&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Zooming to the centre is very nice, the &lt;a href=&quot;https://en.wikipedia.org/wiki/North_Laine&quot;&gt;North Laines&lt;/a&gt; are obvious (to the north) and the pedestriansed area below (the &amp;#8220;south laines&amp;#8221;) is clear too. Further south we see the &lt;a href=&quot;https://en.wikipedia.org/wiki/Brighton_Pier&quot;&gt;Brighton Pier&lt;/a&gt; reaching into the sea. To the north west on the edge of the map is another cluster inside &lt;a href=&quot;https://en.wikipedia.org/wiki/Brighton_station&quot;&gt;Brighton Station&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/brighton_gps_to0403_map_zoomed.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1798&quot; alt=&quot;brighton_gps_to0403_map_zoomed&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/brighton_gps_to0403_map_zoomed-300x288.png&quot; width=&quot;300&quot; height=&quot;288&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Finally &amp;#8211; what about all the geo-tagged Tweets for the UK (annoyingly I didn&amp;#8217;t go far enough west to get Ireland)? I&amp;#8217;m pleased to see that the entirety of the mainland is well defined, I&amp;#8217;m guessing many of the tweets around the coastline are more from pretty visiting points.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/uk_gps_to0404_map_r5_zoomed.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1800&quot; alt=&quot;uk_gps_to0404_map_r5_zoomed&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/uk_gps_to0404_map_r5_zoomed-184x300.png&quot; width=&quot;184&quot; height=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;How might this compare with a satellite photograph of the UK at night? Population centres are clearly visible but tourist spots are far less visible, the edge of the country is much less defined (via &lt;a href=&quot;http://www.dailymail.co.uk/sciencetech/article-2243891/Sleepless-Britain-Nasas-stunning-images-UK-night.html&quot;&gt;dailymail&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/uk_nightlights_via_dailymail_article-0-165F7719000005DC-828_964x592.jpg&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1801&quot; alt=&quot;Europe satellite&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/04/uk_nightlights_via_dailymail_article-0-165F7719000005DC-828_964x592-300x184.jpg&quot; width=&quot;300&quot; height=&quot;184&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m guessing we can use these Tweets for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Understanding what people talk about in certain areas (e.g. Oxford Street at rush-hour?)&lt;/li&gt;
&lt;li&gt;Learning why foursquare checkings (below) aren&amp;#8217;t in the same place as tweet locations (can we filter locations away by using foursquare data?)&lt;/li&gt;
&lt;li&gt;Seeing how people discuss the weather &amp;#8211; is it correlated with local weather reports?&lt;/li&gt;
&lt;li&gt;Learning if people talk about their environment (e.g. too many cars, poor London tube climate control, bad air, too noisy, shops and signs, events)&lt;/li&gt;
&lt;li&gt;Seeing how shops, gigs and events are discussed &amp;#8211; could we recommend places and events in real time based on their discussion?&lt;/li&gt;
&lt;li&gt;Figuring out how people discuss landmarks and tourist spots &amp;#8211; maybe this helps with recommending good spots to visit?&lt;/li&gt;
&lt;li&gt;Looking at the trail people leave as they Tweet over time &amp;#8211; can we figure out their commute and what they talk about before and after? Maybe this is a sort of survey process that happens using public data?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are some other geo-based visualisations I&amp;#8217;ve recently seen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nice video of Oyster London Underground checkins from 2012 (&lt;a href=&quot;http://oliverobrien.co.uk/2013/03/londons-tidal-oyster-card-flow/&quot;&gt;write-up&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;FourSquare&amp;#8217;s 500,000 &lt;a href=&quot;https://foursquare.com/infographics/500million?&quot;&gt;check-in visualisation&lt;/a&gt; (&lt;a href=&quot;http://blog.foursquare.com/2013/01/17/what-the-last-500000000-check-ins-look-like-and-what-they-show-about-the-future-of-foursquare/&quot;&gt;Jan blog post&lt;/a&gt;) for the world, zoom on London to see how the map is &lt;em&gt;different&lt;/em&gt; to the tweet data I have above&lt;/li&gt;
&lt;li&gt;Another FourSquare &lt;a href=&quot;http://thebackofyourhand.com/&quot;&gt;check-in visualisation&lt;/a&gt; just for London filtered by location-type&lt;/li&gt;
&lt;li&gt;Language-tagged &lt;a href=&quot;http://ny.spatial.ly/&quot;&gt;geo-tweets for New York&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Language-tagged &lt;a href=&quot;http://spatialanalysis.co.uk/2012/10/londons-twitter-languages/&quot;&gt;geo-tweets for London&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Language-tagged &lt;a href=&quot;https://secure.flickr.com/photos/walkingsf/6276642489/&quot;&gt;geo-tweets for Europe&lt;/a&gt; (uses the Chromium &lt;a href=&quot;https://code.google.com/p/chromium-compact-language-detector/&quot;&gt;compact language detector&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want help with this sort of work then note that I run my own &lt;a href=&quot;http://morconsulting.com/&quot;&gt;AI consultancy&lt;/a&gt;, analysing and visualising social media like Twitter is an active topic for me at present (and will be more so via my planned API at &lt;a href=&quot;http://annotate.io/&quot;&gt;annotate.io&lt;/a&gt;).&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">More Python 3.3 downloads than Python 2.7 for past 3 months</title>
		<link href="http://ianozsvald.com/2013/04/15/more-python-3-3-downloads-than-python-2-7-for-past-3-months/"/>
		<id>http://ianozsvald.com/?p=1779</id>
		<updated>2013-04-15T13:03:32+00:00</updated>
		<content type="html">&lt;p&gt;Since PyCon 2013 I&amp;#8217;ve been in a set of conversations that start with &amp;#8220;should I be using Python 3.3 for science work?&amp;#8221;. Here&amp;#8217;s a recent &lt;a href=&quot;http://www.reddit.com/r/Python/comments/19eu32/im_a_student_brushing_up_on_my_python_should_i/&quot;&gt;reddit thread&lt;/a&gt; on the subject. Last year I solidly recommended using Python 2.7 for scientific work (as many key libraries weren&amp;#8217;t yet supported). I&amp;#8217;m on the cusp of changing my recommendation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; there&amp;#8217;s a nice thread on &lt;a href=&quot;http://www.reddit.com/r/Python/comments/1cdxi6/more_python_33_downloads_than_python_27_each/&quot;&gt;Reddit/r/python&lt;/a&gt; discussing what&amp;#8217;s required and where the numbers are coming from.&lt;/p&gt;
&lt;p&gt;I last looked at the rate of Python downloads via ShowMeDo &lt;a href=&quot;http://blog.showmedo.com/news/growth-in-python-project-popularity/&quot;&gt;during 2008&lt;/a&gt; when Python 2.5 was the top dog. The Windows 2.5.1 installer was getting 500,000 downloads a month. In the last 3 months I&amp;#8217;m pleasantly surprised to see that Python 3.3 for Windows is downloaded more each month than Python 2.7. We can see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python.org/webstats/usage_201303.html&quot;&gt;March 2013&lt;/a&gt; Python 3.3 for Windows has 647k downloads vs Python 2.7 with 630k&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python.org/webstats/usage_201302.html&quot;&gt;February 2013&lt;/a&gt; Python 3.3 for Windows has 553k downloads vs Python 2.7 with 498k&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python.org/webstats/usage_201301.html&quot;&gt;January 2013&lt;/a&gt; Python 3.3 for Windows has 533k downloads vs Python 2.7 with 495k (Python 2.7 less popular since January 2013)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.python.org/webstats/usage_201212.html&quot;&gt;December 2012&lt;/a&gt; Python 3.3 for Windows has 412k downloads vs Python 2.7 with 525k&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These figures only tell a part of the story of course. For Windows you have to download Python. On Linux and Mac it comes pre-installed (so we can&amp;#8217;t measure those numbers).&lt;/p&gt;
&lt;p&gt;Python 2.7 has been the default on Ubuntu for a while, that&amp;#8217;s &lt;a href=&quot;https://wiki.ubuntu.com/RaringRingtail/TechnicalOverview#Python_3.3&quot;&gt;changing with Ubuntu 13.04&lt;/a&gt;. There are &lt;a href=&quot;https://py3ksupport.appspot.com/&quot;&gt;two&lt;/a&gt; &lt;a href=&quot;https://python3wos.appspot.com/&quot;&gt;lists&lt;/a&gt; of Python-3 compatible packages, it seems that Django is on this list and at PyCon there was a &lt;a href=&quot;http://www.pyvideo.org/video/1787/porting-django-apps-to-python-3&quot;&gt;how-to-port-to-py3 video&lt;/a&gt; (not &lt;a href=&quot;https://gist.github.com/untitaker/5321447&quot;&gt;Flask yet&lt;/a&gt; &lt;strong&gt;update&lt;/strong&gt; Armin is &lt;a href=&quot;https://twitter.com/mitsuhiko/status/323177177367601152&quot;&gt;tweeting for sprint help&lt;/a&gt; for Py3 support), SQLAlchemy is (but not MySQL-python), Fabric isn&amp;#8217;t ready yet. For web-dev it seems to be a mixed bag but I&amp;#8217;m guessing Python 3 support will be across the board this year.&lt;/p&gt;
&lt;p&gt;For scientific use we already have Python-3 compatible numpy, scipy and matplotlib. scikit-learn is &amp;#8216;&lt;a href=&quot;https://github.com/scikit-learn/scikit-learn/pull/1361&quot;&gt;nearly&lt;/a&gt;&amp;#8216; ported, Pillow (the recent fork of PIL) is ready for Python 3. NLTK is also &lt;a href=&quot;http://nltk.org/nltk3-alpha/&quot;&gt;being ported&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For scientific use around natural language processing the switch to unicode-by-default looks most attractive (the mix of strings and unicode datatypes has burnt hours for me over the years in Python 2.x). Here&amp;#8217;s a PyCon video on the use of &lt;a href=&quot;http://www.pyvideo.org/video/1704/why-you-should-use-python-3-for-text-processing&quot;&gt;Python 3 for text processing&lt;/a&gt; and this reviews &lt;a href=&quot;http://www.pyvideo.org/video/1730/python-33-trust-me-its-better-than-27&quot;&gt;why Python 3.3 is superior to Python 2.7&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is slightly too early for me yet to want to switch but I&amp;#8217;m starting to experiment. I&amp;#8217;ve added some __future__ imports to new code so I know I&amp;#8217;m writing Python 2.7 in a 3-like style. I&amp;#8217;m also increasingly using Ned Batchelder&amp;#8217;s &lt;a href=&quot;http://nedbatchelder.com/code/coverage/&quot;&gt;coverage.py&lt;/a&gt; via nosetests to make sure I have good coverage. I currently run 2to3 to check that things convert cleanly to Python 3 but rarely run the result with Python 3 (I haven&amp;#8217;t needed to do this yet). There&amp;#8217;s a set of useful advice on &lt;a href=&quot;http://python3porting.com/&quot;&gt;python3porting&lt;/a&gt; including various __future__ imports (including division, print_function, unicode_literals, absolute_import).&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Careful with your assertRaises() and inheritance of exceptions</title>
		<link href="http://www.peterbe.com/plog/assertraises-and-inheritance"/>
		<id>http://www.peterbe.com/plog/assertraises-and-inheritance</id>
		<updated>2013-04-10T16:47:17+00:00</updated>
		<content type="html">&lt;p&gt;This took me by surprise today!&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;If you run this unit test, it actually passes with flying colors:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;unittest&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BadAssError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ne&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BadAssError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;d'oh&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertRaises&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BadAssError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertRaises&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ne&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertRaises&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ne&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'__main__'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Basically, &lt;code&gt;assertRaises&lt;/code&gt; doesn't just take the exception that is being raised and accepts it, it also takes any of the raised exceptions' parents.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;I've only tested it with Python 2.6 and 2.7. And the same works equally with &lt;a href=&quot;https://pypi.python.org/pypi/unittest2&quot;&gt;unittest2&lt;/a&gt;.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;I don't really know how I feel about this. It did surprise me when I was changing one of the exceptions and expected the old tests to break but they didn't. I mean, if I want to write a test that really makes sure the exception really is &lt;code&gt;BadAssError&lt;/code&gt; it means I can't use &lt;code&gt;assertRaises()&lt;/code&gt;. &lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Applied Parallel Computing (PyCon 2013 Tutorial) slides and code</title>
		<link href="http://ianozsvald.com/2013/04/02/applied-parallel-computing-pycon-2013-tutorial-slides-and-code/"/>
		<id>http://ianozsvald.com/?p=1720</id>
		<updated>2013-04-02T07:32:33+00:00</updated>
		<content type="html">&lt;p&gt;Minesh B. Amin (&lt;a href=&quot;http://www.mbasciences.com/&quot;&gt;MBASciences&lt;/a&gt;) and I (&lt;a href=&quot;http://www.morconsulting.com/&quot;&gt;Mor Consulting&lt;/a&gt; Ltd) taught &lt;a href=&quot;https://us.pycon.org/2013/schedule/presentation/27/&quot;&gt;Applied Parallel Computing&lt;/a&gt; over 3 hours at PyCon 2013. PyCon this year was a heck of a lot of fun, I did the fun run (mentioned below), received one of the free 2500 RaspberryPis that were given away, met an awful lot of interesting people and ran two birds-of-a-feather sessions (parallel computing for our tutorial, another on natural language processing).&lt;/p&gt;
&lt;p&gt;I held posting this entry until the video was ready (it came out yesterday). All the code and slides are in the &lt;a href=&quot;https://github.com/ianozsvald/pycon2013_applied_parallel_computing/tree/master/Presentation%20slides&quot;&gt;github repo&lt;/a&gt;. Currently (but not indefinitely) there&amp;#8217;s a VirtualBox image &lt;a href=&quot;http://ianozsvald.com/2013/03/15/use-of-virtualbox-to-prepare-students-pycon-tutorials/&quot;&gt;with everything&lt;/a&gt; (Redis, Disco etc) pre-installed.&lt;/p&gt;
&lt;p&gt;After the conference, partly as a result of the BoF NLP session I created a Twitter graph &lt;a href=&quot;http://ianozsvald.com/2013/03/18/semantic-map-of-pycon2013-twitter-topics/&quot;&gt;&amp;#8220;Concept Map&amp;#8221; based on #pycon tweets&lt;/a&gt;, then &lt;a href=&quot;http://ianozsvald.com/2013/03/22/analysing-pydata-london-and-brighton-tweets-for-concept-mapping/&quot;&gt;another for #pydata&lt;/a&gt;. They neatly summarise many of the topics of conversation.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s our room of 60+ students, slides and video are below:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/students_left.jpg&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1724&quot; alt=&quot;Applied Parallel Computing PyCon 2013 (left side of room)&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/students_left-300x225.jpg&quot; width=&quot;300&quot; height=&quot;225&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/students_right1.jpg&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1723&quot; alt=&quot;Applied Parallel Computing PyCon 2013 (left side)&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/students_right-300x225.jpg&quot; width=&quot;300&quot; height=&quot;225&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The video runs for 2 hours 40:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a list of our slides:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ianozsvald/pycon2013_applied_parallel_computing/blob/master/Presentation%20slides/IntroParallelism.pdf&quot;&gt;Intro to Parallelism&lt;/a&gt; (Minesh)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ianozsvald/pycon2013_applied_parallel_computing/blob/master/Presentation%20slides/LessonsLearned_AppliedParallelComputing_PyCon2013.pdf&quot;&gt;Lessons Learned&lt;/a&gt; (Ian)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ianozsvald/pycon2013_applied_parallel_computing/blob/master/Presentation%20slides/ListOfTasks_AppliedParallelComputing_PyCon2013.pdf&quot;&gt;List of Tasks with Mandelbrot set&lt;/a&gt; (Ian)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ianozsvald/pycon2013_applied_parallel_computing/blob/master/Presentation%20slides/MapReduce_AppliedParallelComputing_PyCon2013.pdf&quot;&gt;Map/Reduce with Disco&lt;/a&gt; (Ian)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ianozsvald/pycon2013_applied_parallel_computing/blob/master/Presentation%20slides/IntroOS.pdf&quot;&gt;Hyperparameter optimisation with grid and random search&lt;/a&gt; (Minesh)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are each of the slide decks:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I also had fun in the 5k fun run (coming around 77th of 150 runners), we raised $7k or so for cancer research and the &lt;a href=&quot;http://numfocus.org/johnhunter/&quot;&gt;John Hunter Memorial Fund&lt;/a&gt;. &lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">IMAPClient 0.9.2</title>
		<link href="http://freshfoo.com/blog/IMAPClient-0.9.2"/>
		<id>http://freshfoo.com/blog/2013/03/28/IMAPClient-0.9.2</id>
		<updated>2013-03-28T23:35:00+00:00</updated>
		<content type="html">&lt;p&gt;IMAPClient 0.9.2 was released yesterday. In this release:&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;The IMAP THREAD command is now supported. Thanks to Lukasz Mierzwa
for the patches.&lt;/li&gt;
&lt;li&gt;Enhanced CAPABILITY querying&lt;/li&gt;
&lt;li&gt;Better documentation for contributors (see &lt;a class=&quot;reference external&quot; href=&quot;https://bitbucket.org/mjs0/imapclient/src/tip/HACKING&quot;&gt;HACKING&lt;/a&gt; file)&lt;/li&gt;
&lt;li&gt;Copyright date update for 2013.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class=&quot;reference external&quot; href=&quot;https://bitbucket.org/mjs0/imapclient/src/tip/NEWS&quot;&gt;NEWS&lt;/a&gt; file and &lt;a class=&quot;reference external&quot; href=&quot;http://imapclient.readthedocs.org/&quot;&gt;manual&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;IMAPClient can be installed from PyPI (&lt;tt class=&quot;docutils literal&quot;&gt;pip install imapclient&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;.&lt;/p&gt;
&lt;p&gt;Note that the official project source repository is now &lt;a class=&quot;reference external&quot; href=&quot;https://bitbucket.org/mjs0/imapclient/&quot;&gt;on
Bitbucket&lt;/a&gt;. &lt;a class=&quot;reference external&quot; href=&quot;http://imapclient.freshfoo.com/&quot;&gt;http://imapclient.freshfoo.com/&lt;/a&gt; is still the offical home
page and is still used for project tracking. It is only the source
respository that has moved.&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>2013-06-19T00:22:11+00:00</updated>
			<rights type="html">Copyright 2009 Menno Smits</rights>
		</source>
	</entry>

	<entry>
		<title type="html">&quot;Test Driven Development of Web Applications&quot; -- the book exists, and is available on Early Release</title>
		<link href="http://www.obeythetestinggoat.com/tdd-web-programming-book-on-oreilly-early-release.html"/>
		<id>tag:www.obeythetestinggoat.com,2013-03-26:tdd-web-programming-book-on-oreilly-early-release.html</id>
		<updated>2013-03-26T18:35:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;img alt=&quot;Front cover of book&quot; src=&quot;http://www.obeythetestinggoat.com/static/images/new_goat_cover_lrg.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I can't quite believe this is actually happening, but I have not only signed a contract with O'Reilly, but i have actually written the first four chapters, or at least a first draft of the first four chapters!&lt;/p&gt;
&lt;p&gt;For anyone new, the idea is to provide an introduction to TDD for web app development, for beginners -- whether it's people who've never done web development and Django before, or just people who've never done TDD.&lt;/p&gt;
&lt;p&gt;I'm releasing the book as early as possible to try and gather feedback, so please, please do get yourself a copy, and tell me what I'm doing right and wrong!  What would you change?  Am I pitching it at the right level?  Is the pace right or wrong? Should I spend more or less time on explaining the basics of Django, more or less time on the basics of TDD, more or less time with detailed examples?&lt;/p&gt;
&lt;p&gt;Here's the book on the O'Reilly Early Release program:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.kqzyfj.com/click-7079286-11260198?url=http%3A%2F%2Fshop.oreilly.com%2Fproduct%2F0636920029533.do%3Fcmp%3Daf-code-book-product_cj_9781449367794_%7BPID%7D&amp;amp;cjsku=0636920029533&quot; target=&quot;_top&quot;&gt;
Test-Driven Development with Python&lt;/a&gt;&lt;img src=&quot;http://www.awltovhc.com/image-7079286-11260198&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Buying direct from O'Reilly is probably the best option, they have DRM-free versions you can download in all sorts of formats (MOBI/epub/pdf)...&lt;/p&gt;
&lt;p&gt;Alternatively, if you have an account on Safari, you can &lt;a href=&quot;http://my.safaribooksonline.com/9781449365141&quot;&gt;get it there too&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Remember, this is an early draft, so expect the occasional rough edges... But I really, really want your feedback folks, so do let me know what you think -- here in the comments, in the comments on either site, or just by email to &lt;a href=&quot;mailto:hjwp2@cantab.net&quot;&gt;hjwp2@cantab.net&lt;/a&gt;.  &lt;/p&gt;
&lt;p&gt;Thanks to everyone for your kind words of support, and thanks in advance for your help!&lt;/p&gt;
&lt;p&gt;[update] -- in case it's not clear:  if you buy this book now, either via O'Reilly or via Safari, you'll get updates from now on, as each new chapter is released, until the final version is released and you get the full copy.  Anyone that provides feedback is totes getting a credit in the final book!&lt;/p&gt;
&lt;p&gt;[update 2] -- &lt;em&gt;naturally&lt;/em&gt; I assume you're all more than keen to &lt;strong&gt;pay&lt;/strong&gt; for this book, but just as a matter of principle, there will be a Creative Commons, &quot;try-before-you-buy&quot;, free version of the early drafts, released sometime in the near future.  The final version of the book will also have a Creative Commons (NC-ND) digital version released on publication.  And after 10 years, it will automatically revert to CC-0 Public Domain. But I (and my publishers) very much appreciate every single early sale!&lt;/p&gt;
&lt;p&gt;[update 3] -- follow me on twitter &lt;a href=&quot;https://twitter.com/hjwp&quot;&gt;@hjwp&lt;/a&gt; or sign up for this blog's updates to find out more about progress with the book, including when the CC version comes out... And, just let me know you're interested!&lt;/p&gt;</content>
		<author>
			<name>Harry</name>
			<uri>http://www.obeythetestinggoat.com/</uri>
		</author>
		<source>
			<title type="html">Obey the Testing Goat!</title>
			<link rel="self" href="http://www.obeythetestinggoat.com/feeds/all.atom.xml"/>
			<id>http://www.obeythetestinggoat.com/</id>
			<updated>2013-06-10T20:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Analysing #pydata, London and Brighton tweets for concept mapping</title>
		<link href="http://ianozsvald.com/2013/03/22/analysing-pydata-london-and-brighton-tweets-for-concept-mapping/"/>
		<id>http://ianozsvald.com/?p=1748</id>
		<updated>2013-03-22T00:16:10+00:00</updated>
		<content type="html">&lt;p&gt;Below I&amp;#8217;ve visualised tweets for #PyData conference and the cities of London and Brighton &amp;#8211; this builds on my &amp;#8216;&lt;a href=&quot;http://ianozsvald.com/2013/03/18/semantic-map-of-pycon2013-twitter-topics/&quot;&gt;concept cloud&lt;/a&gt;&amp;#8216; from a few days ago at the #PyCon conference. Props to Maksim for his &lt;a href=&quot;https://us.pycon.org/2013/schedule/presentation/29/&quot;&gt;Social Media Analysis&lt;/a&gt; tutorial for inspiration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; &amp;#8211; Maksim&amp;#8217;s &lt;a href=&quot;http://pyvideo.org/video/1714/analyzing-social-networks-with-python&quot;&gt;Analying Social Networks&lt;/a&gt; tutorial video is online.&lt;/p&gt;
&lt;p&gt;For the earlier &lt;a href=&quot;https://us.pycon.org/2013/&quot;&gt;#PyCon 2013&lt;/a&gt; analysis I visualised #hashtags and @usernames from #pycon tagged tweets during the conference. I&amp;#8217;ve built upon this to add some natural language processing for &amp;#8216;noun phrase extraction&amp;#8217; which I detail below &amp;#8211; this helps me to pull out phrases that are descriptive but haven&amp;#8217;t been tagged. It also helps us to see which people are connected with which subjects. For the PyCon analysis I collected 22k tweets, after removing retweets I was left with 7,853 for analysis.&lt;/p&gt;
&lt;h2&gt;#PyData (PyData Santa Clara 2013)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/pydata_weds_afternoon.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1749&quot; alt=&quot;pydata_weds_afternoon&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/pydata_weds_afternoon-300x300.png&quot; width=&quot;300&quot; height=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://sv2013.pydata.org/&quot;&gt;PyData 2013&lt;/a&gt; is a much smaller conference than PyCon (PyCon had 2,500 people and 20% female attendance, PyData had around 400 with 10% female attendance). Being smaller it had far fewer tweets &amp;#8211; after removing retweets I had just 225 tweets to analyse. Cripes! This is clearly &lt;em&gt;not big data&lt;/em&gt;. The other problem was that people weren&amp;#8217;t using many #hashtags, they were referring to topics using natural language. For example:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&amp;#8220;Peter Norvig was giving a talk at PyData in Santa Clara, CA on the topic of innovation in education.&amp;#8221; (&lt;a href=&quot;https://twitter.com/jdunck/status/314073172360187906&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Clearly some natural language processing was required. I took two approaches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extract capitalised sub-phrases (e.g. &amp;#8220;Peter Norvig&amp;#8221;, &amp;#8220;Santa Clara&amp;#8221;) of one or more words&lt;/li&gt;
&lt;li&gt;Use NLTK&amp;#8217;s &lt;a href=&quot;https://en.wikipedia.org/wiki/N-gram&quot;&gt;bigram&lt;/a&gt; &lt;a href=&quot;https://nltk.googlecode.com/svn/trunk/doc/howto/collocations.html&quot;&gt;collocation&lt;/a&gt; analyser (to find lowercased phrases such as &amp;#8220;ipython notebook&amp;#8221;, &amp;#8220;machine learning&amp;#8221;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Starting at the bottom of the plot we see three types of colour:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;white is for #hashtags&lt;/li&gt;
&lt;li&gt;light blue is for @usernames&lt;/li&gt;
&lt;li&gt;dark green is for phrases (extracted using natural language processing)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We see a cluster of references around &lt;a href=&quot;https://twitter.com/fperez_org&quot;&gt;@fperez_org&lt;/a&gt; (Fernando Perez of IPython), one cluster is around &lt;a href=&quot;https://twitter.com/swcarpentry&quot;&gt;@swcarpentry&lt;/a&gt; (the scientist-friendly software carpentry movement), the other is around IPython and the IPython Notebook (&lt;a href=&quot;https://twitter.com/minrk&quot;&gt;@minrk&lt;/a&gt; of IPython/parallel is linked too). I like the connection to Julia &amp;#8211; Fernando discussed during his keynote that Julia now interoperates with Python.&lt;/p&gt;
&lt;p&gt;The day before we had &lt;a href=&quot;https://en.wikipedia.org/wiki/Peter_Norvig&quot;&gt;Peter Norvig&lt;/a&gt; (Director of research at Google) giving a keynote on the use of Python in education at Udacity including a discussion of how machine learning could be used to identify the mistakes that new coders make so we could make friendlier error messages to help students correct their code. See the clustering around this at the top of the graph.&lt;/p&gt;
&lt;p&gt;Later the same day Henrik (&lt;a href=&quot;https://twitter.com/brinkar&quot;&gt;@brinkar&lt;/a&gt;) spoke on &lt;a href=&quot;http://about.wise.io/&quot;&gt;Wise.io&lt;/a&gt;&amp;#8216;s Random Forest classifier. Their approach was efficient enough to demo live on a RaspberryPi. The connection from Peter to Henrik goes via #venturebeat who &lt;a href=&quot;http://venturebeat.com/2013/03/19/data-science-nerds-bring-machine-learning-to-the-masses-exclusive/&quot;&gt;covered&lt;/a&gt; wise.io&amp;#8217;s new software release during the conference.&lt;/p&gt;
&lt;p&gt;Connecting IPython and Wise.io is &lt;a href=&quot;https://twitter.com/ogrisel&quot;&gt;@ogrisel&lt;/a&gt; (Olivier Grisel) of scikit-learn. He gave an impressive (and given the variability of conference wifi &amp;#8211; slightly ballsy) live demo of scaling a machine learning system via IPython Parallel on EC2.&lt;/p&gt;
&lt;p&gt;In the middle we see &lt;a href=&quot;https://twitter.com/teoliphant&quot;&gt;@teoliphant &lt;/a&gt;(Travis Oliphant) joined to Continuum (his company). Off to the right I get to blow my own trumpet &amp;#8211; the phrases &amp;#8220;awesome python&amp;#8221; and &amp;#8220;network analysis&amp;#8221; connect to &amp;#8220;russel brand&amp;#8221; which is how one wag described my lightning talk. I got a chance to demo the earlier version of this at the end of &lt;a href=&quot;https://twitter.com/katychuang&quot;&gt;@katychuang&lt;/a&gt;&amp;#8216;s talk on networkx.&lt;/p&gt;
&lt;h2&gt;London (geo-tagged tweets)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/londonout.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1750&quot; alt=&quot;londonout&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/londonout-300x300.png&quot; width=&quot;300&quot; height=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For the last month I&amp;#8217;ve been grabbing tweets in the London geo area for another project. I had to raise my filtering levels to bring the network down to a sane (and easily visualised) number of nodes. After removing ReTweets I have 497,771 tweets from just a subset of my data. Some obvious clusters can be seen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;#weather and #rain and (presumably a rather wet) &amp;#8220;St Albans&amp;#8221; (a very British discussion)&lt;/li&gt;
&lt;li&gt;The &amp;#8220;O2 Arena&amp;#8221; near the centre with &amp;#8220;Justin Beiber&amp;#8221; and #believetour, linked with #amazing, #excited, #nowplaying&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/onedirection&quot;&gt;@onedirection&lt;/a&gt; must have been playing (connected with band members &lt;a href=&quot;https://twitter.com/louis_tomlinson&quot;&gt;@louis_tomlinson&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/real_liam_payne&quot;&gt;@real_liam_payne&lt;/a&gt; amongst others)&lt;/li&gt;
&lt;li&gt;To the top-right we have a football cluster with &amp;#8220;Manchester United&amp;#8221;, &amp;#8220;Champions League&amp;#8221;, #cpfc, #realmadrid and &amp;#8220;Old Trafford&amp;#8221;&lt;/li&gt;
&lt;li&gt;The usual tourist spots like &amp;#8220;Tower Bridge&amp;#8221;, &amp;#8220;Covent Garden&amp;#8221;, &amp;#8220;Hyde Park&amp;#8221;, &amp;#8220;Big Ben&amp;#8221;, &amp;#8220;Trafalgar Square&amp;#8221; are  discussed with #happy #sun #loveit, linked just off of here is &amp;#8220;London Heathrow Airport&amp;#8221; and &amp;#8220;New York&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Brighton (geo-tagged tweets)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/brighton.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1751&quot; alt=&quot;brighton&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/brighton-300x300.png&quot; width=&quot;300&quot; height=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is my favourite, analysed using 40,379 tweets after removing ReTweets. The nature of the two cities (Brighton is 50 miles south of London on the coast, it is a university town with a young &amp;amp; party-friendly population) is quite apparent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Top left there is discussion around &amp;#8220;One Direction&amp;#8221;, #justinbeiber and #seo (a particular Brighton tech &lt;em&gt;thing&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Just south of &lt;a href=&quot;https://twitter.com/justinbieber&quot;&gt;@justinbieber&lt;/a&gt; is a single chain of not-safe-for-work ranting (another particular Brighton &lt;em&gt;thing&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;If you jump to the bottom right you&amp;#8217;ll see #underwear, #lingerie, #teenagers &amp;#8211; not as dodgy as you might expect, Sweetling were doing a &lt;a href=&quot;http://sweetling.co.uk/products&quot;&gt;social media&lt;/a&gt; &lt;a href=&quot;https://twitter.com/dollysweetling/status/308610700694130689/photo/1&quot;&gt;bra&lt;/a&gt; campaign&lt;/li&gt;
&lt;li&gt;#hove is joined with #sunny #morning and nearby places #lewes #shoreham&lt;/li&gt;
&lt;li&gt;#brightonbeach and &amp;#8220;Brighton Pier&amp;#8221; connect with #birds (Seagulls &amp;#8211; a bane!) and #sun&lt;/li&gt;
&lt;li&gt;#friends, #memories#, #happy, #goodtimes, #marina, #fun, #girls cluster around the centre (Brighton does like a party)&lt;/li&gt;
&lt;li&gt;Off down to the bottom left is a some sort of political discussion (what were they doing in Brighton?)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Reproducing this&lt;/h2&gt;
&lt;p&gt;All the code is in github at &lt;a href=&quot;https://github.com/ianozsvald/twitter_networkx_concept_map&quot;&gt;twitter_networkx_concept_map&lt;/a&gt; including the one line cURL command to capture the data. An example .gephi file is included for visualisation in &lt;a href=&quot;https://gephi.org/&quot;&gt;Gephi&lt;/a&gt;. The built-in &lt;a href=&quot;https://networkx.lanl.gov/&quot;&gt;networkx&lt;/a&gt; viewer (optionally using &lt;a href=&quot;http://www.graphviz.org/&quot;&gt;GraphViz&lt;/a&gt;) works reasonably well but isn&amp;#8217;t interactive. Maksim&amp;#8217;s tutorial and utils class were jolly useful (utils is in my repo), I&amp;#8217;m also using &lt;a href=&quot;https://pypi.python.org/pypi/twitter-text-python/&quot;&gt;twitter-text-python&lt;/a&gt; for parsing @usernames, #hashtags and URLs from the tweets.&lt;/p&gt;
&lt;p&gt;If you want some custom work around this, give me a shout via &lt;a href=&quot;http://www.morconsulting.com/&quot;&gt;Mor Consulting&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">premailer now honours specificity</title>
		<link href="http://www.peterbe.com/plog/premailer-now-honours-pecificity"/>
		<id>http://www.peterbe.com/plog/premailer-now-honours-pecificity</id>
		<updated>2013-03-21T23:36:55+00:00</updated>
		<content type="html">&lt;p&gt;Thanks to &lt;a href=&quot;https://github.com/theospears&quot;&gt;Theo Spears&lt;/a&gt; awesome effort &lt;a href=&quot;https://pypi.python.org/pypi/premailer/&quot;&gt;premailer&lt;/a&gt; now support CSS specificity. What that means is that when linked and inline CSS blocks are transformed into tag style attributes the order is preserved as you'd expect.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;When the browser applies CSS to elements it does it in a specific order. For example if you have this CSS:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.tag&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;blue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;red&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and this HTML:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Regular text&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Special text&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;the browser knows to draw the first paragraph tag in red and the second paragraph in red. It does that because &lt;code&gt;p.tag&lt;/code&gt; is more specific that &lt;code&gt;p&lt;/code&gt;.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Before, it would just blindly take each selector and set it as a style tag like this:&lt;br /&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;/div&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;color:red&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Regular text&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;color:blue; color:red&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Special text&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;&lt;br /&gt;

&lt;p&gt;which is not what you want.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/peterbe/premailer/blob/master/premailer/premailer.py#L139-L147&quot;&gt;code in action is here&lt;/a&gt;.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Thanks Theo!&lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Semantic map of PyCon2013 Twitter Topics</title>
		<link href="http://ianozsvald.com/2013/03/18/semantic-map-of-pycon2013-twitter-topics/"/>
		<id>http://ianozsvald.com/?p=1736</id>
		<updated>2013-03-18T06:36:24+00:00</updated>
		<content type="html">&lt;p&gt;Maksim taught a lovely &lt;a href=&quot;https://us.pycon.org/2013/schedule/presentation/29/&quot;&gt;Social Graph Analytics&lt;/a&gt; course at PyCon the day before I taught &lt;a href=&quot;http://ianozsvald.com/2013/02/18/pycon-tutorial-notes-for-applied-parallel-computing/&quot;&gt;Applied Parallel Computing&lt;/a&gt;. I took his demo for a &amp;#8220;poor mans LDA/LSI analysis&amp;#8221; of a Twitter topic (rather than using full LDA it just uses co-incident hashtags) and added usernames to produce the plot below.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; &amp;#8211; &lt;a href=&quot;http://ianozsvald.com/2013/03/22/analysing-pydata-london-and-brighton-tweets-for-concept-mapping/&quot;&gt;Analysing #pydata conference (and the cities London and Brighton) tweets using NLTK and NetworkX&lt;/a&gt; added as a second post.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/pycon2013_hashtags_usernames.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1737&quot; alt=&quot;pycon2013_hashtags_usernames&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/pycon2013_hashtags_usernames-300x300.png&quot; width=&quot;300&quot; height=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;White nodes are hashtags (e.g. &lt;a href=&quot;https://twitter.com/search?q=raspberrypi&amp;amp;src=typd&quot;&gt;#raspberrypi&lt;/a&gt; centres the left white cluster), purple is for usernames (e.g. organiser &lt;a href=&quot;https://twitter.com/jessenoller&quot;&gt;@jessenoller&lt;/a&gt; is in the centre, Python&amp;#8217;s creator &lt;a href=&quot;https://twitter.com/gvanrossum&quot;&gt;@gvanrossum&lt;/a&gt; is between #raspberrypi and Jesse, &lt;a href=&quot;https://twitter.com/dabeaz&quot;&gt;@dabeaz&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/raymondh&quot;&gt;@raymondh&lt;/a&gt; are near the centre). We see a strongly connected cluster of people and hashtags along with several disconnected sets.&lt;/p&gt;
&lt;p&gt;Over the course of PyCon I&amp;#8217;ve collected all the #pycon tagged Tweets using the 1% Twitter Firehose (via a 1 line curl command). I have some Tweet parsing code which transforms this data into useful subsets (originally I was working on 2D geo-tagged plots of London and Brighton &amp;#8211; to be posted later), in this case I extract the hashtags and usernames from each tweet using &lt;a href=&quot;https://pypi.python.org/pypi/twitter-text-python/&quot;&gt;twitter-text-python&lt;/a&gt; and and then build edges in a graph for each pair of mentions that occur in a tweet. E.g.:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&amp;#8220;really cool stenography talk by @stenoknight at #PyCon &amp;#8211; she still uses #vim with #plover&amp;#8221;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;will cause a link to form between #pycon and #vim, #pycon and #plover, #vim and #plover. The width of edges in the diagram corresponds to the number of times the same hashtags (and users) are linked in each tweet. To understand which people are related to each concept I added usernames so in the above example edges are also formed between @stenoknight and the three hashtags.&lt;/p&gt;
&lt;p&gt;If you open up a larger version of the image (click the main image) you can follow some of the detail. The #raspberrypi tag is interesting &amp;#8211; lots of prominent projects are mentioned alongside (e.g. #pandas, #django). Just below the main cluster is a subcluster on #robots #vision #hackers &amp;#8211; these are joined to the main #raspberrypi cluster by the adjective #awesome (rather lovely!). All 2,500 attendees of PyCon were given a full Raspberry Pi Model B during the &lt;a href=&quot;http://www.pyvideo.org/video/1668/keynote-2&quot;&gt;Friday morning keynote&lt;/a&gt; by Eben Upton and during the weekend a RaspberryPi hacklab taught many people how to add hardware and use Python on the device.&lt;/p&gt;
&lt;p&gt;In the centre we see a lot of people &amp;#8211; many people mention each other or are linked by others (e.g. prominent speakers) in their tweets. I filter out ReTweets so we&amp;#8217;re only looking at mentions of people inside one tweet if someone has written that tweet afresh. The legendary Testing in Python Birds of a Feather session (#tipbof) on the right is linked to a few prominent folk.&lt;/p&gt;
&lt;p&gt;#openscience and #openaccess are well linked to the south of the main cluster, connected to the main group via clusters of people.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m quite intrigued by the &lt;a href=&quot;https://twitter.com/styleseat&quot;&gt;@styleseat&lt;/a&gt; link out to #nailjerks #pixiedust #nailart to the north, they ran a manicure/pedicure session in connection with #pyladies.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/pycon_tags_people2_annotated_sundayguido.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1740&quot; alt=&quot;pycon_tags_people2_annotated_sundayguido&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/pycon_tags_people2_annotated_sundayguido-300x225.png&quot; width=&quot;300&quot; height=&quot;225&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Guido gave a keynote this morning and discussed async programming &amp;#8211; a new cluster formed (see zoom from earlier analysis shown above) from yesterday&amp;#8217;s data with #tulip #sunday #pep3156 whilst talking about &lt;a href=&quot;http://www.python.org/dev/peps/pep-3156/&quot;&gt;PEP 3156&lt;/a&gt;. It is interesting to note the time-based nature of the clusters (which we can&amp;#8217;t see in this single 2D image, maybe I ought to animate it?).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; I&amp;#8217;ve added the plot below using the Community Detection feature of Gephi, it shows Guido&amp;#8217;s async tag set as a separate cluster. #raspberrypi has a nicely large cluster, web servers have their own too.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/pycon_tags_people_communities.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1744&quot; alt=&quot;pycon_tags_people_communities&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/03/pycon_tags_people_communities-300x300.png&quot; width=&quot;300&quot; height=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Due to yesterday&amp;#8217;s PyCon 5k Fun Run there&amp;#8217;s a disconnected cluster for #10minutemile #shootforthestars #ugh to the north &amp;#8211; 150 of us (of 2500 attendees) ran at 7am, we raised $7k towards cancer research.&lt;/p&gt;
&lt;p&gt;It is worth mentioning that I removed some of the more prominent nodes as many of the other topics connect to these so they add little information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;#pycon&lt;/li&gt;
&lt;li&gt;#python&lt;/li&gt;
&lt;li&gt;#pycon2013&lt;/li&gt;
&lt;li&gt;@pycon&lt;/li&gt;
&lt;li&gt;@top_webtech @inowgb (spammy)&lt;/li&gt;
&lt;li&gt;any username node with less than 50 occurrences&lt;/li&gt;
&lt;li&gt;any hashtag node with only 1 occurrence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;ll add the code to github tomorrow. Tools used include &lt;a href=&quot;https://pypi.python.org/pypi/twitter-text-python/&quot;&gt;twitter-text-python&lt;/a&gt;, &lt;a href=&quot;http://networkx.github.com/&quot;&gt;networkx&lt;/a&gt; and &lt;a href=&quot;https://gephi.org/&quot;&gt;Gephi&lt;/a&gt;. &lt;strong&gt;Update&lt;/strong&gt; the code is in github as &lt;a href=&quot;https://github.com/ianozsvald/twitter_networkx_concept_map&quot;&gt;twitter_networx_concept_map&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If I get time whilst here I&amp;#8217;ll do some more analysis on the data. I&amp;#8217;d love to use a named entity tool or some parsing to extract obvious nouns (e.g. packages and topics) that aren&amp;#8217;t #hashtagged.&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">WebSocket for CherryPy 3.2</title>
		<link href="http://www.defuze.org/archives/232-websocket-for-cherrypy-32.html"/>
		<id>http://www.defuze.org/?p=232</id>
		<updated>2013-03-17T10:41:32+00:00</updated>
		<content type="html">&lt;p&gt;Just a quick note about the first draft of support for WebSocket in &lt;a href=&quot;http://www.cherrypy.org/&quot;&gt;CherryPy&lt;/a&gt;. You can find the code &lt;a href=&quot;https://github.com/Lawouach/WebSocket-for-Python&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note that this is still work in progress but does work against Chrome and the &lt;a href=&quot;http://code.google.com/p/pywebsocket/&quot;&gt;pywebsocket&lt;/a&gt; echo client. It supports &lt;a href=&quot;http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76&quot;&gt;draft-76&lt;/a&gt; of the specification only and I&amp;#8217;m waiting for the &lt;a href=&quot;https://www.ietf.org/mailman/listinfo/hybi&quot;&gt;working-group&lt;/a&gt; to settle a bit more before making any further modification.&lt;/p&gt;
&lt;p&gt;The updated code has started integrating draft-06 as well but this is a work in progress.&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>2013-05-23T22:22:10+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Use of VirtualBox to prepare students (PyCon tutorials)</title>
		<link href="http://ianozsvald.com/2013/03/15/use-of-virtualbox-to-prepare-students-pycon-tutorials/"/>
		<id>http://ianozsvald.com/?p=1731</id>
		<updated>2013-03-15T22:22:34+00:00</updated>
		<content type="html">&lt;p&gt;Minesh and I ran a tutorial (Applied Parallel Computing) at PyCon 2013 yesterday, we&amp;#8217;ve been working on building and distributing a VirtualBox (7GB) for students to simplify the teaching with a unified, preconfigured environment. This process took a while, below are my notes. Others (e.g. &lt;a href=&quot;https://us.pycon.org/2013/schedule/presentation/65/&quot;&gt;Kat teaching SimpleCV&lt;/a&gt;) also had a VirtualBox.&lt;/p&gt;
&lt;p&gt;The upside of a VirtualBox is that everyone has a unified environment, so students see on their screen &lt;em&gt;exactly&lt;/em&gt; what you have on your screen. The downside is that this doesn&amp;#8217;t help them install the tools onto their laptop for normal use. If you&amp;#8217;re teaching a medley of tools (as we were) and especially if some require non-trivial installation (e.g. &lt;a href=&quot;http://discoproject.org/&quot;&gt;Disco&lt;/a&gt; map/reduce for us) then VirtualBoxes are a clear win.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We zipped the directory containing the VDI file, Kat used a single &lt;a href=&quot;https://en.wikipedia.org/wiki/Open_Virtualization_Format&quot;&gt;OVF&lt;/a&gt; file (both for VirtualBox), I think the single OVF file might be easier to distribute and might work in other (non-VirtualBox) environments. Our zip took 7GB down to 2.2GB&lt;/li&gt;
&lt;li&gt;Your VirtualBox will be configured for you&amp;#8230;but students might have foreign keyboards (e.g. Minesh made our VBox image with a US keyboard, I have a UK keyboard, some students have German etc keyboards) &amp;#8211; provide notes on how to reconfigure the Guest OS so the student can setup their keyboard&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;git clone&lt;/strong&gt; a read-only repo into the VBox, students can then just &lt;strong&gt;git pull&lt;/strong&gt; to get updates&lt;/li&gt;
&lt;li&gt;We added a &lt;a href=&quot;https://github.com/ianozsvald/pycon2013_applied_parallel_computing/blob/master/run_this_to_confirm_you_have_the_correct_libraries.py&quot;&gt;run_this_to_confirm_you_have_the_correct_libraries.py&lt;/a&gt; script, it checks that everything is installed, students can run this to double check that their install is good&lt;/li&gt;
&lt;li&gt;Use a standard user and password &amp;#8211; we used &amp;#8220;pycon:pycon&amp;#8221;&lt;/li&gt;
&lt;li&gt;I made a YouTube screencast using RecordMyDesktop (with desktop compositing disabled to reduce flicker)&lt;/li&gt;
&lt;li&gt;Bundle everything into a blog post that you can easily update &amp;#8211; here are our &lt;a href=&quot;http://ianozsvald.com/2013/02/18/pycon-tutorial-notes-for-applied-parallel-computing/&quot;&gt;install notes and video&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A large zip is harder to distribute &amp;#8211; I linked to the zip on my blog (I have lots of bandwidth) and created a torrent using the super-easy &lt;a href=&quot;http://burnbit.com/&quot;&gt;burnbit&lt;/a&gt; site (here&amp;#8217;s my &lt;a href=&quot;http://burnbit.com/torrent/237168/PyCON_2013_AppliedParallelComputing1_2_zip&quot;&gt;download page&lt;/a&gt;) &amp;#8211; you can see the torrent link on the install notes page linked above&lt;/li&gt;
&lt;li&gt;You probably want to use a 32 bit OS for the Guest OS (we used Linux Mint 14 32 bit), a 64 bit Guest OS won&amp;#8217;t run on a 32 bit system (but a 32 bit Guest OS will run on a 64 bit host)&lt;/li&gt;
&lt;li&gt;Despite linking our tutorial notes to the tutorial page on the PyCon website (and mailing students), many didn&amp;#8217;t have a preinstalled environment &amp;#8211; we had a set of USB Thumb Drives which simplified the setup. Our first 30 minutes was talking so students had time to install the VBox&lt;/li&gt;
&lt;li&gt;Github is a great place to store code, data (if not huge) and slides&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">django-fancy-cache with or without stats</title>
		<link href="http://www.peterbe.com/plog/django-fancy-cache-with-or-without-stats"/>
		<id>http://www.peterbe.com/plog/django-fancy-cache-with-or-without-stats</id>
		<updated>2013-03-11T01:00:00+00:00</updated>
		<content type="html">&lt;p&gt;If you use &lt;code&gt;django-fancy-cache&lt;/code&gt; you can either run &lt;strong&gt;with&lt;/strong&gt; stats or &lt;strong&gt;without&lt;/strong&gt;. With stats, you can get a number of how many times a cache key &quot;hits&quot; and how many times it &quot;misses&quot;. Keeping stats incurs a small performance slowdown. But how much?&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;I created a simple page that either keeps stats or ignores it. I ran the benchmark over Nginx and Gunicorn with 4 workers. The cache server is a memcached running on the same host (my OSX 10.7 laptop).&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;With stats:&lt;br /&gt;
&lt;/p&gt;
&lt;pre&gt;
Average: 768.6 requests/second
Median: 773.5 requests/second
Standard deviation: 14.0
&lt;/pre&gt;

&lt;p&gt;Without stats:&lt;br /&gt;
&lt;/p&gt;
&lt;pre&gt;
Average: 808.4 requests/second
Median: 816.4 requests/second
Standard deviation: 30.0
&lt;/pre&gt;

&lt;p&gt;That means, roughly that running &lt;strong&gt;with&lt;/strong&gt; stats incurs a &lt;strong&gt;6%&lt;/strong&gt; slower performance.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;The stats is completely useless to your users. The stats tool is purely for your own curiousity and something you can switch on and off easily.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Note: This benchmark assumes that the memcached server is running on the same host as the Nginx and the Gunicorn server. If there was more network in between, obviously all the &lt;code&gt;.incr()&lt;/code&gt; commands would cause more performance slowdown. &lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Yesterday’s London Python Dojo</title>
		<link href="http://ramblings.timgolden.me.uk/2013/03/08/yesterdays-london-python-dojo/"/>
		<id>http://ramblings.timgolden.me.uk/2013/03/08/yesterdays-london-python-dojo/</id>
		<updated>2013-03-08T13:26:31+00:00</updated>
		<content type="html">&lt;p&gt;Yesterday was the March Python Dojo, hosted as usual by the ever-generous &lt;a href=&quot;http://www.fry-it.com/&quot;&gt;Fry-IT&lt;/a&gt;, with a book donated by &lt;a href=&quot;http://oreilly.com/&quot;&gt;O&amp;#8217;Reilly&lt;/a&gt;. We started with a couple of not-so lightning talks from Tom Viner &amp;#8212; talking about &lt;a href=&quot;https://github.com/ldnpydojo/slider-puzzle/tree/master/team2&quot;&gt;his team&amp;#8217;s solution&lt;/a&gt; for last month&amp;#8217;s puzzle &amp;#8212; and Nicholas Tollervey &amp;#8212; talking about bittorrent. An artfully-worded late question had @ntoll on his soapbox for a while on the subject of copyright and payment to artists, until someone spoiled it by suggesting that maybe we ought to write some code in Python!&lt;/p&gt;
&lt;p&gt;After the usual, only slightly convoluted, voting experience, we decided to pick up one of last month&amp;#8217;s runner-up challenges: creating a compression-decompression algorithm. Naturally most people started from some kind of frequency table, replacing the most common items with the smallest replacement. The approaches ranged from a hybrid Huffman-UTF8 encoding to an attempt to replace common words by a $n placeholder, where the n would increase as the word became less common. The winner for the most optimistic approach was a lossy algorithm which dropped every other word on compression, replacing it on decompression by the most likely from a lookup table. Tested against a corpus of Shakespeare&amp;#8217;s works it produced some quite readable poetry.&lt;/p&gt;
&lt;p&gt;As an aside, I can assert after a wide-ranging survey that (a) the preferred editor background is dark (black or dark-grey); and (b) in spite of all the tech at their fingertips, programmers still reach for pen and paper when they need to work something out!&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>2013-06-07T12:22:13+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">pip install : Lightspeed and Bulletproof</title>
		<link href="http://tartley.com/?p=1423"/>
		<id>http://tartley.com/?p=1423</id>
		<updated>2013-03-08T09:29:09+00:00</updated>
		<content type="html">&lt;p&gt;I saw a post about &lt;a href=&quot;http://www.scottisheyes.com/how-to-fix-slow-pip-install&quot;&gt;speeding up the Python packaging command &amp;#8220;pip install&amp;#8221;&lt;/a&gt;, by specifying more responsive mirrors for querying and downloading packages. For my situation, a better tactic is this.&lt;/p&gt;
&lt;p&gt;Step one: Download all your project&amp;#8217;s dependencies into a local &amp;#8216;packages&amp;#8217; dir, but don&amp;#8217;t install them yet:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mkdir packages&lt;br /&gt;
pip install --download=packages -r requirements.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Step two, install from the &amp;#8216;packages&amp;#8217; dir:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pip install --no-index --find-links=packages -r requirements.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em id=&quot;__mceDel&quot;&gt;(The above syntax works on pip 1.3, released yesterday. Docs for older versions of pip claim to support this, but in practice, for pip 1.2, I&amp;#8217;ve had to use &amp;#8220;&lt;code&gt;--find-links=file://$PWD/packages&lt;/code&gt;&amp;#8220;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Step 2 works even if PyPI is unreachable. It works even if some of your dependencies are self-hosted by the authors, and that website is unreachable. It works even if the version you have pinned of one of your dependencies has been deleted by the author (some packages do this routinely after security updates.) It works even if you have no network connection at all. In short, it makes creation of your virtualenv bulletproof.&lt;/p&gt;
&lt;p&gt;As a nice side effect, it runs really fast, because it isn&amp;#8217;t downloading the packages across the internet, nor is it attempting to scan a remote index to check for matching or newer versions of each package. This is much quicker than just using a Pip download cache, especially for large projects with many dependencies which only change occasionally.&lt;/p&gt;
&lt;p&gt;At &lt;a href=&quot;http://rangespan.com&quot;&gt;Rangespan&lt;/a&gt;, we check the &amp;#8216;packages&amp;#8217; directory into source control, so that once you&amp;#8217;ve checked out a project&amp;#8217;s repo, you have everything you need to deploy locally and run, even if you have no network. You might choose to treat &amp;#8216;packages&amp;#8217; as ephemeral.&lt;/p&gt;
&lt;p&gt;It was pointed out to me recently by &lt;a href=&quot;https://twitter.com/jezdez&quot;&gt;@jezdez&lt;/a&gt;, Pip maintainer, this usage pattern has now been &lt;a href=&quot;http://www.pip-installer.org/en/latest/cookbook.html#fast-local-installs&quot;&gt;explicitly called out in the documentation&lt;/a&gt;, which was substantially reorganised and improved with the recent 1.3 release.&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>2013-04-25T10:22:39+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">ANN: twitter-text-python 1.0.0.2 release (Python Tweet parsing library)</title>
		<link href="http://ianozsvald.com/2013/03/07/ann-twitter-text-python-1-0-0-2-release-python-tweet-parsing-library/"/>
		<id>http://ianozsvald.com/?p=1705</id>
		<updated>2013-03-07T15:54:29+00:00</updated>
		<content type="html">&lt;p&gt;A few weeks back I took over as maintainer of the &lt;a href=&quot;https://pypi.python.org/pypi/twitter-text-python/&quot;&gt;twitter-text-python&lt;/a&gt; library (&lt;a href=&quot;https://github.com/ianozsvald/twitter-text-python&quot;&gt;source on github&lt;/a&gt;). This library lets you take a tweet like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;&quot;@ianozsvald, you now support #IvoWertzel's tweet ...
parser! https://github.com/ianozsvald/&quot;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;and extract the Twitter entities as defined in the &lt;a href=&quot;https://github.com/twitter/twitter-text-conformance&quot;&gt;Twitter conformance tests&lt;/a&gt;. The entities in the above tweet would be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;pre&gt;reply: 'ianozsvald'&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre&gt;users: ['ianozsvald']&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre&gt;tags: ['IvoWertzel']&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre&gt;urls: ['https://github.com/ianozsvald/']&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre&gt;lists: []  # no lists in this tweet&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre&gt;output html: u'&amp;lt;a href=&quot;http://twitter.com/ianozsvald&quot;&amp;gt;@ianozsvald&amp;lt;/a&amp;gt;, ...&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre&gt;  you now support &amp;lt;a href=&quot;http://search.twitter.com/search?q=%23IvoWertzel&quot;&amp;gt;#IvoWertzel&amp;lt;/a&amp;gt;\'s&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre&gt;  tweet parser! &amp;lt;a href=&quot;https://github.com/ianozsvald/&quot;&amp;gt;https://github.com/ianozsvald/&amp;lt;/a&amp;gt;'&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&amp;#8217;re parsing Tweets or status-update-like-entities (from e.g. App.net)  in Python then this library makes it easy to extract @people, URLs and #hashtags. You can also request the spans (character locations) for each entity, very useful if you have repeated phrases and you&amp;#8217;re doing a search/replace.&lt;/p&gt;
&lt;p&gt;The library is easily installed using &amp;#8220;$ pip install &lt;a href=&quot;https://pypi.python.org/pypi/twitter-text-python/&quot;&gt;twitter-text-python&lt;/a&gt;&amp;#8221; (MIT license) via the Python Package Index, currently at version 1.0.0.2.&lt;/p&gt;
&lt;p&gt;Credit &amp;#8211; the library was developed by Ivo Wertzel (&lt;a href=&quot;https://github.com/BonsaiDen/twitter-text-python&quot;&gt;BonsiaDan&lt;/a&gt; on github), I merged a few Pull requests after forking to fix some bugs and have now taken over official maintenance.&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">This site is now 100% inline CSS and no bytes are wasted</title>
		<link href="http://www.peterbe.com/plog/100-percent-inline-css"/>
		<id>http://www.peterbe.com/plog/100-percent-inline-css</id>
		<updated>2013-03-05T08:39:17+00:00</updated>
		<content type="html">&lt;p&gt;This personal blog site of mine uses &lt;a href=&quot;http://www.peterbe.com/plog/django-fancy-cache&quot;&gt;django-fancy-cache&lt;/a&gt; and &lt;a href=&quot;http://www.peterbe.com/plog/mincss&quot;&gt;mincss&lt;/a&gt;.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;What that means is that I can cache the whole output of every blog post for weeks and when I do that I can first preprocess the HTML and convert every external CSS into one inline STYLE block which will only reference selectors that are actually used.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;To see it in action, right-click and select &quot;View Page Source&quot;. You'll see something like this:&lt;br /&gt;
&lt;/p&gt;
&lt;pre&gt;
/*
Stats about using github.com/peterbe/mincss
-------------------------------------------
Requests:         1 (now: 0)
Before:           81Kb
After:            11Kb
After (minified): 11Kb
Saving:           70Kb
*/
section{display:block}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-tex...
&lt;/pre&gt;

&lt;p&gt;The reason the saving is so huge, in my case, is because I'm using &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Twitter Bootstrap&lt;/a&gt; CSS framework which is awesome but as any framework, it will inevitably contain a bunch of stuff that I don't use. Some stuff I don't use on any page at all. Some stuff is used only on some pages and some &lt;em&gt;other&lt;/em&gt; stuff is used only on some &lt;em&gt;other&lt;/em&gt; pages.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What I gain by this, is faster page loads.&lt;/strong&gt; What the browser does is that it, gets a URL, downloads all HTML, opens the HTML to look for referenced CSS (using the &lt;code&gt;link&lt;/code&gt; tag) and downloads that too. Once all of that is downloaded, it starts to render the page. Approximately after that it starts to download all referenced Javascript and starts evaluating and executing that. &lt;/p&gt;
&lt;p&gt;By not having to download the CSS the browser has one less thing to do. Only one request? Well, that request might be on a CDN (not a great idea actually) so even though it's just 1 request it will involve another DNS look-up.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Here's what the &lt;a href=&quot;http://www.webpagetest.org/result/130304_4F_ZKN/1/details/&quot;&gt;loading of the homepage&lt;/a&gt; looks like in Firefox from a US east coast IP.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Granted, a downloaded CSS file can be cached by the browser and used for other pages under the same domain. But, on my blog the bounce rate is about 90%. That doesn't necessarily mean that visitors leave as soon as they arrived, but it does mean that they generally just read one page and then leave. For those 10% of visitors who visit more than one page will have to download the same chunk of CSS more than once. But mind you, it's not always the same chunk of CSS because it's different for different pages. And the amount of CSS that is now in-line only adds about 2-3Kb on the HTML load when sent gzipped.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Getting to this point wasn't easy because I first had to develop &lt;a href=&quot;https://github.com/peterbe/mincss&quot;&gt;mincss&lt;/a&gt; and &lt;a href=&quot;https://github.com/peterbe/django-fancy-cache&quot;&gt;django-fancy-cache&lt;/a&gt; and integrate it all. However, what this means is that you can have it done &lt;strong&gt;on your site too!&lt;/strong&gt; All the code is Open Source and it's all Python and Django which are very popular tools.&lt;br /&gt;
&lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry>
		<title type="html">&quot;TDD / Django tutorial: The Book!&quot;</title>
		<link href="http://www.obeythetestinggoat.com/writing-a-book-preview.html"/>
		<id>tag:www.obeythetestinggoat.com,2013-03-03:writing-a-book-preview.html</id>
		<updated>2013-03-03T00:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;em&gt;[update April 2012] : The book is now coming out on O'Reilly!  more info here:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;reference external&quot; href=&quot;http://www.tdd-django-tutorial.com/blog/articles/2013/test-driven-development-web-applications-book-exis/&quot;&gt;http://www.tdd-django-tutorial.com/blog/articles/2013/test-driven-development-web-applications-book-exis/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Thanks so much for following on this far! I'm afraid that's all there is for
now, but I am about to start on the next stage -- a proper book on TDD for
web apps.&lt;/p&gt;
&lt;p&gt;If you've found the tutorial useful so far, I wonder whether I can solicit
some feeback regarding a book version?&lt;/p&gt;
&lt;p&gt;Here's the chapter outline I've got so far.  Now, remember, this is a very rough draft,
and it's very much bound to change, but I'd love to hear your thoughts... Especially
about some quite general questions, like:&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Am I broadly covering the right sort of stuff?&lt;/li&gt;
&lt;li&gt;Am I right to spend plenty of time talking about JavaScript, as well as Python?&lt;/li&gt;
&lt;li&gt;What should I choose as my example app?  I've written the outline as if it
were a forums app, but I'm starting to see the appeal of one of the other classic
examples, the &amp;quot;to-do list&amp;quot; (very simple at base, can be extended easily, opportunities
for sharing/social bits, plenty of stuff to do on the client-side too...).  What
would you choose as an example?&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;section&quot; id=&quot;part-1-beginning-web-app-development-with-tdd&quot;&gt;
&lt;h2&gt;PART 1 - Beginning web app development with TDD&lt;/h2&gt;
&lt;p&gt;The idea is to dive straight in with a practical example, rather than talking
a lot of theory up-front.   I had originally thought to start with a toy example
(cf these 3 abandoned chapters: &lt;a class=&quot;reference external&quot; href=&quot;http://www.tdd-django-tutorial.com/tutorial/6/&quot;&gt;http://www.tdd-django-tutorial.com/tutorial/6/&lt;/a&gt; ),
but I decided that people prefer real practical stuff to toy examples...&lt;/p&gt;
&lt;p&gt;I also want the first few chapters to be very short + bit-sized, so that the
reader feels like they're really making progress quickly... (the inspiration
comes from Kent Beck's TDD by Example, an awesome book)&lt;/p&gt;
&lt;p&gt;Essentially part 1 is a re-hash of this online tutorial, using a differnt example
app...&lt;/p&gt;
&lt;div class=&quot;section&quot; id=&quot;our-first-functional-test-with-selenium&quot;&gt;
&lt;h3&gt;1: Our first functional test with Selenium&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Briefly discuss difference between functional testing (AKA acceptance
testing, integration testing, whatever) and unit testing&lt;/li&gt;
&lt;li&gt;Write first test - Introduce Selenium, &lt;cite&gt;setUp&lt;/cite&gt;, &lt;cite&gt;tearDown&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;Demonstrate we can get it to open a web browser, and navigate to a web page
eg - google.com&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;getting-django-set-up-and-running&quot;&gt;
&lt;h3&gt;2: Getting Django set-up and running&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Change our test to look for the test server&lt;/li&gt;
&lt;li&gt;Switch to Django LiveServerTestCase. Explain&lt;/li&gt;
&lt;li&gt;Get the first test running and failing for a sensible reason&lt;/li&gt;
&lt;li&gt;Create django project &lt;cite&gt;django-admin.py startproject&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;It worked!&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;a-static-front-page&quot;&gt;
&lt;h3&gt;3: A static front page&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Look for &amp;quot;Welcome to the Forums&amp;quot;, or similar&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;urls.py&lt;/cite&gt;, &lt;cite&gt;direct_to_template&lt;/cite&gt; ?&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;super-users-and-the-django-admin-site&quot;&gt;
&lt;h3&gt;4: Super-users and the Django admin site&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Extend FT to try and log in&lt;/li&gt;
&lt;li&gt;Explain the admin site&lt;/li&gt;
&lt;li&gt;Database setup, &lt;cite&gt;settings.py&lt;/cite&gt;, &lt;cite&gt;syncdb&lt;/cite&gt;, &lt;cite&gt;admin.py&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;runserver&lt;/cite&gt; to show login code&lt;/li&gt;
&lt;li&gt;Explain difference between test database and real database&lt;/li&gt;
&lt;li&gt;Fixtures&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;first-unit-tests-and-database-model&quot;&gt;
&lt;h3&gt;5: First unit tests and Database model&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Distinction between unit tests and functional tests&lt;/li&gt;
&lt;li&gt;Extend FT to try and create a new topic&lt;/li&gt;
&lt;li&gt;new app&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;models.py&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;test/code cycle&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;testing-a-view&quot;&gt;
&lt;h3&gt;6: Testing a view&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;urls.py again&lt;/li&gt;
&lt;li&gt;Test view as a function&lt;/li&gt;
&lt;li&gt;assert on string contents&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;django-s-template-system&quot;&gt;
&lt;h3&gt;7: Django's template system&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Introduce template syntax&lt;/li&gt;
&lt;li&gt;Keep testing as a function&lt;/li&gt;
&lt;li&gt;The, introduce the Django Test Client&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;reflections-what-to-test-what-not-to-test&quot;&gt;
&lt;h3&gt;8: Reflections: what to test, what not to test&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;time for a bit of theory/philosophy&lt;/li&gt;
&lt;li&gt;&amp;quot;Don't test constants&amp;quot;&lt;/li&gt;
&lt;li&gt;Test logic&lt;/li&gt;
&lt;li&gt;Tests for simple stuff should be simple, so not much effort&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;simple-forms&quot;&gt;
&lt;h3&gt;9: Simple Forms&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Manually coded HTML&lt;/li&gt;
&lt;li&gt;Refactor test classes&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;user-authentication&quot;&gt;
&lt;h3&gt;10: User Authentication&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Sign up, login/logout&lt;/li&gt;
&lt;li&gt;Email?&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;more-advanced-forms&quot;&gt;
&lt;h3&gt;11: More advanced forms&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Use Django Forms classes&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;on-refactoring&quot;&gt;
&lt;h3&gt;12: On Refactoring&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Martin Fowler&lt;/li&gt;
&lt;li&gt;Tests critical&lt;/li&gt;
&lt;li&gt;Methodical process - explain step by step&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;pagination&quot;&gt;
&lt;h3&gt;13: Pagination&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Extend various old unit tests and FTs&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;part-2-more-advanced-testing-for-a-more-advanced-site&quot;&gt;
&lt;h2&gt;PART 2: More advanced testing for a more advanced site&lt;/h2&gt;
&lt;div class=&quot;section&quot; id=&quot;notifications&quot;&gt;
&lt;h3&gt;14: Notifications&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Django Notifications, for post edits&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;adding-style-with-markdown&quot;&gt;
&lt;h3&gt;15: Adding style with MarkDown&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Using an external library&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;switching-to-oauth-mocking&quot;&gt;
&lt;h3&gt;16: Switching to OAuth: Mocking&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&amp;quot;Don't store passwords&amp;quot;&lt;/li&gt;
&lt;li&gt;Discuss challenges of external dependencies&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;getting-dynamic-testing-javascript-part-1&quot;&gt;
&lt;h3&gt;17: Getting Dynamic: Testing Javascript part 1&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Simple input validation&lt;/li&gt;
&lt;li&gt;Choose JS unit testing framework (probably Qunit, or YUI)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;testing-javascript-part-2-ajax&quot;&gt;
&lt;h3&gt;18: Testing Javascript part 2 - Ajax&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Dynamic previews of post input&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;getting-pretty-bootstrap&quot;&gt;
&lt;h3&gt;19: Getting pretty: Bootstrap&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Bring in nicer UI elements&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;getting-pretty-gravatar&quot;&gt;
&lt;h3&gt;20: Getting pretty: Gravatar&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;pictures for users&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;part-3-getting-seriously-sexy&quot;&gt;
&lt;h2&gt;PART 3: Getting seriously sexy&lt;/h2&gt;
&lt;div class=&quot;section&quot; id=&quot;getting-serious-about-the-client-side-single-page-website&quot;&gt;
&lt;h3&gt;21: Getting serious about the client-side + single-page website?&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Introduce one of the client-side js frameworks -- backbone.js / ember.js / angular&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;switching-databases-1-postgresql&quot;&gt;
&lt;h3&gt;22: Switching Databases 1: PostgreSQL&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;show how Django makes this easy&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;websockets-and-async-on-the-server-side&quot;&gt;
&lt;h3&gt;23: Websockets and Async on the server-side&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;we want dynamic notifications of when new posts appear on a thread we're
looking at&lt;/li&gt;
&lt;li&gt;Need to spin up, Tornado/Twisted/Gevent as well as Django LiveServerTestCase&lt;/li&gt;
&lt;li&gt;FT opens multiple browser tabs in parallel&lt;/li&gt;
&lt;li&gt;Big change!&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;switching-databases-2-nosql-and-mongodb&quot;&gt;
&lt;h3&gt;24: Switching Databases 2: NoSQL and MongoDB&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;obligatory discussion of NoSQL and MongoDB&lt;/li&gt;
&lt;li&gt;descrine installation, particularities of testing&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;continuous-integration&quot;&gt;
&lt;h3&gt;26: Continuous Integration&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Need to build 3 server types&lt;/li&gt;
&lt;li&gt;Jenkins (or maybe buildbot)&lt;/li&gt;
&lt;li&gt;Need to adapt Fts, maybe rely less on LiveServerTestCase&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;caching-for-screamingly-fast-performance&quot;&gt;
&lt;h3&gt;27: Caching for screamingly fast performance&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;unit testing &lt;cite&gt;memcached&lt;/cite&gt;&lt;/li&gt;
&lt;li&gt;Functionally testing performance&lt;/li&gt;
&lt;li&gt;Apache &lt;cite&gt;ab&lt;/cite&gt; testing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Well, that's what I have so far.  What do you think?  Have I missed anything
out?  Does anything seem superfluous?  Most importantly, would you buy it?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</content>
		<author>
			<name>Harry</name>
			<uri>http://www.obeythetestinggoat.com/</uri>
		</author>
		<source>
			<title type="html">Obey the Testing Goat!</title>
			<link rel="self" href="http://www.obeythetestinggoat.com/feeds/all.atom.xml"/>
			<id>http://www.obeythetestinggoat.com/</id>
			<updated>2013-06-10T20:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Welcome to the world django-fancy-cache!</title>
		<link href="http://www.peterbe.com/plog/django-fancy-cache"/>
		<id>http://www.peterbe.com/plog/django-fancy-cache</id>
		<updated>2013-03-01T19:01:47+00:00</updated>
		<content type="html">&lt;p&gt;&lt;strong&gt; A Django cache_page on steroids&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Django ships with an awesome view decorator called &lt;a href=&quot;https://docs.djangoproject.com/en/1.5/topics/cache/#django.views.decorators.cache.cache_page&quot;&gt;cache_page&lt;/a&gt; which is awesome. But a bit basic too.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;What it does is that it stores the whole view response in memcache and the key to it is the URL it was called with  including any query string. All you have to do is specify the length of the cache timeout and it just works.&lt;br /&gt;
Now, it's got some shortcomings which &lt;code&gt;django-fancy-cache&lt;/code&gt; upgrades. These &quot;steroids&quot; are:&lt;br /&gt;
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ability to override the key prefix with a callable.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Ability to remember every URL that was cached so you can do invalidation by a URL pattern.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Ability to modify the response before it's stored in the cache.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Ability to ignore certain query string parameters that don't actually affect the view but does yield a different cache key.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Ability to serve from cache but always do one last modification to the response.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Incrementing counter of every hit and miss to satisfy your statistical curiosity needs.&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The documentation is here:&lt;br /&gt;
&lt;a href=&quot;https://django-fancy-cache.readthedocs.org/&quot;&gt;https://django-fancy-cache.readthedocs.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see it in a real world implementation by seeing how it's used on &lt;a href=&quot;https://github.com/peterbe/django-peterbecom/blob/master/apps/homepage/views.py&quot;&gt;my blog here&lt;/a&gt;. You basically use it like this::&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;fancy_cache&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cache_page&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@cache_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;myview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'template.html'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What I'm doing with it here on my blog is that I make the full use of caching on each blog post but as soon as a new comment is posted, I wipe the cache by basically creating a new key prefix. That means that pages are never cache stale but the views never have to generate the same content more than once.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;I'm also using &lt;code&gt;django-fancy-cache&lt;/code&gt; to do some optimizations on the output before it's stored in cache. &lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">mincss version 0.8 is much much faster</title>
		<link href="http://www.peterbe.com/plog/mincss-0.8"/>
		<id>http://www.peterbe.com/plog/mincss-0.8</id>
		<updated>2013-02-27T07:59:22+00:00</updated>
		<content type="html">&lt;p&gt;Remember &lt;a href=&quot;http://www.peterbe.com/plog/mincss&quot;&gt;mincss&lt;/a&gt; from last month? Well, despite it's rather crazy version number has only really had one major release. And it's never really been optimized.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;So I took some metrics and was able to find out where all the time is spent. It's basically in this:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bodies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CSSSelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That in itself, on its own, is very fast. Just a couple of milliseconds. But the problem was that it happens so god damn often!&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;So, in version 0.8 it now, by default, first make a list (actually, a set) of every ID and every CLASS name in every node of every HTML document. Then, using this it gingerly tries to avoid having to use &lt;code&gt;CSSSelector(selector)&lt;/code&gt; if the selector is quite simple. For example, if the selector is &lt;code&gt;#container form td:last-child&lt;/code&gt; and if there is no node with id &lt;code&gt;container&lt;/code&gt; then why bother.&lt;br /&gt;
It equally applies the same logic to classes.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;And now, what you've all been waiting for; the results:&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;On a big document (20Kb) like &lt;a href=&quot;http://www.peterbe.com/&quot;&gt;my home page&lt;/a&gt;...&lt;br /&gt;
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;BEFORE:&lt;/strong&gt;  4.7 seconds&lt;br /&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AFTER:&lt;/strong&gt; 0.85 seconds&lt;br /&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(I ran it a bunch of times and averaged the times which had very little deviation)&lt;/p&gt;
&lt;p&gt;So in the first round of optimization it suddenly becomes &lt;strong&gt;500% faster&lt;/strong&gt;. Pretty cool!&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;I've made it possible to switch this off just because I haven't yet tested it on equally many sites. All the unit tests pass of course. &lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">PyCon Tutorial Notes for Applied Parallel Computing</title>
		<link href="http://ianozsvald.com/2013/02/18/pycon-tutorial-notes-for-applied-parallel-computing/"/>
		<id>http://ianozsvald.com/?p=1677</id>
		<updated>2013-02-18T22:43:44+00:00</updated>
		<content type="html">&lt;p&gt;This post is for students of the &lt;a href=&quot;https://us.pycon.org/2013/schedule/presentation/27/&quot;&gt;Applied Parallel Computing&lt;/a&gt; &lt;a href=&quot;http://ianozsvald.com/2013/02/10/applied-parallel-computing-at-pycon-2013-march/&quot;&gt;tutorial&lt;/a&gt; that Minesh B. Amin and I will run during March 2013 at &lt;a href=&quot;https://us.pycon.org/2013/&quot;&gt;PyCon&lt;/a&gt;.This is a wiki-post, I&amp;#8217;ll update it over the next month. If you are attending the tutorial you &lt;em&gt;must&lt;/em&gt; check this post in the run-up to the tutorial. Important notes are below for you to read now. This is linked to from &lt;a href=&quot;https://us.pycon.org/2013/community/tutorials/27/&quot;&gt;our PyCon Tutorial Support&lt;/a&gt; page.&lt;/p&gt;
&lt;p&gt;If you come to this after the tutorial you&amp;#8217;ll probably find this useful for setup. The following is for my students:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check this post before you come to PyCon, you will be expected to have followed instructions and installed the software and updates &lt;em&gt;before&lt;/em&gt; the tutorial&lt;/li&gt;
&lt;li&gt;You won&amp;#8217;t have time to install/setup during the tutorial, you &lt;em&gt;must&lt;/em&gt; arrive prepared, we have a lot to work through and we&amp;#8217;ll start immediately&lt;/li&gt;
&lt;li&gt;Accepting that the PyCon wifi has been great in past years you &lt;em&gt;must&lt;/em&gt; &lt;em&gt;assume&lt;/em&gt; that wifi will be broken &amp;#8211; come prepared with a fully working environment&lt;/li&gt;
&lt;li&gt;We &lt;strong&gt;recommend strongly&lt;/strong&gt; that you use our &lt;a href=&quot;https://www.virtualbox.org/&quot;&gt;VirtualBox&lt;/a&gt; (it has all the libs and the github repo pre-installed, it is open source, it&amp;#8217;ll run on Win/Mac/Linux), if you install your own package set then we can&amp;#8217;t help you if it doesn&amp;#8217;t work as expected (it is also quite fiddly to setup yourself) &amp;#8211; you can of course buddy-up with someone else during the tutorial if required&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You will be able to get the VirtualBox (about 7GB GB) from this post in the next week, you&amp;#8217;ll be better off using the torrent that we&amp;#8217;ll provide (please seed if you can, if possible all the way until the tutorial runs to help fellow students).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Download link for VirtualBox (required!) for the tutorial: &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;(v1.1 torrent deleted as it didn&amp;#8217;t run cleanly on Macs)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://burnbit.com/torrent/237168/PyCON_2013_AppliedParallelComputing1_2_zip&quot;&gt;PyCON-2013_AppliedParallelComputing1.2.zip&lt;/a&gt; torrent (very robust &amp;#8211; resume if download breaks, 2.2GB zip decompresses to 6.9GB) or via &lt;a href=&quot;http://ianozsvald.com/wp-content/PyCON-2013_AppliedParallelComputing1.2.zip&quot;&gt;direct&lt;/a&gt; download (more brittle &amp;#8211; no resume if the download breaks).&lt;/p&gt;
&lt;p&gt; &lt;a class=&quot;burnbit_torrent&quot;&gt;&lt;/a&gt;&lt;br /&gt;
 &lt;/p&gt;
&lt;p&gt;md5sum: ce43b52a18ca913e62842ae72cc8df74&lt;/p&gt;
&lt;p&gt;NOTE &amp;#8211; I had the v1.1 version linked in the torrent above for a few days &amp;#8211; if you got that and you can&amp;#8217;t start the VirtualBox, just right-click in VirtualBox and discard the saved state, then restart the image. If you have the v1.2 version (linked as of March 4th) then you&amp;#8217;re fine.&lt;/p&gt;
&lt;p&gt;Video &amp;#8211; this &lt;a href=&quot;http://youtu.be/4sxeXPo0sL4&quot;&gt;YouTube Video Demo&lt;/a&gt; (7 minutes) shows you how to install the image.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Instructions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Unzip to a directory with 7GB of disk space (MAC USERS &amp;#8211; the built-in unzip doesn&amp;#8217;t seem to handle 64 bit files, use &lt;a href=&quot;http://www.7-zip.org/download.html&quot;&gt;7zip&lt;/a&gt; for success [maybe Windows users too?])&lt;/li&gt;
&lt;li&gt;Open &lt;a href=&quot;https://www.virtualbox.org/&quot;&gt;VirtualBox&lt;/a&gt; (optional but useful &amp;#8211; add the &lt;a href=&quot;https://www.virtualbox.org/wiki/Downloads&quot;&gt;extension pack&lt;/a&gt; for host integration)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Machine | Add&lt;/em&gt; and open the directory that contains the .vdi and .vbox files&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Start&lt;/em&gt; the machine, it&amp;#8217;ll boot to the Linux desktop&lt;/li&gt;
&lt;li&gt;Open the web link on the Desktop if you want to see the latest version of this blog post&lt;/li&gt;
&lt;li&gt;Double click the &amp;#8220;Download GITHUB Repo&amp;#8221; script on the desktop and it&amp;#8217;ll refresh the repository (in case we&amp;#8217;ve added new code)&lt;/li&gt;
&lt;li&gt;Familiarise yourself with the environment (Linux Mint 14), GTK Vim and emacs are installed&lt;/li&gt;
&lt;li&gt;Open a terminal and run &lt;em&gt;./pycon2013_applied_parallel_computing/run_this_to_confirm_you_have_the_correct_libraries.py&lt;/em&gt; (from the home directory) which confirms to you that the necessary Python libraries are installed (I&amp;#8217;ve done this, you can do it for confirmation)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The VirtualBox is a fully configured &lt;a href=&quot;http://www.linuxmint.com/&quot;&gt;Linux Mint 14&lt;/a&gt; 32 bit (based on Ubuntu 12.10) distribution, with gui, also with gvim installed. Feel free to add anything else. You don&amp;#8217;t need to bother installing further system updates, the OS was up to date when we released it. It is configured to provide 2 CPUs and 3GB RAM &amp;#8211; you might need to reduce these figures to get it running on your machine.&lt;/p&gt;
&lt;p&gt;It runs on my 64 bit laptop (Linux Mint 13 64 bit) and on 32 bit machines, it should work equally well on Windows and Mac (we&amp;#8217;ve tested it on both). You should install the Guest Additions (when the Ubuntu installation has booted use the Devices menu at the top of the VirutalBox window and &amp;#8220;install guest additions&amp;#8221; &amp;#8211; this installs integration features like copy/paste with your host OS) as they provide things like shared clipboard to the host machine.&lt;/p&gt;
&lt;p&gt;Instructions if you can&amp;#8217;t/won&amp;#8217;t use our VirtualBox (but you&amp;#8217;re on your own in this case):&lt;/p&gt;
&lt;p&gt;You can get the &lt;a href=&quot;https://github.com/ianozsvald/pycon2013_applied_parallel_computing&quot;&gt;github repo here&lt;/a&gt; &amp;#8211; if you set this up yourself then we can&amp;#8217;t offer help if it doesn&amp;#8217;t work (go to the relevant forums and ask there). There is a test script in the root of the repo (&lt;a href=&quot;https://github.com/ianozsvald/pycon2013_applied_parallel_computing/blob/master/run_this_to_confirm_you_have_the_correct_libraries.py&quot;&gt;run_this_to_confirm_you_have_the_correct_libraries.py&lt;/a&gt;) which will confirm if you have the right libraries installed (it only checks for the presence of Disco, it doesn&amp;#8217;t confirm that it is configured correctly). The &lt;a href=&quot;https://github.com/ianozsvald/pycon2013_applied_parallel_computing/blob/master/README.md&quot;&gt;README&lt;/a&gt; will give you some guidance but we really recommend that you get our VirtualBox (to be released in the next week via this post).&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Monitoring Audio Levels with PulseAudio</title>
		<link href="http://freshfoo.com/blog/pulseaudio_monitoring"/>
		<id>http://freshfoo.com/blog/2013/02/10/pulseaudio_monitoring</id>
		<updated>2013-02-10T22:05:00+00:00</updated>
		<content type="html">&lt;p&gt;I'm working on driving an analog &lt;a class=&quot;reference external&quot; href=&quot;http://en.wikipedia.org/wiki/VU_meter&quot;&gt;VU meter&lt;/a&gt; from my &lt;a class=&quot;reference external&quot; href=&quot;http://www.raspberrypi.org/&quot;&gt;Raspberry Pi&lt;/a&gt;
using whatever audio is going out the Pi's sound outputs. The de facto
Linux sound system, &lt;a class=&quot;reference external&quot; href=&quot;http://www.freedesktop.org/wiki/Software/PulseAudio&quot;&gt;PulseAudio&lt;/a&gt;, allows any sound output (or &amp;quot;sink&amp;quot;
in PulseAudio's nonclementure) to be monitored. In PulseAudio land,
each sink has a corresponding &amp;quot;source&amp;quot; called the monitor source which
can be read just like any other other PulseAudio input such as a
microphone. In fact, to help with volume meter style applications,
PulseAudio even allows you to ask for peak level measurements, which
means you can sample the monitor sink at a low frequency, with low
CPU utilisation, but still produce a useful volume display. When this
feature is used, each sample read indicates the peak level since the
last sample.&lt;/p&gt;
&lt;a href=&quot;http://freshfoo.com/blog/pulseaudio_monitoring&quot;&gt;Read more...&lt;/a&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>2013-06-19T00:22:11+00:00</updated>
			<rights type="html">Copyright 2009 Menno Smits</rights>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Applied Parallel Computing at PyCon 2013 (March)</title>
		<link href="http://ianozsvald.com/2013/02/10/applied-parallel-computing-at-pycon-2013-march/"/>
		<id>http://ianozsvald.com/?p=1663</id>
		<updated>2013-02-10T13:28:13+00:00</updated>
		<content type="html">&lt;p&gt;Minesh B. Amin (&lt;a href=&quot;http://www.mbasciences.com/&quot;&gt;MBA Sciences&lt;/a&gt;) and I (&lt;a href=&quot;http://morconsulting.com/&quot;&gt;Mor Consulting&lt;/a&gt;) are teaching &lt;a href=&quot;https://us.pycon.org/2013/schedule/presentation/27/&quot;&gt;Applied Parallel Computing&lt;/a&gt; at &lt;a href=&quot;https://us.pycon.org/2013/&quot;&gt;PyCon&lt;/a&gt; in San Jose in just over a month, here&amp;#8217;s an outline of the tutorial. The conference is sold out but there&amp;#8217;s still tickets for the tutorials (note that they&amp;#8217;re selling quickly too).&lt;/p&gt;
&lt;p&gt;Typically a recording of the tutorial is released a couple of months after PyCon to &lt;a href=&quot;http://pyvideo.org/&quot;&gt;PyVideo&lt;/a&gt; &amp;#8211; you miss out on the networking but you can at least catch up on the material. The source code will also be released.&lt;/p&gt;
&lt;p&gt;Our tutorial uses a lot of tools so we&amp;#8217;re providing a VirtualBox image (32 bit requiring about 5GB of disk space, runs on Win/Lin/Mac). Those who choose not to use the VBox image will have to install the requirements themselves, for some parts this is a bit tough so we strong recommend using the VBox image. Details of the image will be provided to students a few weeks before the conference.&lt;/p&gt;
&lt;p&gt;Parts of my tutorial build on my PyCon 2012 &lt;a href=&quot;http://ianozsvald.com/2012/03/18/high-performance-python-1-from-pycon-2012-slides-video-src/&quot;&gt;High Performance Python 1&lt;/a&gt; tutorial. You might also be interested in the (slightly vague!) idea I have of writing a book on these topics &amp;#8211; if so you should add your name to my &lt;a href=&quot;http://eepurl.com/neIw5&quot;&gt;High Performance Python Mailing List&lt;/a&gt; (it is an announce list for when/if I make progress on this project, very lightweight).&lt;/p&gt;
&lt;p&gt;This year&amp;#8217;s 3 hour tutorial is split into five sections:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Types of parallelism&lt;/li&gt;
&lt;li&gt;Hard-won lessons in building reliable/debuggable/extensible parallel systems&lt;/li&gt;
&lt;li&gt;&amp;#8220;List of tasks&amp;#8221; &amp;#8211; solving a Mandelbrot task using multiprocessing (single machine), parallelpython (can run multi-machine), redis queue (multi machine and language)&lt;/li&gt;
&lt;li&gt;&amp;#8220;Map/reduce&amp;#8221; &amp;#8211; investigating and understanding a set of Tweets using Disco, practical guide to configuration, visualisation with word-cloud and matplotlib, possibly moving on to social network connectivity analysis and visualisation&lt;/li&gt;
&lt;li&gt;&amp;#8220;Hyperparameter optimisation&amp;#8221; &amp;#8211; solving a many-paramemter optimisation problem whose parameter space is not fixed at the start of the run&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;During the Mandelbrot solver we&amp;#8217;ll look at where the complexity lies in generating an image like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/02/big_3d_cutdown_800x600.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1664&quot; alt=&quot;Mandelbrot Surface&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/02/big_3d_cutdown_800x600-300x195.png&quot; width=&quot;300&quot; height=&quot;195&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;During the Disco problem we&amp;#8217;ll visualise the results using Andreas&amp;#8217; word-cloud tool, we may also cover the use of map/reduce for social network exploration:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ianozsvald.com/wp-content/uploads/2013/02/output_apple.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1665&quot; alt=&quot;Word-cloud of Apple mentions&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2013/02/output_apple-300x225.png&quot; width=&quot;300&quot; height=&quot;225&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Install requirements will be announced closer to the tutorial along with the (recommended!) VirtualBox image. I&amp;#8217;m probably providing more material than we can cover for my two sections (Mandelbrot, Disco &amp;#8211; how far we get depends on the size and capabilities of the class), all the material will be provided for keen students to continue and we&amp;#8217;ll run an after-class session for those with more questions.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">mincss now support PhantomJS</title>
		<link href="http://www.peterbe.com/plog/mincss-now-support-phantomjs"/>
		<id>http://www.peterbe.com/plog/mincss-now-support-phantomjs</id>
		<updated>2013-02-02T18:33:50+00:00</updated>
		<content type="html">&lt;p&gt;Remember &lt;a href=&quot;http://www.peterbe.com/plog/mincss&quot;&gt;mincss&lt;/a&gt; from a couple of days ago? Now it supports downloading the HTML, to analyze, using &lt;a href=&quot;http://phantomjs.org/&quot;&gt;PhantomJS&lt;/a&gt;. That's pretty exciting because PhantomJS actually supports Javascript. It's a headless (a web browser without a graphical user interface) Webkit engine. What mincss does is that invokes a simple script like this:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'webpage'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;phantom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;phantom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;which will allow any &lt;code&gt;window.onload&lt;/code&gt; events to fire which might create more DOM nodes. So, like in &lt;a href=&quot;https://github.com/peterbe/mincss/blob/2d4e806c32480694b748a5e187491a8c327b4e75/example/page.html#L18&quot;&gt;this example&lt;/a&gt; it'll spit out HTML that contains a &lt;code&gt;&amp;lt;p class=&quot;bar&quot;&amp;gt;&lt;/code&gt; tag which you otherwise wouldn't get with Python's &lt;code&gt;urllib.urlopen()&lt;/code&gt;.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;The feature was just added (&lt;a href=&quot;http://pypi.python.org/pypi/mincss/0.6.0&quot;&gt;version 0.6.0&lt;/a&gt;) and I wouldn't be surprised if there are dragons there because I haven't tried it on a lot of sites. And at the time of writing, I was not able to compile it on my Ubuntu 64bit server so I haven't put it into production yet.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Anyway, with this you can hopefully sprinkle &lt;em&gt;less&lt;/em&gt; of those &lt;code&gt;/* no mincss */&lt;/code&gt; comments into you CSS.&lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">mincss in action - sample report from the wild</title>
		<link href="http://www.peterbe.com/plog/mincss-in-action"/>
		<id>http://www.peterbe.com/plog/mincss-in-action</id>
		<updated>2013-01-22T02:56:16+00:00</updated>
		<content type="html">&lt;p&gt;First of all, to find out what &lt;code&gt;mincss&lt;/code&gt; is &lt;a href=&quot;http://www.peterbe.com/plog/mincss&quot;&gt;read this blog post&lt;/a&gt; which explains what the heck this new Python tool is.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;My personal website is an ideal candidate for using &lt;code&gt;mincss&lt;/code&gt; because it uses an un-customized Bootstrap CSS which weighs over 80Kb (minified) and on every page hit, the rendered HTML is served directly from memcache so dynamic slowness is not a problem. With that, what I can do is run &lt;code&gt;mincss&lt;/code&gt; just before the rendered (from Django) output HTML is stored in memcache. Also, what I can do is take ALL inline &lt;code&gt;style&lt;/code&gt; blocks and all &lt;code&gt;link&lt;/code&gt; tags and combine them into &lt;em&gt;one&lt;/em&gt; big inline &lt;code&gt;style&lt;/code&gt; block. That means that I can reduce any additional HTTP connections needed down to zero! Remember, &quot;Minimize HTTP Requests&quot; is &lt;a href=&quot;http://developer.yahoo.com/performance/rules.html&quot;&gt;the number one web performance optimization rule&lt;/a&gt;.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;To get a preview of that, compare &lt;a href=&quot;http://www.peterbe.com/about&quot;&gt;http://www.peterbe.com/about&lt;/a&gt; with &lt;a href=&quot;http://www.peterbe.com/about3&quot;&gt;http://www.peterbe.com/about3&lt;/a&gt;. Visually no difference. But view the source :)&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Before:&lt;br /&gt;
&lt;a href=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/3c/2f/3c2f973896bf19cdda2b242a966a3e6f.jpg&quot; title=&quot;Document size: Before&quot;&gt;&lt;img src=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/17/f9/17f9e18f39cd58fd919e36e771f6edea.jpg&quot; alt=&quot;Document size: Before&quot; width=&quot;100&quot; height=&quot;58&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;After:&lt;br /&gt;
&lt;a href=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/00/db/00dba7ac2db21d245b8f89021afed1b6.jpg&quot; title=&quot;Document size: After&quot;&gt;&lt;img src=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/ed/c3/edc399e606ba4aebfca2a296cbae4a54.jpg&quot; alt=&quot;Document size: After&quot; width=&quot;100&quot; height=&quot;57&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Voila! &lt;strong&gt;One HTTP request less and 74Kb less!&lt;/strong&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Now, as if that wasn't good enough, let's now take into account that the browser won't start rendering the page until the HTML and ALL CSS is &quot;downloaded&quot; and parsed. Without further ado, let's look at how much faster this is now:&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Before:&lt;br /&gt;
&lt;a href=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/f4/fe/f4fe7ecae0b6caa48b1f52a582484e5a.jpg&quot; title=&quot;Waterfall view: Before&quot;&gt;&lt;img src=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/6f/a8/6fa8a2db3c836032f520c1d44e940463.jpg&quot; alt=&quot;Waterfall view: Before&quot; width=&quot;100&quot; height=&quot;59&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.webpagetest.org/result/130121_H_1MQ/1/details/&quot;&gt;report&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After:&lt;br /&gt;
&lt;a href=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/03/5f/035fd8642dd9bee5e3565760c8c042fa.jpg&quot; title=&quot;Waterfall view: After&quot;&gt;&lt;img src=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/8b/27/8b2786657b1cccb8ac26ab858c3ea068.jpg&quot; alt=&quot;Waterfall view: After&quot; width=&quot;100&quot; height=&quot;55&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.webpagetest.org/result/130121_K_1Q3/1/details/&quot;&gt;report&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;How cool is that! The &quot;Start Render&quot; event is fired after &lt;strong&gt;0.4 seconds&lt;/strong&gt; instead of &lt;strong&gt;2 seconds&lt;/strong&gt;!&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Note how the &quot;Content Download&quot; isn't really changing. That's because no matter what the CSS is, there's still a tonne of images yet to download.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;That example page is interesting too because it contains a piece of Javascript that is fired on the &lt;code&gt;window.onload&lt;/code&gt; that creates little permalink links into the document and the CSS it needs is protected thanks to the &lt;code&gt;/* no mincss */&lt;/code&gt; trick as &lt;a href=&quot;https://github.com/peterbe/django-peterbecom/blob/master/apps/homepage/templates/homepage/about.html#L14-L23&quot;&gt;you can see here&lt;/a&gt;.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;The code that actually implements &lt;code&gt;mincss&lt;/code&gt; &lt;a href=&quot;https://github.com/peterbe/django-peterbecom/blob/master/apps/homepage/views.py#L403&quot;&gt;here&lt;/a&gt; is still very rough and is going to need some more polishing up until I publish it further.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Anyway, I'm really pleased with the results. I'm going to tune the implementation a bit further and eventually apply this to all pages here on my blog. Yes, I understand that the CSS, if implemented as a &lt;code&gt;link&lt;/code&gt;, can be reused thanks to the browser's cache but visitors of my site rarely check out more than one page. In fact, the number of &quot;pages per visit&quot; on my blog is 1.17 according to Google Analytics. Even if this number was bigger I still think it would be a significant web performance boost.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/souders&quot;&gt;Steve Souders&lt;/a&gt; points out a flaw in the test. See his full comment below. Basically, what appears to happen in the &lt;a href=&quot;http://www.webpagetest.org/result/130121_H_1MQ/1/details/&quot;&gt;first report&lt;/a&gt;, IE8 downlads the file &lt;code&gt;c98c3dfc8525.css&lt;/code&gt; &lt;strong&gt;twice&lt;/strong&gt; even though it returns as a 200 the first time. No wonder that delays the &quot;Start Render&quot; time. &lt;/p&gt;
&lt;p&gt;So, I re-ran the test with Firefox instead (still from the US East coast):&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Before:&lt;br /&gt;
&lt;a href=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/81/57/815773204d5fabb2250581d32858717e.jpg&quot; title=&quot;WebpageTest before (Firefox)&quot;&gt;&lt;img src=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/6b/50/6b5061a792db74b110b76c2708560d56.jpg&quot; alt=&quot;WebpageTest before (Firefox)&quot; width=&quot;100&quot; height=&quot;59&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.webpagetest.org/result/130123_VF_KYG/&quot;&gt;report&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After:&lt;br /&gt;
&lt;a href=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/42/9d/429d3a1a79fdb9645dea03f7a964073d.jpg&quot; title=&quot;WebpageTest after (Firefox)&quot;&gt;&lt;img src=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/55/8b/558b64fda56304b77c8e811ca795a156.jpg&quot; alt=&quot;WebpageTest after (Firefox)&quot; width=&quot;100&quot; height=&quot;55&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.webpagetest.org/result/130123_CY_KYV/&quot;&gt;report&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That still shows a performance boost from &lt;strong&gt;1.4 seconds&lt;/strong&gt; down to &lt;strong&gt;0.6 seconds&lt;/strong&gt; when run using Firefox.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Perhaps it's a bug in Webpagetest or perhaps it's simply how IE8 works. In a sense it &quot;simulates&quot; the advantages of reducing the dependency on extra HTTP requests.&lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">mincss &quot;Clears the junk out of your CSS&quot;</title>
		<link href="http://www.peterbe.com/plog/mincss"/>
		<id>http://www.peterbe.com/plog/mincss</id>
		<updated>2013-01-21T03:56:45+00:00</updated>
		<content type="html">&lt;p&gt;A project I started before Christmas (i.e. about a month ago) is now production ready.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://pypi.python.org/pypi/mincss&quot;&gt;mincss&lt;/a&gt; (&lt;a href=&quot;https://github.com/peterbe/mincss&quot;&gt;code on github&lt;/a&gt;) is a tool that when given a URL (or multiple URLs) downloads that page and all its CSS and compares each and every selector in the CSS and finds out which ones aren't used. The outcome is a copy of the original CSS but with the selectors not found in the document(s) removed. It goes something like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;mincss.processor&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Processor&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Processor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'http://www.peterbe.com'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inlines&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;links&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mincss&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;processor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LinkResult&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x10a3bbe50&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mincss&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;processor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LinkResult&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x10a4d4e90&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;one&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;links&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;href&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;'//d1ac1bzf3lrf3c.cloudfront.net/static/CACHE/css/c98c3dfc8525.css'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;before&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;83108&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;10062&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;70&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;u'header {display:block}html{font-size:100%;-webkit-text-size-adjust:100'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To whet your appetite, running it on any one of my pages here on my blog it goes from: &lt;strong&gt;82Kb&lt;/strong&gt; down to &lt;strong&gt;7Kb&lt;/strong&gt;. Before you say anything; yes I know its because I using a massive (uncustomized) &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Twitter Bootstrap&lt;/a&gt; file that contains all sorts of useful CSS that I'm not using more than 10% of. And yes, those 10% on one page might be different from the 10% on another page and between them it's something like 15%. Add a third page and it's 20% etc. But, because I'm just doing one page at a time, I can be certain it will be enough.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;One way of using &lt;code&gt;mincss&lt;/code&gt; is to run it on the command line and look at the ouput, then audit it and give yourself an idea of selectors that aren't used. A safer way is to just do one page at a time. It's safer.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;The way it works is that it parses the CSS payload (from inline blocks or &lt;code&gt;link&lt;/code&gt; tags) with a relatively advanced regular expression and then loops over each selector one at a time and runs it with &lt;a href=&quot;http://pypi.python.org/pypi/cssselect&quot;&gt;cssselect&lt;/a&gt; (which uses &lt;a href=&quot;http://lxml.de/&quot;&gt;lxml&lt;/a&gt;) to see if the selector is used anywhere. If the selector isn't used the selector is removed.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;I know I'm not explaining it well so I put together a &lt;a href=&quot;https://github.com/peterbe/mincss/tree/master/example&quot;&gt;little example implementation&lt;/a&gt; which you can download and run locally just to see how it works.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Now, regarding Javascript and DOM manipulations and stuff; there's not a lot you can do about that. If you know exactly what your Javascript does, for example, creating a &lt;code&gt;div&lt;/code&gt; with class &lt;code&gt;loggedin-footer&lt;/code&gt; you can prepare your CSS to tell &lt;code&gt;mincss&lt;/code&gt; to leave it alone by adding &lt;code&gt;/* no mincss */&lt;/code&gt; somewhere in the block. Again, look at the example implementation for how this can work.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;An alternative is to instead of using &lt;code&gt;urllib.urlopen()&lt;/code&gt; you could use a headless browser like &lt;a href=&quot;http://phantomjs.org/&quot;&gt;PhantomJS&lt;/a&gt; which will run it with some Javascript rendering but you'll never cover all bases. For example, your page might have something like this:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getJSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/is-logged-in'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;logged_in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&amp;lt;div class=&amp;quot;loggedin-footer&amp;quot;&amp;gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#footer'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But let's not focus on what it can &lt;em&gt;not&lt;/em&gt; do.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;I think this can be a great tool for all of us who either just download a bloated CSS framework or you have a legacy CSS that hasn't been updated as new HTML is added and removed.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;The code is Open Source (of course) and patiently awaiting your pull requests. There's almost full test coverage and there's still work to be done to improve the code such as finding more bugs and optimizing.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/69/7d/697db04abcc6b8547972f291dd5a667d.jpg&quot; title=&quot;Using the proxy with '?MINCSS_STATS=1'&quot;&gt;&lt;img class=&quot;floatright&quot; src=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/d5/a5/d5a5d03e04fa526df9f071e1b21c3611.jpg&quot; alt=&quot;Using the proxy with '?MINCSS_STATS=1'&quot; width=&quot;100&quot; height=&quot;94&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
Also, there's a rough proxy server you can start that attempts to run it on any URL. You start it like this:&lt;br /&gt;
&lt;/p&gt;
&lt;pre&gt;
pip install Flask
cd mincss/proxy
python app.py
&lt;/pre&gt;

&lt;p&gt;and then you just visit something like &lt;code&gt;http://localhost:5000/www.peterbe.com/about&lt;/code&gt; and you can see it in action. That script needs some love since it's using &lt;code&gt;lxml&lt;/code&gt; to render the processed output which does weird things to some DOM elements.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;I hope it's of use to you.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Published a blog post about using &lt;a href=&quot;http://www.peterbe.com/plog/mincss-in-action&quot;&gt;mincss in action&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;cssmin now supports downloading using &lt;a href=&quot;http://phantomjs.org/&quot;&gt;PhantomJS&lt;/a&gt; which means that Javascript rendering will work. See &lt;a href=&quot;http://www.peterbe.com/plog/mincss-now-support-phantomjs&quot;&gt;this announcement&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Version &lt;a href=&quot;http://www.peterbe.com/plog/mincss-0.8&quot;&gt;0.8 is 500% faster now&lt;/a&gt; for large documents. Make sure you upgrade!&lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">The Great Thing About Open Source Is…</title>
		<link href="http://ramblings.timgolden.me.uk/2013/01/16/the-great-thing-about-open-source-is/"/>
		<id>http://ramblings.timgolden.me.uk/2013/01/16/the-great-thing-about-open-source-is/</id>
		<updated>2013-01-16T13:51:55+00:00</updated>
		<content type="html">&lt;p&gt;(No, this isn&amp;#8217;t one of those New Year memes; it&amp;#8217;s just a bit of a verbal ramble). &lt;/p&gt;
&lt;p&gt;I wanted to get an app up-and-running on WebFaction. And, for reasons not necessarily entirely connected with reality and hard requirements, I decided to go for Python3. WF offers CherryPy 3.2 against Python 3.1 but &amp;#8212; again, for no very good reason &amp;#8212; I decided I wanted the very latest.&lt;/p&gt;
&lt;p&gt;So: download cherrypy.latest.tgz and python.latest.tgz. Dum de dum, configure &amp;#8211;prefix=$HOME &amp;#038;&amp;#038; make &amp;#038;&amp;#038; make install. Bit of fiddling about with WF&amp;#8217;s cherrypy setup and&amp;#8230; we have a problem. The cherrypy engine is, for some reason of its own, using threading._Timer rather than threading.Timer and it&amp;#8217;s not there any more in Python 3.3.&lt;/p&gt;
&lt;p&gt;Investigation shows that this was fixed in cherrypy &lt;a href=&quot;https://bitbucket.org/cherrypy/cherrypy/src/01b6adcb3849/cherrypy/process/plugins.py&quot;&gt;a few months ago&lt;/a&gt;. Meanwhile things will probably go ok with Python 3.2. What to do? I decided on backtracking on Python (truth be told, I hadn&amp;#8217;t checked the cherrypy logs at this point). Download python.32.tgz. Dum de dum&amp;#8230; and&amp;#8230; error with _posixsubprocess. Looks like it&amp;#8217;s fixed in the 3.2 branch but not yet released.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m now in the situation where I&amp;#8217;ll either have to use a hg checkout of cherrypy or an hg checkout of Python. Or both.&lt;/p&gt;
&lt;p&gt;Lest this be seen as a dig at either the cherrypy or the Python guys, it&amp;#8217;s certainly not. I&amp;#8217;m grateful to them both for the work they&amp;#8217;ve done and for the open source infrastructure they use which gives me the information and options I&amp;#8217;ve outlined above. I could most certainly backtrack a couple of published versions of either perfectly well for my own needs.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s more of an endorsement of what open source offers you if you want (and I haven&amp;#8217;t even talked about the fact that I could fork cherrypy or Python if I needed and still maintain a version in sync with the canonical one for my own use on WF).&lt;/p&gt;
&lt;p&gt;All I need to do now is clone hg.python.org/cpython, config &amp;#038; make and I&amp;#8217;m away.&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>2013-06-07T12:22:13+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Map/Reduce (Disco) on millions of tweets</title>
		<link href="http://ianozsvald.com/2013/01/13/mapreduce-disco-on-millions-of-tweets/"/>
		<id>http://ianozsvald.com/?p=1610</id>
		<updated>2013-01-13T19:10:49+00:00</updated>
		<content type="html">&lt;p&gt;Whilst working on &lt;a href=&quot;http://www.morconsulting.com/&quot;&gt;data sciencey&lt;/a&gt; problems for &lt;a href=&quot;https://www.adaptivelab.com/&quot;&gt;AdaptiveLab&lt;/a&gt; I&amp;#8217;m becoming more involved in simple visualisations for proof-of-concepts for clients. This ties in nicely with my PyCon &lt;a href=&quot;https://us.pycon.org/2013/schedule/presentation/27/&quot;&gt;Parallel Computing&lt;/a&gt; tutorial with Minesh. I&amp;#8217;ve been prototyping a Disco map/reduce tutorial (part 2 for PyCon) using tweets collected during the life of &lt;a href=&quot;http://socialtiesapp.com/&quot;&gt;SocialTies&lt;/a&gt; during 2011-2012.&lt;/p&gt;
&lt;p&gt;Using 11,645,331 tweets on 1 machine running through &lt;a href=&quot;http://discoproject.org/&quot;&gt;Disco&lt;/a&gt; with a modified word_count example it is easy to filter to keep tweets with a certain word (&amp;#8220;loving&amp;#8221; in this case) and to plot a &lt;a href=&quot;https://github.com/amueller/word_cloud&quot;&gt;word cloud&lt;/a&gt; (thanks Andreas!) of the remaining tweets:&lt;/p&gt;
&lt;div class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;https://secure.flickr.com/photos/54145418@N00/8376453299/in/photostream&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://farm9.staticflickr.com/8044/8376453299_cd2f900ee5_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Words in &amp;#8220;loving&amp;#8221; tweets&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Tweet analysis often shows a self-referential nature &amp;#8211; here we see &amp;#8220;i&amp;#8217;m&amp;#8221; as one of the most popular words. It is nice to see &amp;#8220;:)&amp;#8221; making an appearance. Brands mentioned include &amp;#8220;Google&amp;#8221;, &amp;#8220;iPhone&amp;#8221;, &amp;#8220;iPad&amp;#8221;. We also see &amp;#8220;thanks&amp;#8221;, &amp;#8220;love&amp;#8221;, &amp;#8220;nice&amp;#8221; and &amp;#8220;watching&amp;#8221; along with &amp;#8220;London&amp;#8221; and &amp;#8220;music&amp;#8221;. Annoyingly I&amp;#8217;m not cleaning the words so we see &amp;#8220;it!&amp;#8221;, &amp;#8220;it.&amp;#8221;, &amp;#8220;(via&amp;#8221; (with erroneous brackets) and the like which clutter the results a bit.&lt;/p&gt;
&lt;p&gt;Next I&amp;#8217;ve applied &amp;#8220;hating&amp;#8221; as the filter to the same set:&lt;/p&gt;
&lt;div class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;https://secure.flickr.com/photos/54145418@N00/8376453403/in/photostream&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://farm9.staticflickr.com/8324/8376453403_e9a1d58fac_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Words in &amp;#8220;hating&amp;#8221; tweets&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;One of the most mentioned words is &amp;#8220;people&amp;#8221; which is a bit of a shame, along with &amp;#8220;i&amp;#8217;m&amp;#8221;. Thankfully we see some &amp;#8220;love&amp;#8221; and &amp;#8220;loving&amp;#8221; there. &amp;#8220;apple&amp;#8221; appears more frequently than &amp;#8220;twitter&amp;#8221; or &amp;#8220;google&amp;#8221;. Lots of related negative words also appear e.g. &amp;#8220;stupid&amp;#8221;, &amp;#8220;hate&amp;#8221;, &amp;#8220;shit&amp;#8221;, &amp;#8220;fuck&amp;#8221;, &amp;#8220;bitch&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Interestingly few of the terms shown include Twitter users or hashtags.&lt;/p&gt;
&lt;p&gt;Finally I tried the same using &amp;#8220;apple&amp;#8221; on an earlier smaller set (859,157 tweets):&lt;/p&gt;
&lt;div class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;https://secure.flickr.com/photos/54145418@N00/8377521798/in/photostream&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://farm9.staticflickr.com/8088/8377521798_984f5b380d_m.jpg&quot; width=&quot;240&quot; height=&quot;180&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Words in &amp;#8220;apple&amp;#8221; tweets&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Unsurprisingly we see &amp;#8220;store&amp;#8221;, &amp;#8220;iphone&amp;#8221;, &amp;#8220;ipad&amp;#8221;  &amp;#8220;steve&amp;#8221;. Hashtags include &amp;#8220;#wwdc&amp;#8221;, &amp;#8220;#apple&amp;#8221; and &amp;#8220;#ipad&amp;#8221;. The Twitter accounts shown are errors due to string-matching on &amp;#8220;apple&amp;#8221; except for &lt;a href=&quot;https://twitter.com/techcrunch&quot;&gt;@techcrunch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I find it interesting to see competitor brands being mentioned in the same tweets (e.g. &amp;#8220;google&amp;#8221;, &amp;#8220;microsoft&amp;#8221;, &amp;#8220;android&amp;#8221;, &amp;#8220;samsung&amp;#8221;, &amp;#8220;amazon&amp;#8221;, &amp;#8220;nokia&amp;#8221;), although the firms are obviously related to &amp;#8220;apple&amp;#8221;.&lt;/p&gt;
&lt;p&gt;An improvement would be to remove words from the chart that match the original pattern (hence removing words like &amp;#8220;apple&amp;#8221; and &amp;#8220;#apple&amp;#8221; but keeping everything else). Removing near-duplicate terms (e.g. &amp;#8220;apple&amp;#8221;, &amp;#8220;apples&amp;#8221;, &amp;#8220;apple&amp;#8217;&amp;#8221;) and performing common string clean-ups (removing punctuation) which also help.&lt;/p&gt;
&lt;p&gt;It would also be good to change the colour channels &amp;#8211; perhaps using red for commonly-negative words and green for commonly-positive words, with the rest in a neutral colour. Maybe we could also colour the neutral words differently if they&amp;#8217;re commonly associated with the key word (e.g. brands of the key word).&lt;/p&gt;
&lt;p&gt;Getting started with Disco was easy enough. The installation takes a few hours (the Disco project instructions assume a certain familiarity with networked systems), after that editing the examples is straightforward. Visualising using Andreas&amp;#8217; code was very straight-forward. The source will be posted around the time of my PyCon tutorial in March.&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry>
		<title type="html">The next stage: writing a book</title>
		<link href="http://www.obeythetestinggoat.com/writing-a-book-announcement.html"/>
		<id>tag:www.obeythetestinggoat.com,2013-01-08:writing-a-book-announcement.html</id>
		<updated>2013-01-08T00:00:00+00:00</updated>
		<content type="html">&lt;p&gt;I've decided to try and develop this tutorial into an actual book on test-driven development for web apps.  Have a look at the chapter outline I've posted as part 6:&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;reference external&quot; href=&quot;http://www.tdd-django-tutorial.com/tutorial/6/&quot;&gt;http://www.tdd-django-tutorial.com/tutorial/6/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I'd love to hear what you think!  Am I completely mad?&lt;/p&gt;</content>
		<author>
			<name>Harry</name>
			<uri>http://www.obeythetestinggoat.com/</uri>
		</author>
		<source>
			<title type="html">Obey the Testing Goat!</title>
			<link rel="self" href="http://www.obeythetestinggoat.com/feeds/all.atom.xml"/>
			<id>http://www.obeythetestinggoat.com/</id>
			<updated>2013-06-10T20:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Gun Nuts 1</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/YKj7rBN_cdg/gun-nuts-1.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-2222177690675766546</id>
		<updated>2012-12-17T02:57:24+00:00</updated>
		<content type="html">In the wake of the most recent school slaying I thought it might be relevant to revisit the writings of Eric S Raymond. Within my world he is a well-known and self-described &quot;gun nut.&quot; His two principal writings on he right to bear arms appear to be&amp;nbsp;&lt;i&gt;&lt;a href=&quot;http://www.catb.org/esr/guns/sheep.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;The Parable of the Sheep&lt;/a&gt;&lt;/i&gt; and &lt;i&gt;&lt;a href=&quot;http://www.catb.org/esr/guns/gun-ethics.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Ethics Through the Barrel of a Gun&lt;/a&gt;&lt;/i&gt;. I will look at the latter in a separate post. There is nothing I can do for the misery of the bereaved families. I can only hope to help in the longer run.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;b&gt;The Parable of the Sheep&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
This is a tale of a flock of sheep. The dog cannot keep the wolves away. Some sheep take the claws and fangs from dead wolves. They fight back, reducing the carnage. Eventually the wolves mostly leave sheep alone. They do not know which sheep are armed. Many sheep are terrified of the weapons. They ban the armed sheep from to the pasture. They post signs at the edges forbidding hidden weapons. The wolves, seeing this, return. Once again they inflict carnage on the flock. They are only beaten off by the armed sheep. The flock remain afraid of the weapons. They barely tolerate their protectors, the armed sheep. The armed sheep altruistically continue to protect the flock. Raymond describes the situation thus:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span&gt;&lt;span&gt;The bold sheep knew that the fangs and claws they possessed had not changed them. They still grazed like other sheep, and raised their lambs in the spring, and greeted their friend the dog as he walked among them. But they could not quell the terror of the flock, which rose in them like some ancient dark smoky spirit and could not be damped by reason, nor dispelled by the light of day.&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;
The parable omits many refinements of the true situation. That is forgivable for&amp;nbsp;expository&amp;nbsp;purposes. A school shooting represents something outside the parable. There is a genuine reason for the terror of the unarmed sheep. Occasionally the armed sheep start acting like wolves. Of course the unarmed sheep are then the inevitable target.&lt;br /&gt;
&lt;br /&gt;
The statistics for murder and armed robbery are quite alarming. Those for child murder are truly chilling. &lt;a href=&quot;http://nationalpostnews.files.wordpress.com/2012/12/fo1217_childmurder940.jpg&quot; target=&quot;_blank&quot;&gt;Almost 63% involved a firearm in 2011&lt;/a&gt;. Well over a thousand kids blown away each year. To suggest that we &lt;i&gt;all&lt;/i&gt;&amp;nbsp;arm to protect ourselves seems unbalanced. It's like the 1950's &quot;defense&quot; policy of Mutually Assured Destruction. Never was an acronym more appropriate.&amp;nbsp;The terrorists aren't&amp;nbsp;&lt;i&gt;over there&lt;/i&gt;, they are among us. A school massacre is an act of terror.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
Here the Japanese strategy of many approaches might be fruitful. It is unlikely there is a single switch we can turn to stop this happening. Surely it is better to try to understand these acts of atrocity. Consider them a societal ill and seek its cure. Perhaps we could try to build a world where people are better in touch with their fellows. Extremes of behavior can (most of the time) be recognized. If someone is heading in a dangerous direction, perhaps it can be deflected by sympathetic attention.&lt;br /&gt;
&lt;br /&gt;
I imagine* that most mass murderers are completely in control most of the time. They are indistinguishable &amp;nbsp;from &quot;normal&quot; people. The classic quote after an apparently psychotic shooting episode? &quot;He seemed like a normal guy.&quot; Let's leave the fact it's usually a man to another time. It's not like they are landmines, liable to go off at any touch. I am a pretty placid person most of the time. Occasionally some perfect storm of circumstances hits. Shortage of sleep is often involved. Physical exhaustion never helps. Emotional distress is very rarely positive. I &quot;go off on one&quot; in an uncharacteristic way. We all have extremes of behavior, often in response to extreme circumstances. Some people are more extreme than others.&lt;br /&gt;
&lt;br /&gt;
Some people, sadly, are so extreme that they must be incarcerated to protect the rest of us. I would, in the USA, prefer it if the government invested its funding in long-term plans to make the country a better place to live than lock up predominantly black predominantly drug-offending adults.** Now private companies are running prisons, vested interests are powerful.&lt;br /&gt;
&lt;br /&gt;
So while Raymond's simplified argument seems reasonable enough, that's only because it is simplified. There are inevitable outliers in a flock of over three hundred million.&amp;nbsp;Mental stability and degree of moral control are two important dimensions.&amp;nbsp;At that scale the sheep would appear to have a good reason for caution. Anyone proposing to use fangs and claws should surely be assessed as a responsible individual. Mistakes will still be made, but (presumably) it is not beyond the wit of sheep to concoct a scheme that reduces the number of massacre incidents.&lt;br /&gt;
&lt;br /&gt;
In network parlance, the parable &lt;i&gt;doesn't scale to larger flocks&lt;/i&gt;. Neither does it scale to bigger and better teeth and claws. The &lt;i&gt;reductio ad absurdum&lt;/i&gt;&amp;nbsp;of many gun nut arguments is that we should all carry personal tactical nuclear weapons. What's reasonable, and what's not? Why are such deadly automatic weapons allowed outside gun clubs and the armed forces? I don't mind people enjoying handling and using firearms. Hunting, preferably for food, for example, is a perfectly legitimate use. So is fun at a gun club shooting range. Mowing down kids, not so much. We have to strike a balance.&lt;br /&gt;
&lt;br /&gt;
One final note: please let's not imagine there is an instant cure. All we can do is lay, and maintain to, long term plans. These should aim to reduce the availability and access to weapons, particularly those capable of facilitating mass murder.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span&gt;* Admittedly if this were a Wikipedia article someone would have at least added a &quot;citation needed&quot; flag&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;** Who are then unable to vote&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=YKj7rBN_cdg:dDRZfytCR5I: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=YKj7rBN_cdg:dDRZfytCR5I:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=YKj7rBN_cdg:dDRZfytCR5I:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/YKj7rBN_cdg&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">&quot;Any sufficiently advanced technology is indistinguishable from magic&quot; -- Arthur C Clarke
&lt;br /&gt;
Musings from the technological frontier</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2013-05-16T00:22:18+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">A Thank You to Eric Sterling</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/AWWHBhBAJls/a-thank-you-to-eric-sterling.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-7918576359961685100</id>
		<updated>2012-12-17T00:34:01+00:00</updated>
		<content type="html">Offered for the attention of those who attended Eric's recent keynote at DjangoCon and, most especially for Eric himself. I still remember the talk and the panel session he took the time to contribute to fondly, and I particularly enjoyed the unique flavor he added to the lunch he attended.&lt;br /&gt;
&lt;div class=&quot;separator&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-0yPc7iBL_wQ/UM6obZsyuxI/AAAAAAAABaM/8dWKGPT8RkU/s1600/2012-12-16_21-04-47.png&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/-0yPc7iBL_wQ/UM6obZsyuxI/AAAAAAAABaM/8dWKGPT8RkU/s1600/2012-12-16_21-04-47.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=AWWHBhBAJls:3hdtcQiI0rY: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=AWWHBhBAJls:3hdtcQiI0rY:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=AWWHBhBAJls:3hdtcQiI0rY:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/AWWHBhBAJls&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">&quot;Any sufficiently advanced technology is indistinguishable from magic&quot; -- Arthur C Clarke
&lt;br /&gt;
Musings from the technological frontier</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2013-05-16T00:22:18+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">I'm Sorry</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/o8WqY0TSSu8/im-sorry.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-3033163751951070918</id>
		<updated>2012-12-15T09:44:31+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/-ma_dDypuHLc/UMwyq2emRiI/AAAAAAAABZ0/ZCjIYKSLltg/s1600/P1000255.JPG&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;http://2.bp.blogspot.com/-ma_dDypuHLc/UMwyq2emRiI/AAAAAAAABZ0/ZCjIYKSLltg/s200/P1000255.JPG&quot; width=&quot;150&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot;&gt;The one-eyed snake&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
It appears I've been that guy (again). I've seen those &quot;sorry if you were offended&quot; apologies, and they are bullshit. So let me begin by unreservedly apologizing for my inappropriate behavior. Then perhaps I can tell you what this is all about. I do so in the doleful expectation that this post will generate more heat than light, as is typical for this subject matter in geek circles, and will be the cause of a large amount of ill-informed, unhelpful and possibly personally damaging commentary. Since it gives me the opportunity to discuss a few issues of importance I accept that as the price.&lt;br /&gt;
&lt;br /&gt;
&lt;strike&gt;Last&lt;/strike&gt;&amp;nbsp;This year, at PyCon, I had a Square, a device to accept credit card payments through my cellphone, and &lt;i&gt;inter alia&lt;/i&gt;&amp;nbsp;was soliciting donations to the Python Software Foundation. As a part of my &lt;i&gt;schtick&lt;/i&gt;&amp;nbsp;I was offering to take photographs, and offered the option of a prop, a little Beanie Babies™ bean-stuffed Python which my dog, when a &amp;nbsp;puppy, had once got hold of and played with so enthusiastically that she tore off (and probably swallowed) the glued-on bead that represented its left eye. I've had this snake almost ever since I started using Python (almost twenty years now) and I'm very fond of it. It often travels with me as a talisman, since I usually travel alone.&lt;br /&gt;
&lt;br /&gt;
Because I am so familiar with it, in retrospect it seems a little odd that I had never particularly dwelt on the fact that it is, literally, my &quot;one-eyed snake&quot; though I had used the phrase at home with family and friends as a joke. [For readers not familiar with colloquial English and American, I am obliged to point out at this stage that &quot;one-eyed snake&quot; is one of many euphemisms for the penis]. I was amused enough, on that day, by this fatuous coincidence that I&amp;nbsp;offered to include &quot;the chairman's one-eyed snake&quot; in the photographs I was taking, of men as well as women.&lt;br /&gt;
&lt;br /&gt;
People&amp;nbsp;appeared&amp;nbsp;(in my opinion, not actually the opinion that matters as it happens) to tolerate my&amp;nbsp;&lt;i&gt;risqué&lt;/i&gt;&amp;nbsp;attempt at humor, feeble as it was, and took it in good part although certainly not everyone asked for the snake to be included. The conference ran its course, I went on my way, unaware that a storm was brewing.&lt;br /&gt;
&lt;br /&gt;
The storm's gestation in fact took another event to trigger it, a recent motion by the PSF board that we would require any conference we funded to implement a code of conduct. The board collectively felt that this would be a forward step, and would actually be helpful to conference organizers who had not yet addressed this issue. PyCon has has a code of conduct for several years, and since the conferences I run professionally also have codes of conduct, I had no hesitation in voting for the motion.&lt;br /&gt;
&lt;br /&gt;
It's difficult to describe this situation in anonymous terms, since verbatim quotes are required in order to allow me to properly discuss the way this situation has turned out. But those who wish to know the identities of the proponents must do so by using {{search_engine_of_choice}}. What happened when news of the motion came out is that someone posted a comment on Hacker News which included the following content&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;div class=&quot;p1&quot;&gt;
From what I understand, the code was approved by the Board of Directors of the PSF, and not the PSF as a whole. Please, correct me if I am wrong. This is ironic since one of the Board members was walking around the conference last year with a damaged stuffed python toy asking, &quot;Would you like to see my one eyed snake?&quot;&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
This was said to one of my female colleagues. I asked her if she would like me to say something and she replied, &quot;No, it is just creepy, but I'm an adult.&quot;&lt;/div&gt;
&lt;/blockquote&gt;
I'd like you to particularly note two things: first, the quote is inaccurate, I believe (if I uttered those words I would have to accept I would have gone over the line with anyone but a close friend); second, the colleague herself chose not to complain. This is significant because of what happened next. Clearly the comment had received some attention, since shortly thereafter a second person, one I think it is fair to say is known not to be well-disposed towards the PSF, tweeted (in reply to a third party who may for all I know have been a fifth or twelfth party)&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
Wait, I didn't read this comment closely enough. What fucktard was walking around asking women to pet his one-eyed snake?&lt;/blockquote&gt;
Note again: the already inaccurate quotation has been through the mangler once more. So now we (that is me and the PSF, though in this post I must put my director's hat aside and accept personal culpability) have a &lt;i&gt;situation&lt;/i&gt;. This is not something that would have worried me hugely in my personal capacity, but the fact is that it has brought a lot of pressure to bear on someone who, through his heroic efforts to improve on last year's incredible PyCon, is already under quite enough pressure. So it is necessary for me to write this explanation lest his efforts to bring in sponsorship and promote diversity of all kinds in the Python community are damaged by my bad behavior.&lt;br /&gt;
&lt;br /&gt;
Now to the several points I should like to make about the outcomes so far. I hesitate to think of the fallout to my professional life.&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;I am lucky to be a man, since any woman posting about similar issues of female sensitivity is likely to be harangued and harassed until, unless she is of extraordinary character, she either allows herself to be silenced or leaves the Internet altogether (yes, well-known women have received threats that they felt obliged them to do this).&lt;/li&gt;
&lt;li&gt;Context is important. Although my behavior may not have been appropriate, it was taking place in broad daylight in a well-populated area so nobody felt especially threatened by it. The same offer (let alone either of the two misquoted ones above) made to a woman who is the only other occupant of an elevator at 1:30 in the morning would, I think, be reasonably interpreted as a possible if not an actual threat. Anyone who doesn't understand that isn't really fit to be out alone.&lt;/li&gt;
&lt;li&gt;It isn't up to me to decide whether my behavior is appropriate, but those with whom I interact. I teach professionally, have taken (and passed) sensitivity training classes, and am accustomed to behave in a professional manner that does not run the risk of attaching stigma to those I represent. &amp;nbsp;Because I feel that many members of the Python community are my friends, I perhaps overstepped the boundaries of professionalism, believing that nobody would mind.&lt;/li&gt;
&lt;li&gt;The fall-out of righteous indignation about events like this often lands on the wrong person. There is now heavy pressure on Jesse Noller as PyCon chair for not taking action about this. There have been definite suggestions that Jesse is being hypocritical in promoting a code of conduct for PyCon while condoning inappropriate behavior by a fellow director. There are two things worthy of note about this.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Firstly, since the issue only came to his and my attention eight months after the conference (and, indeed, after both he and I voted for the motion requiring codes of conduct) it is difficult to know what he could have been expected to do at the time. He has been heroically silent (for him).&lt;/li&gt;
&lt;li&gt;Secondly, the code of conduct exists precisely to reassure people that harassing actions can be reported, and will be dealt with, &lt;i&gt;no matter what the position of the offender in the community&lt;/i&gt;. So I think anyone who is gunning for Jesse about this should give him a pass. If he had come to me because he had received a complaint I cannot say what action I would have felt correct, but at the least I would have expected to make a public apology. I do not expect that Jesse would have felt able to let a transgression on my part go without action: he has far too much integrity for that. I like to think I have enough integrity to accept being told when I have transgressed (hence my dislike of the &quot;if anyone was offended, sorry&quot; stuff).&lt;/li&gt;
&lt;li&gt;Circumstances alter cases. The code of conduct is not expected to protect people in a vacuum. If you find someone's behavior offensive your first recourse should be to say so. Hopefully an apology should be forthcoming, or at least a civilized discussion about your differences in standards. If the issue cannot be resolved in person &lt;i&gt;then&lt;/i&gt;&amp;nbsp;is the time to invoke the code of conduct. This is what makes variations in behavioral standards acceptable: when you are with people you know you are unlikely to go wrong; when you are not you should take others' input as defining acceptable limits.&lt;/li&gt;
&lt;li&gt;It is unreasonable to expect perfection. We all slip from time to time, and a slip should not necessarily lead to a fall. I noted with a parenthetical &quot;again&quot; in the opening paragraph that this is not the first time I have behaved inappropriately, and sadly it may not be the last. I can say, though, that on the few occasions my behavior towards an individual was definitely capable of causing offense I have apologized sincerely and without reservation, usually before further contact from the other party (&lt;i&gt;i.e.&lt;/i&gt;&amp;nbsp;I am capable of recognizing bad behavior on my own part and voluntarily apologizing for it). I am happy to say that I count some of those to whom I have had to apologize as friends even now, and believe those feelings are reciprocated.&lt;/li&gt;
&lt;li&gt;I specifically do &lt;i&gt;not&lt;/i&gt;&amp;nbsp;want the support of men weighing in with some equivalent of &quot;what the hell, man, you didn't do anything wrong, what are the women complaining about?&quot; Perhaps when your knuckles stop dragging along the ground we can talk. I very much &lt;i&gt;would&lt;/i&gt;&amp;nbsp;like the support of men who are equally liable to do stupid things (and have done) and yet still remain open to the possibility that one can be equally civil and courteous to members of all sexes. It's easy for men to say &quot;we've all been that guy,&quot; but I hope that women don't imagine that guy conversation is laced with tales about how we &lt;i&gt;were&lt;/i&gt; &quot;that guy&quot;. We don't talk about our goofs even among ourselves (unless&amp;nbsp;there's some club I'm not a member of). Men who are sensitive to the need for gender diversity find these mistakes painful to remember, and only dwell on them in private (this has not been an easy post to write). Men who are not sensitive to that need, please re-read the opening sentence of this paragraph.&amp;nbsp;Support from others will also be more than welcome.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Diversity is not just gender diversity. Because I speak fluent English it is easy for Americans to imagine that I have absorbed their culture fully, though even after fifteen years I often have to stop to clarify cultural referents common to most natives. They forget that I am, in fact, an immigrant who was brought up with different standards. I am not trying to suggest that I should not be subject to the values of the USA, but would hope that when I overstep the bounds some leniency might be shown. I in my turn sometimes forget that standards &lt;i&gt;are&lt;/i&gt; different over here.&lt;/li&gt;
&lt;/ol&gt;
There is more that I could write*, but I feel that this post is already long enough. I will close by remarking that it turns out the female colleague of the original poster is personally known to me, and in our several meetings both personal and professional since then she has not mentioned this issue (unless my memory has failed me). Naturally I intend to apologize to her at the first available opportunity, and to ensure that in the future I do nothing to make her feel uncomfortable (the basis on which I believed I was conducting the relationship). If I was not confident that people would feel comfortable in my presence I would not feel able to attend PyCon, since that would exclude others.&lt;br /&gt;
&lt;br /&gt;
As PyCon's founder I genuinely want to see it address diversity issues properly. For eight years as a director and three years as chairman I have worked to ensure that the PSF is seen to take these issues seriously. I am mortified that I ran the risk of bringing either into disrepute. I hope that by making this apology I continue to lead by example.&lt;br /&gt;
&lt;br /&gt;
&lt;span&gt;&lt;b&gt;* I might, say, discuss the appropriateness of using the word &quot;fucktard&quot; in public discourse on such serious matters .&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=o8WqY0TSSu8:ycwpxgSq0Yc: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=o8WqY0TSSu8:ycwpxgSq0Yc:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=o8WqY0TSSu8:ycwpxgSq0Yc:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/o8WqY0TSSu8&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">&quot;Any sufficiently advanced technology is indistinguishable from magic&quot; -- Arthur C Clarke
&lt;br /&gt;
Musings from the technological frontier</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2013-05-16T00:22:18+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Office social graph connectivity using NetworkX</title>
		<link href="http://ianozsvald.com/2012/12/13/office-social-graph-connectivity-using-networkx/"/>
		<id>http://ianozsvald.com/?p=1588</id>
		<updated>2012-12-12T23:23:21+00:00</updated>
		<content type="html">&lt;p&gt;I wanted an excuse to play with the Python &lt;a href=&quot;http://networkx.lanl.gov/&quot;&gt;NetworkX&lt;/a&gt; graph visualisation library and recently I joined &lt;a href=&quot;https://www.adaptivelab.com/&quot;&gt;AdaptiveLab&lt;/a&gt; to consult on some data science &amp;amp; visualisation problems. Thus formed the question &amp;#8211; how were we all connected together? I figured that looking at who follows us all will yield a little insight into the people we have in common. I&amp;#8217;m particularly interested in this question seeing as I was living in Brighton, then &lt;a href=&quot;http://ianozsvald.com/2012/11/25/startupchile-round-2-1-all-finished-thoughts/&quot;&gt;lived in Chile&lt;/a&gt; for most of the year and have only recently moved to London &amp;#8211; my social graph is likely to be disjointed to the graph of the existing London-based team.&lt;/p&gt;
&lt;p&gt;Below I show the follower graph with my new colleagues at the top (&lt;a href=&quot;https://twitter.com/jameshaycock&quot;&gt;James&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/lovedaybrooke&quot;&gt;Kat&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/localben&quot;&gt;Ben&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/markpriestley&quot;&gt;Mark&lt;/a&gt;, Steve), &lt;a href=&quot;https://twitter.com/fluffyemily&quot;&gt;Emily&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/jot&quot;&gt;Jon&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/ianozsvald&quot;&gt;myself&lt;/a&gt; in the middle and my collaborator &lt;a href=&quot;https://twitter.com/brouberol&quot;&gt;Balthazar&lt;/a&gt; at the bottom:&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;My local twitter network&quot; href=&quot;https://raw.github.com/ianozsvald/twitter-social-graph-networkx/master/sample_full_network.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1590&quot; alt=&quot;sample_full_network_thumb&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2012/12/sample_full_network_thumb-300x167.png&quot; width=&quot;300&quot; height=&quot;167&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I chose to visualise followers rather than who-we-follow as I cared about the graph of who-pays-(some)-attention-to-us. I figure this is a good surrogate for people who might actually know us, suggesting a good chance that we have friends and colleagues in common.&lt;/p&gt;
&lt;p&gt;Balthazar worked in France with me in StrongSteam (whilst I was in Chile), he&amp;#8217;s followed by almost nobody from my usual network. &lt;a href=&quot;http://emilytoop.com/&quot;&gt;Emily&lt;/a&gt; and I are a couple, we&amp;#8217;re followed by a lot of the same people. Our friend Jon lives in Brighton and runs the central &lt;a href=&quot;http://www.theskiff.org/&quot;&gt;co-working environment&lt;/a&gt; (where we were for 10 years), he is followed by many of the people who follow us. The top of the graph shows that my colleagues are followed by only a few people who follow others in the company (so we all have different social networks), with the exception of boss-James who shares a set of followers with my Jon and myself (I guess because we&amp;#8217;re all outspoken in the UK tech scene).&lt;/p&gt;
&lt;p&gt;In the above graph I deliberately reduced the number of nodes drawn if they were only connected to one person in the network. Seeing as a few of us have over a thousand followers the graph got  too busy too quickly. Below is a subsampled version of the early network with no limit on the number of one-edge-only nodes:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ianozsvald/twitter-social-graph-networkx/blob/master/sample_network.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-1594&quot; alt=&quot;sample_network_thumb&quot; src=&quot;http://ianozsvald.com/wp-content/uploads/2012/12/sample_network_thumb-300x176.png&quot; width=&quot;300&quot; height=&quot;176&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The subsampled network looks nicely organic, like living cells.&lt;/p&gt;
&lt;p&gt;The code is on github as &lt;a href=&quot;https://github.com/ianozsvald/twitter-social-graph-networkx&quot;&gt;twitter-social-graph-networkx&lt;/a&gt;, it includes some patches that have just been added back to the &lt;a href=&quot;https://github.com/bear/python-twitter/&quot;&gt;python-twitter&lt;/a&gt; module to enable whole-graph downloading. You can use this code to download the follower graph for your own network, then plot it using NetworkX (it is configured to use GraphViz as the plots are faster, you can use pure NetworkX if you don&amp;#8217;t have GraphViz). The git project has pickles of my social network so if you satisfy the dependencies, you should be good to plot straight away.&lt;/p&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Hexagonal Django</title>
		<link href="http://tartley.com/?p=1404"/>
		<id>http://tartley.com/?p=1404</id>
		<updated>2012-12-04T14:42:01+00:00</updated>
		<content type="html">&lt;p&gt;The last few weeks I&amp;#8217;ve been thinking about the architectural pattern known as &lt;a href=&quot;http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html&quot;&gt;Clean, Onion, Hexagonal, or Ports&amp;#8217;n'Adaptors&lt;/a&gt;. I&amp;#8217;m curious if many people are applying it in the Django world.&lt;/p&gt;
&lt;p&gt;The premise is for your core application entity classes and business rules to be plain old objects, with no dependencies. In particular, they are not dependent on the interfaces between your application and external systems, such as your persistence mechanism, or your web framework. Instead, external interface components depend upon your core business objects. This essentially moves the database from the &amp;#8216;bottom&amp;#8217; layer of the old traditional &amp;#8216;three layer architecture&amp;#8217;, to form a part of the topmost layer &amp;#8211; a sibling with the &amp;#8216;UI.&amp;#8217;&lt;/p&gt;
&lt;p&gt;For inbound messages (e.g handling a web request) this is straightforward &amp;#8211; Django calls your view code which calls your business layer, but keep your business layer separate from your Django code, so it is stand-alone and unit-testable. For outbound messages, such as then rendering the web page in response, it&amp;#8217;s slightly more complicated: Your business logic must pass the result (typically a pure data structure) back to your web-aware code, but without your business logic depending on the web-aware component. This requires an inversion of control.&lt;/p&gt;
&lt;p&gt;That way, all your business logic can easily be tested in unit tests, with no mocking required. You still need some end-to-end tests to verify integration, but you shouldn&amp;#8217;t need to involve your UI or database in testing every detail of your business logic.&lt;/p&gt;
&lt;p&gt;Also, you can easily switch out your external system interfaces, such as persistence, to use another RDBMS, another ORM, a NoSQL store, or an in-memory version for testing Since the core of your application doesn&amp;#8217;t have any dependency on these components, it is oblivious to the change. The business logic, because it doesn&amp;#8217;t depend on Django, is no longer riddled with Django&amp;#8217;s convenient ORM database access.&lt;/p&gt;
&lt;p&gt;Same thing goes for switching out your web framework, or calling the same logic from web UI or web API calls. And again, for switching out your UI: add a command line application, or a console UI. The core application logic is unaffected, and your new interface components contain only the code that is specific to that interface&amp;#8217;s concerns.&lt;/p&gt;
&lt;p&gt;Another side effect is that your web framework, if you&amp;#8217;re using one, becomes a peripheral detail which depends upon your core application, rather than the other way round. Your Django project would become a subdirectory of your project, rather than dominating your project directory structure. Since the business logic formerly contained within it is now elsewhere (in your core business objects) the Django project is now very thin. Views, for example, are delegations to single business-layer functions. The Django project now contains just the web-oriented aspects of your project, as it should.&lt;/p&gt;
&lt;p&gt;These ideas all seem like relatively straightforward software engineering, and I feel a bit foolish for not having been aware of them all these years. I console myself that I&amp;#8217;m not alone.&lt;/p&gt;
&lt;p&gt;UncleBob&amp;#8217;s Ruby Midwest keynote &amp;#8220;&lt;a href=&quot;http://tartley.com/ http://www.confreaks.com/videos/759-rubymidwest2011-keynote-architecture-the-lost-years&quot;&gt;Architecture &amp;#8211; The Lost Years&lt;/a&gt;&amp;#8221; attributes one source of this idea to Ivar Jacobsen&amp;#8217;s 1994 book &lt;a href=&quot;http://tartley.com/ http://www.amazon.co.uk/Object-oriented-Software-Engineering-Approach-Press/dp/0201544350&quot;&gt;Object Oriented Software Engineering : A Use Case Driven Approach&lt;/a&gt; (2nd-hand hardbacks cheap on Amazon.)&lt;/p&gt;
&lt;p&gt;I see a few people applying these ideas to Rails, but are many people out there doing this in Django? I plan to refactor a small vertical slice of our monster Django app into this style, to try and prove the idea for myself.&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>2013-04-25T10:22:39+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Python for Data Analysis</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/WlygopRZ-dc/python-for-data-analysis.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-2474722595477854785</id>
		<updated>2012-11-19T02:13:51+00:00</updated>
		<content type="html">&lt;span&gt;&lt;b&gt;&lt;a href=&quot;http://shop.oreilly.com/product/0636920023784.do&quot; target=&quot;_blank&quot;&gt;Python for Data Analysis&lt;/a&gt;; Wes McKinney. O'Reilly Media, October 2012&lt;br /&gt;[Review copy kindly provided gratis by O'Reilly Media]&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This book is a welcome addition to the Python canon, and anyone who is at all concerned with data analysis would do well to read it. From the opening chapter it is a clear and concise explanation of how to deploy Python for such tasks. Early on the author makes the point that Python should be thought of primarily as a “glue” language, so the book makes no attempt to show you how to program analytical methods in Python but rather demonstrates through practical examples how to use the existing extremely effective tool chain already available.&lt;br /&gt;
&lt;br /&gt;
After a few brief motivating examples you will read one of the clearest expositions of the benefits of iPython I have seen. Since reading this chapter I have become convinced of the benefits of iPython Notebook and have opened an account with &lt;a href=&quot;https://notebookcloud.appspot.com/&quot; target=&quot;_blank&quot;&gt;NotebookCloud&lt;/a&gt;*, which I feel will be a real boon in my teaching work.&lt;br /&gt;
&lt;br /&gt;
The next chapter covers Numpy basics, followed by an introduction to the pandas library. You are then taken in detail, and with copious practical examples, through data cleanup and various important transformations, plotting and visualization, data aggregation and grouping, time series and finally financial applications.&lt;br /&gt;
&lt;br /&gt;
The final chapter on advanced Numpy provides the kind of look under the hood that will help those interested to extract maximum efficiency from the package and understanding how best to take advantage of more advanced features. The closing Appendix, “Python Language Essentials,” is a concise introduction to the language that should provide even inexperienced Python users with sufficient information to understand the examples.&lt;br /&gt;
&lt;br /&gt;
The writing is clear throughout, with numerous examples that enliven and illuminate the discussions. For those whose mantra is &quot;show me the code,&quot; the code is here in spades. Flipping through the book you find very few pages that do not contain Python code (and many of them are displaying the &lt;i&gt;output&lt;/i&gt;&amp;nbsp;from Python code).&lt;br /&gt;
&lt;br /&gt;
Wes McKinney took the sensible decision to focus on Python 2.7, which is what is currently deployed by the vast majority of the scientific and analytical communities. The quality of the writing and the recent welcome news that matplotlib** is now ported to Python 3 will, I am sure, make a Python 3 update a popular choice in coming years.&lt;br /&gt;
&lt;br /&gt;
If you want to understand how you can use Python as an analytical tool then I heartily recommend this book.&lt;br /&gt;
&lt;br /&gt;
&lt;span&gt;* An Amazon Web Services account is required to use this service, and will be charged for your computations&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;** This means the standard &quot;Scientific tool chain&quot; is now available for Python 3&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=WlygopRZ-dc:NuJuYAl6Kpo: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=WlygopRZ-dc:NuJuYAl6Kpo:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=WlygopRZ-dc:NuJuYAl6Kpo:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/WlygopRZ-dc&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">&quot;Any sufficiently advanced technology is indistinguishable from magic&quot; -- Arthur C Clarke
&lt;br /&gt;
Musings from the technological frontier</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2013-05-16T00:22:18+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Building New Communities</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/Ub8HUq7S7Pg/building-new-communities.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-2035271169307114405</id>
		<updated>2012-11-17T16:18:22+00:00</updated>
		<content type="html">&lt;br /&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;b&gt;&lt;span&gt;[This post is based on a keynote talk to the PyCon DE conference on November 1, 2012]&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;
&lt;b&gt;&lt;span&gt;[UPDATE: Nov 17, 2012: The video of this talk is at&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;b&gt;http://pyvideo.org/video/1479/building-new-communities]&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
Good afternoon, and thank you for inviting me. It’s always intimidating to talk to an audience which is so technically capable. Today, though, I am hoping that we can look at a non-technical topic that has implications for everyone who is interested in Python: how do we promote the Python language and improve the development process?&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;b&gt;DO EXISTING COMMUNITIES WORK?&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Let me begin by saying that I have invested huge amounts of time in the Python community, and I believe that it has a well-deserved reputation as one of the more welcoming open source communities. So today I am talking more broadly than just Python. What I say applies, I believe, to many open source communities.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
This talk is being given at an unprecedented time in human history. Clearly these things are a matter of interpretation, but nowadays it’s hard to find someone that doesn’t agree that the modern world is failing to meet the needs of many of its inhabitants.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Historically, we are living in strange times, The world human population reached 7 billion, depending on which figures you choose to believe, between October 2011 and March 2012, only twelve years after it reached 6 billion. According to one UN estimate it’s possible that population will reach ten billion before reaching any kind of stability, and that population in Africa could triple in this century. However you interpret these figures it is obvious that most governments are going to be struggling with population growth in a world where they are already finding it difficult to manage things to everyone’s satisfaction.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
So I have a lot of questions, and not many answers. Being a geek, my approach attempts rationality—we have to take into account what we know about human behavior, differences between the various national and political cultures in which people live, and so on. In an increasingly crowded world it is easy to feel threatened by governmental and economic systems that are posited on continuous growth.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
When I was young an organization called the Club of Rome produced a report called “The Limits to Growth,” positing that the finite nature of many resources could, if growth were not checked, lead to cataclysmic failures in supply of the very things that keep us alive: clean air, clean water, and nutritious food. This is where climate change deniers got their start, and yet from recent work it appears that the report was, within its limitations, a very accurate projection of certain futures.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
My own vision of the future tends, I must admit, towards the catstrophic. I think it is entirely possible that the human race will wipe itself out simply by continuing to foul its own nest and ignoring the toxic environment it is creating. So I see it as important to try and bring this to people’s attention, and to do what I can to ensure that we (the human race) build a sustainable future for ourselves and the other species we have to share this huge ball of mud we call Earth with.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;b&gt;HEY, ISN'T THIS PYCON?&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
All of this might seem a very long way from our little open source world. I can already hear people thinking that I am abusing my position as a keynote speaker to stand on a political soap box and peddle my socialistic ideas. I admit I am a socialist, and those who know me also know that I am happy to stand on a soap box at times. But this is not one of those times.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Context, however, is everything. So I want to place my remarks today in the context of a world that isn’t working, that isn’t equitable, and in which ever larger divisions are opening up: between the poor and the rich in almost any country you like to name, between poor countries and rich countries, and so on. Huge amounts of resource are being wasted on machinery to wipe each other out. This is particularly noticeable in my current home country, the USA, which has 11% of the world’s population and yet is responsible for over 40% of all military expenditures, more than the next 14 top-spending countries put together. One might wonder what they are afraid of, but these expenditures certainly give them clout in the geopolitical sphere.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Open source communities, the Python community included, have growth problems of their own. According to &lt;a href=&quot;http://dirkriehle.com/2008/03/14/the-total-growth-of-open-source/&quot; target=&quot;_blank&quot;&gt;Armit Deshpande and Dirk Riehle&lt;/a&gt; the number of lines of open source code is growing exponentially. This is a management problem of some magnitude, which is not being addressed at the moment. They suggest that open source applications generated revenues of $1.8 billion in 2006, and certainly growth has continued unimpeded since. Of course that $1.8bn represented only about three-quarters of one percent of total software revenues, so there is still a long way to go.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.slideshare.net/timoreilly/the-clothesline-paradox-and-the-sharing-economy-pdf-with-notes-13685423&quot; target=&quot;_blank&quot;&gt;Tim O'Reilly made a sensible case this year&lt;/a&gt; that open source is responsible for&amp;nbsp;increasing small business revenues of a single hosting company’s user base by $180 billion&amp;nbsp; And, of course, &amp;nbsp;many proprietary software products nowadays contain significant open source components.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;b&gt;GET PAID TO BUILD STUFF?&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
I have said many times that the emergence of open source represents a new economic phenomenon. It’s as though, when railways were needed in the United States, a bunch of people had said “You know, that’s a great idea. Let’s go build a railway system,” taken up their picks and shovels and headed off to work. Of course you can’t build a railway without access to heavy engineering, which is arguably difficult to open source. Similarly, most individuals would not find it cost-effective to make their own computers from scratch, or to interconnect them in the way that the infrastructure of the Internet does.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Just the same, the emergence of Linux as a powerful force in the software world, and the somewhat anarchic, less-than formal management of the whole Internet (despite the belief of many US politicians that the Internet should be managed by the US as a divine right) should convince us that it’s possible for individual and group initiatives to take hold and prosper in today’s rather strained commercial environments.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
I understand that open source is not the exclusive domain of unpaid experts. Nowadays a lot of companies are paying programmers and other staff to assist with the creation of open source software projects. Many different models are used to try and recoup the investments made, but the fact remains: it is now commonly accepted that there is value to creating common infrastructure whose presence benefits a large proportion of the community rather than a single individual or organization. Of course such ideas often seem, particularly in the USA, socialistic and therefore suspect, but it is still true that large companies like HP, IBM and Microsoft are enthusiastically involved in myriad open source projects. They aren't generally thought of as having socialist tendencies.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;b&gt;HOW IS SOFTWARE BUILT?&lt;/b&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; 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://www.multunus.com/images/CopyofBalancedswdevelopment-e1334671302237.png&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;290&quot; src=&quot;http://www.multunus.com/images/CopyofBalancedswdevelopment-e1334671302237.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot;&gt;http://www.multunus.com/2011/02/software-development-as-a-balance&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Here’s a fairly typical example of the “software development lifecycle.” It lists a large number of activities and requirements, which deserve to be looked at in detail.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Whether all these activities are strictly necessary or not could be a pleasant discussion over drinks, but I get the definite impression that many open source projects aren’t engaged in any kind of formal process. This freedom, of course, is one of the things that attracts many people into the open source world, and I would be the last person to suggest that unnecessary work should be involved in software production. Nevertheless, open source projects are predominantly run vby programmers, and often all project members are programmers.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;b&gt;WHO BUILDS SOFTWARE?&lt;/b&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; 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://www.ambysoft.com/artwork/agileTeamLarge.jpg&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;310&quot; src=&quot;http://www.ambysoft.com/artwork/agileTeamLarge.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot;&gt;http://www.ambysoft.com/essays/agileRoles.html&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;p4&quot;&gt;
This is a typical conception of the way software is developed in the agile development world. There are many different ways to think about the development process. Arguably, none of them is specifically right or wrong. But when you think about commercial projects the size of Python, there will be many more people involved than just programmers. So Python, like most other open source projects, has to press developers into service to fill the other roles, or leave them unfilled.&lt;br /&gt;
&lt;br /&gt;
WE need to think about whether this works to the&amp;nbsp;ultimate&amp;nbsp;advantage of our projects, or whether it is really a rather inefficient way to produce software.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;b&gt;SOME DEVELOPER ROLES&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-z3IiTo1vuI0/UJJEtOEwISI/AAAAAAAABXo/kNhovmCuwE4/s1600/2012-11-01_10-45-09.png&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;213&quot; src=&quot;http://4.bp.blogspot.com/-z3IiTo1vuI0/UJJEtOEwISI/AAAAAAAABXo/kNhovmCuwE4/s400/2012-11-01_10-45-09.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
Above are just some of the roles that a large-ish software development requires. I would argue that lots of the time projects focus largely or even solely on the programming task, with some design work. Many of the other roles do not offer attractive work for developers, who therefore ignore the need to fill them, often to the project’s great detriment.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
A prime example here is the Python documentation. Good as it is in comparison with many other open source projects (and it &lt;i&gt;is&lt;/i&gt;&amp;nbsp;good, because&amp;nbsp;there has been a lot of hard work put in on it), it still sucks. Its organization is mostly based on a fifteen-year-old structure, back when Python was a smaller and somewhat different language. I still have no idea why, when I want documentation on the Python standard types (int, list, dict, and so on) I have to look in the Standard Library documentation. They are available without any need for an import statement, so why are they documented with the library?&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Of course anyone who has used Python seriously for more than a year knows these things, and can usually find out where to look for the information they need, but this is entirely the wrong emphasis. The first need for documentation is when you are learning a language, and then the&amp;nbsp;information&amp;nbsp;you need should be readily available. Who is the advocate for a rewrite or reorganization of the documentation? Nobody in the current development team relishes such a task, because we don’t have technical authors and editors as a part of our community. And yet this issue causes learners way more pain than it should, and even turns people away from the language.&lt;span class=&quot;Apple-tab-span&quot;&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
This brings me to my central thesis: if we don’t broaden our community to include such people we are unlikely to achieve the world domination we all jokingly feel that Python could achieve. I know from my work over the last eighteen years, and from visiting Python gatherings like this one all over the world, that Python is poised for massive growth. It would be possible, if a concerted effort was made, to make Python the first programming language of choice for literate students. The world has woken up to the fact that computational thinking is an important skill in today’s complex societies, and some feel that Python is its ideal expression.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
So, do we want to slam the doors, say “No, we like things the way they are, we aren’t going to change”? I suspect that some developers will feel that way. But as a PSF director I have to be mindful of our duty to promote the development of the language and grow the international community, and so I have to force myself to look for deficiencies than can be rectified. This means looking outwards, and trying to include people who can fill the necessary roles.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
The alternative, of course, is either to ignore the need for a role to be filled or to have someone fill it whose time would be better spent writing code. Neither is an entirely satisfactory solution.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;b&gt;BEING MORE INCLUSIVE&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
Sarah Novotny, one of the OSCON conference chairs, wrote of &lt;a href=&quot;http://radar.oreilly.com/2011/08/open-minds-and-open-source-community.html&quot; target=&quot;_blank&quot;&gt;her experience at the 2011 conference&lt;/a&gt;: &quot;We must challenge the idea that if someone really wants to use a piece of software, he or she will be willing to slog through half-written documentation, the actual code base and an unkind user interface.&quot;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
This is an approach that I have tried to promote to Python developers, with rather limited success. I can think of several reasons why this should be so. Here are some classic signs that the &lt;i&gt;status quo&lt;/i&gt; is being defended:&lt;/div&gt;
&lt;ul class=&quot;ul1&quot;&gt;
&lt;li class=&quot;li3&quot;&gt;Considering the cost of switching before you consider the benefits&lt;/li&gt;
&lt;li class=&quot;li3&quot;&gt;Highlighting the pain to a few instead of the benefits for the many&lt;/li&gt;
&lt;li class=&quot;li3&quot;&gt;Focusing on short-term costs instead of long-term benefits, because the short-term is more vivid for you&lt;/li&gt;
&lt;li class=&quot;li3&quot;&gt;Embracing sunk costs&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;p3&quot;&gt;
We need to try and broaden our development community to include people with the necessary skills, even though we aren't necessarily very comfortable getting close to them. This makes sense to me as a historical perspective: back in &quot;the old days&quot;, using an open source project was highly likely to involve you as a contributor as well. Nowadays there are many other roles for contributors to fill: bug reporters, technical writers, bloggers, testers, and I am sure all you core Python developers have your own ideas for roles that could reduce &lt;b&gt;your&lt;/b&gt; workload.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
David Eaves of Mozilla corporation has done a lot of work on how software communities can use metrics to improve their development process and monitor community involvement. &lt;a href=&quot;http://www.youtube.com/watch?v=qOB6J4E53Hc&amp;amp;feature=BFa&amp;amp;list=PL93FC98105B19725C&amp;amp;index=21&quot; target=&quot;_blank&quot;&gt;He asks relevant questions&lt;/a&gt; like “why are bugs in this section of the code taking twice as long to be reviewed?” and “who has contributed consistently over the last 18 months, but not in the last 30 days?”&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
If we are prepared to answer questions like that we can take the information, both qualitative and quantitative, and then use it to continue to improve our communities.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;b&gt;INVOLVING THE COMMUNITY&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
We must accept that not every member of the community wants to be involved outside a fairly narrow specialism. This is fine with me: I would much rather have contented community members contributing their skills than seeing members pressed to leave their comfort zone.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
At the same time, there is considerable evidence that an &lt;b&gt;inability to contribute&lt;/b&gt; is a source of frustration to would-be active members. So if we want to grow our community we need to be welcoming and, dare I say, open. We need to make sure that the barriers to entry into our community are as low as possible, and that people whose ideas may not yet be well-informed do not find a hostile environment when they join.&lt;br /&gt;
&lt;br /&gt;
The forthcoming revision of the &lt;a href=&quot;http://python.org/&quot; target=&quot;_blank&quot;&gt;python.org web site&lt;/a&gt; is an attempt to democratize the content and lower the barriers to making a contribution. The intention is to allow contributors to directly affect the content in their area of competence, without requiring mediation from a &quot;webmaster&quot; team who are familiar with the gory internal technical details of the site. More such initiatives are required.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;b&gt;REACHING OUT&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
So, it's important to reach out to the people with the skills to make our community, and our software, better: more user-friendly, more robust, better documented, and so on. The existing community does a fantastic job, but think how much better things could be if we added new skills by growing the community outside its current demographic. While one of the advantages of open source, to many participants, is its lack of corporate rules and regulations, we nevertheless should accept that we do face many of the same problems that businesses do. If we can find new and creative solutions to those problems then that's great. If we can't, however, we shouldn't necessarily ignore the solutions that have already been developed in more traditional environments.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Besides wanting to increase the size of the existing Python community, I would also like to see the Python world reaching out more determinedly to groups supporting specific applications areas such as accounting, law, the conference industry, the print industry, the transport industry, the aerospace industry, and so on.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
The scientific community is a stellar example of the sort of collaborations I envisage. There, the community members are mostly not interested in Python for its abstract beauty, and don't have any ambition or desire to contribute to the core. They use Python because it has been demonstrated to be an effective tool for solving their problems. We need to remember that's the motivation of almost all users outside the development community.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
In my secret life as a conference organizer I am using Python in the shape of Eldarion's Symposion project. While it does currently have many failings, my approach is to use it intensively, and feed back the problems to the developers for fixes. As funds become available we intend to invest in improvements that will make our job as conference organizers easier and more effective. I am hoping that eventually, once we have together built a project that non-specialist users can be happy with, Eldarion and The Open Bastion will find a market among the small to medium-sized conferences, and another industry will start to fall under Python's sway.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Repeating such efforts across many industries is, in my opinion, the best way to make Python popular, and its many existing successes are a stable platform on which to base this work.&amp;nbsp; This will involve effort, since we have to explain open source to people who are not as familiar as we are with the milieu, and whose interest in it is limited to the areas in which it can help them get their jobs done.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;b&gt;TAKING RESPONSIBILITY&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Python is a mature technology, and it's time to consider it, if not exactly a finished work, at least as something that can be presented as a feature-complete tool for use in many different application areas. The UK government, having accepted that its computer education has gone through a period in the &quot;dark ages,&quot; has accepted that computational thinking is a core skill in today's world. It looks as though Python will be adopted aggressively as a teaching language. I hope that success will be mirrored in many other countries.&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
If we are prepared to engage others with different skill sets from our own, and listen to their needs, we can build new communities who will complement our existing skill set and help us promote Python world wide in a multitude of application areas. The benefits for the Python community, though, are only a tiny portion of the gains to be made.&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
I mentioned at the start of my talk that the world is demonstrably broken. Central governments have neither the resources nor the imagination nor the flair to apply global solutions to local problems. It seems self-evident to me that the best way to solve local problems is locally, and so we need to persuade these governments to release some of their control and their funding to the communities with the power to solve those problems.&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
Eric Sterling gave &lt;a href=&quot;http://eric%20sterling%20gave%20a%20very%20engaging%20keynote%20at%20djangocon%20this%20year%20in%20which%20he%20suggested%20that%20it%20was%20important%20for%20a%20much%20broader%20cross-section%20of%20the%20population%20to%20make%20their%20needs%20known./&quot; target=&quot;_blank&quot;&gt;a very engaging keynote at DjangoCon this year&lt;/a&gt; in which he suggested that it was important for a much broader cross-section of the population to make their needs known.&amp;nbsp;As a group who only have to see an itch to start thinking about how to scratch it, I think that open source devotees are in a position to provide some valuable answers to the question of how we fix some of today's complex problems. This means leaving their comfort zone, reaching out and engaging with government and commerce at all levels,&amp;nbsp;and I want to persuade open source communities to use their considerable skills to do so. The world is broken, but I think with determination and goodwill we can help to fix it.&lt;br /&gt;
&lt;br /&gt;
This is an exciting time to be a Python programmer!&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=Ub8HUq7S7Pg:E64HurUb3qY: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=Ub8HUq7S7Pg:E64HurUb3qY:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=Ub8HUq7S7Pg:E64HurUb3qY:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/Ub8HUq7S7Pg&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">&quot;Any sufficiently advanced technology is indistinguishable from magic&quot; -- Arthur C Clarke
&lt;br /&gt;
Musings from the technological frontier</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2013-05-16T00:22:18+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">IMAPClient 0.9.1</title>
		<link href="http://freshfoo.com/blog/IMAPClient-0.9.1"/>
		<id>http://freshfoo.com/blog/2012/11/12/IMAPClient-0.9.1</id>
		<updated>2012-11-12T22:52:00+00:00</updated>
		<content type="html">&lt;p&gt;IMAPClient 0.9.1 is out! In this release:&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;OAUTH2 support: OAUTH v1 is still supported by Gmail but is now
deprecated. Thanks to Zac Witte for the patch for version 2 support.&lt;/li&gt;
&lt;li&gt;Stream support: It is now possible to have IMAPClient run an
external command to establish a connection to an IMAP server. This
is useful for exotic connection or authentication setups. Thanks to
Dave Eckhardt for the original patch.&lt;/li&gt;
&lt;li&gt;livetest updates to deal with the way Gmail now handles with new
messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the &lt;a class=&quot;reference external&quot; href=&quot;http://imapclient.freshfoo.com/browser/NEWS&quot;&gt;NEWS&lt;/a&gt; file and &lt;a class=&quot;reference external&quot; href=&quot;http://imapclient.readthedocs.org/&quot;&gt;manual&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;As always, IMAPClient can be installed from PyPI (&lt;tt class=&quot;docutils literal&quot;&gt;pip install
imapclient&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;.&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>2013-06-19T00:22:11+00:00</updated>
			<rights type="html">Copyright 2009 Menno Smits</rights>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Introducing: HUGEpic - a web app for showing massive pictures</title>
		<link href="http://www.peterbe.com/plog/introducing-hugepic.io"/>
		<id>http://www.peterbe.com/plog/introducing-hugepic.io</id>
		<updated>2012-11-03T10:52:16+00:00</updated>
		<content type="html">&lt;p&gt;So here's my latest little fun side-project: &lt;strong&gt;HUGEpic.io&lt;/strong&gt; &lt;a href=&quot;http://hugepic.io/&quot;&gt;http://hugepic.io&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/dc/0c/dc0cfaa66883636d7d8df02c95f56d8b.jpg&quot; title=&quot;Zoomed in on Mona Lisa&quot;&gt;&lt;img class=&quot;floatright&quot; src=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/1b/b5/1bb5545e831a8523d638c6386f75cd9d.jpg&quot; alt=&quot;Zoomed in on Mona Lisa&quot; width=&quot;100&quot; height=&quot;75&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
It's a web app for uploading massive pictures and looking at them like maps.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;The advantages with showing pictures like this are:&lt;br /&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you only download what you need &lt;/li&gt;
&lt;li&gt;you can send a permanent link to a picture at a particular location with a particular zoom level &lt;/li&gt;
&lt;li&gt;you can draw annotations on a layer on top of the image&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the code is &lt;a href=&quot;https://github.com/peterbe/tiler&quot;&gt;here on Github&lt;/a&gt; and as you can see it's a &lt;a href=&quot;http://www.tornadoweb.org/&quot;&gt;Tornado&lt;/a&gt; that uses two databases: &lt;a href=&quot;http://www.mongodb.org/&quot;&gt;MongoDB&lt;/a&gt; and &lt;a href=&quot;http://redis.io/&quot;&gt;Redis&lt;/a&gt; and when it connects to MongoDB it uses the new Tornado specific driver called &lt;a href=&quot;http://emptysquare.net/motor/&quot;&gt;Motor&lt;/a&gt; which is great.&lt;br /&gt;
&lt;/p&gt;
&lt;!--split--&gt;

&lt;p&gt;Before I get to the juicy client side stuff, let me talk about something awesome in between Tornado and Javascript, namely: &lt;a href=&quot;http://python-rq.org/&quot;&gt;RQ&lt;/a&gt;&lt;br /&gt;
It's an awesomely simple python message queue that only works with Python, Redis and on UNIXy systems. All checks. My only real experience with message queues has honestly been with &lt;a href=&quot;http://celeryproject.org/&quot;&gt;Celery&lt;/a&gt; which is also great but a right pain compared to RQ. With RQ, all I do is reduce the heavy tasks down to pure python functions. For example, &lt;a href=&quot;https://github.com/peterbe/tiler/blob/master/server/utils.py#L80&quot;&gt;make_thumbnail()&lt;/a&gt; then I simply do this:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;utils&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make_thumbnail&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;rq&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Queue&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;redis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;job&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enqueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;make_thumbnail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;extension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'static_path'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and that's it. Starting &lt;code&gt;rqworker&lt;/code&gt; on the command line (from somewhere where &lt;code&gt;__import__('utils.make_thumbnail')&lt;/code&gt; makes sense) and we're off!&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;You might think that using a message queue is all fancy pants and just something I need to bother myself with because of Tornado's eventloop nature. But no, it's so much more than that. When a massive 5 Mb JPG is uploaded, a little algorithm is figuring out roughly how many zoom levels that can be used and what ALL 256x256 tiles are going to be for each resized version of the original. Then it needs to generate a thumbnail to represent that JPG and all the tiles and the thumbnail need to go through an optimizer (I'm using &lt;code&gt;jpegoptim&lt;/code&gt; and &lt;code&gt;optipng&lt;/code&gt;).&lt;br /&gt;
Lastly, to be able to serve all tiles from a fast CDN I have to upload every single tile to a Reduced Redundancy Amazon S3 storage that the Amazon CloudFront CDN is hooked up to. This might sometimes fail due to network hickups and must be resilient to continue where it left off.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;All of that stuff takes a very long time but it's made it much easier and much more comfortable thanks to RQ.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Now, on the front end. The genesis inspiration to this was a library called &lt;a href=&quot;http://polymaps.org/&quot;&gt;Polymaps&lt;/a&gt; which isn't bad but when I later switched to &lt;a href=&quot;http://leafletjs.com/&quot;&gt;Leaftlet&lt;/a&gt; I was blown away. It was lighter, smoother running and has an absolutely stunning &lt;a href=&quot;http://leafletjs.com/reference.html&quot;&gt;API&lt;/a&gt; that even I could understand.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;And that led me to find another amazingly neat library, for Leaflet, called &lt;a href=&quot;https://github.com/jacobtoye/Leaflet.draw&quot;&gt;Leaflet.draw&lt;/a&gt; which makes it really easy to add tools for drawing on the pictures. You can draw lines, rectangles, circles, polygons and drop markers. And for all of them it was relatively easy to bind cute popup bubbles so you can type in comments like &lt;a href=&quot;http://hugepic.io/16169c944#4.00/79.25/-40.43&quot;&gt;this&lt;/a&gt; or &lt;a href=&quot;http://hugepic.io/f0a0955c9#4.00/-14.05/-7.29&quot;&gt;this&lt;/a&gt;.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;And lastly, there's &lt;a href=&quot;https://www.filepicker.io/&quot;&gt;Filepicker&lt;/a&gt;. It's a brilliant web service that simply takes care of your uploads. Uploading a 8 Mb JPG through a little file upload form not only takes an incredibly long time, it's fragile and has no good default UX. Filepicker takes care of all of that and makes it possible to upload files the way you want it. For example, if you use Google Drive to back up your massie pictures, Filepicker can handle that. And Dropbox. And Box. And of course, regular drag-and-drop uploads but with a lovely progress bar indicator and thumbnail preview.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/30/fe/30fea9beb1cbab3608a8a2231369e08b.jpg&quot; title=&quot;Uploading by URL&quot;&gt;&lt;img class=&quot;floatright&quot; src=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/23/9b/239b8a15c318d067a36b9002a3fffe8c.jpg&quot; alt=&quot;Uploading by URL&quot; width=&quot;100&quot; height=&quot;44&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
There's also upload by simply &lt;a href=&quot;http://hugepic.io/upload&quot;&gt;entering a URL&lt;/a&gt;. So, try find a picture on &lt;a href=&quot;http://www.google.com/search?num=10&amp;amp;hl=en&amp;amp;site=imghp&amp;amp;tbm=isch&amp;amp;source=hp&amp;amp;biw=1022&amp;amp;bih=637&amp;amp;q=landscape&amp;amp;oq=landscape&amp;amp;gs_l=img.3..0l10.1581.2845.0.3092.9.7.0.2.2.0.182.464.6j1.7.0...0.0...1ac.1.GlDiQNB4ei8#q=landscape&amp;amp;num=10&amp;amp;hl=en&amp;amp;site=imghp&amp;amp;tbs=imgo:1,isz:lt,islt:10mp&amp;amp;tbm=isch&amp;amp;source=lnt&amp;amp;sa=X&amp;amp;ei=N8OVUJTGO6a0igL6loGIDg&amp;amp;ved=0CCQQpwUoBA&amp;amp;bav=on.2,or.r_gc.r_pw.r_qf.&amp;amp;fp=4c08e0c15ee58a37&amp;amp;bpcl=37189454&amp;amp;biw=1022&amp;amp;bih=637&quot;&gt;Google Images&lt;/a&gt; click on one, then in the right-hand bar right-click the URL and &quot;Copy Link Location&quot; and paste that into HUGEpic to test.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;So for a weekend project that has taken only a couple of weeks I'm quite proud. My hopes for big success is nil but it has been a great learning experience mixing interesting client-side programming, web programming and intereting CPU bound and networking challenges.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/d7/3b/d73baa9e02dcdfe990e3b1f0396118f9.jpg&quot; title=&quot;On iPhone Safari&quot;&gt;&lt;img class=&quot;floatright&quot; src=&quot;http://d1ac1bzf3lrf3c.cloudfront.net/static/cache/fb/4f/fb4f82d609c4f0a2c2498d5361c288c7.jpg&quot; alt=&quot;On iPhone Safari&quot; width=&quot;67&quot; height=&quot;100&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
Oh, and did I mention it works great on mobile too? Even the file uploading part. Thanks to Filepicker.&lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">aMaking “from lxml import etree” work with virtualenv (Python)</title>
		<link href="http://ianozsvald.com/2012/11/01/making-from-lxml-import-etree-work-with-virtualenv-python/"/>
		<id>http://ianozsvald.com/?p=1544</id>
		<updated>2012-11-01T19:00:45+00:00</updated>
		<content type="html">&lt;p&gt;&lt;strong&gt;Update &amp;#8211; these steps are overly complicated and *unnecessary*! See fizyk and Marius&amp;#8217; comments below. I&amp;#8217;ll leave this post just in case it helps anyone &amp;#8211; hopefully anyone coming here will realise it isn&amp;#8217;t hard (now) to install lxml, as long as the OS dependencies are installed&lt;br /&gt;
&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I use virtualenv for all development. Recently I was stumped with the need for the lxml module &amp;#8211; installing it using virtualenv on Linux requires a &lt;a href=&quot;http://stackoverflow.com/questions/3856468/how-to-install-libxml2-in-virtualenv/6045098#6045098&quot;&gt;bit of work&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s see the problem first:&lt;/p&gt;
&lt;pre&gt;$ virtualenv testlibxml
 New python executable in testlibxml/bin/python
 Installing distribute.............................................................................................................................................................................................done.
 Installing pip...............done.&lt;/pre&gt;
&lt;pre&gt;.../virtualenvs/testlibxml $ source bin/activate&lt;/pre&gt;
&lt;pre&gt;$ pip install lxml&lt;/pre&gt;
&lt;pre&gt;gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/home/ian/workspace/virtualenvs/testlibxml/build/lxml/src/lxml/includes -I/usr/include/python2.7 -c src/lxml/lxml.etree.c -o build/temp.linux-x86_64-2.7/src/lxml/lxml.etree.o&lt;/pre&gt;
&lt;pre&gt;In file included from src/lxml/lxml.etree.c:254:0:&lt;/pre&gt;
&lt;pre&gt;/home/ian/workspace/virtualenvs/testlibxml/build/lxml/src/lxml/includes/etree_defs.h:9:31: fatal error: libxml/xmlversion.h: No such file or directory&lt;/pre&gt;
&lt;pre&gt;compilation terminated.&lt;/pre&gt;
&lt;pre&gt;error: command 'gcc' failed with exit status 1&lt;/pre&gt;
&lt;p&gt;Following &lt;a href=&quot;http://pkimber.net/howto/python/pip/install-modules.html&quot;&gt;these instructions&lt;/a&gt; and noting to follow the instructions for *both* libxml2 and libxml (further below) I run (using this change for my local path):&lt;/p&gt;
&lt;pre&gt;./configure --with-python=/home/ian/workspace/virtualenvs/testlibxml/bin/python&lt;/pre&gt;
&lt;p&gt;And now we can start python and import libxml2&lt;/p&gt;
&lt;pre&gt;(testlibxml)ian@ian-Latitude-E6420 ~/workspace/virtualenvs/testlibxml $ python
 Python 2.7.3 (default, Aug  1 2012, 05:14:39)
 [GCC 4.6.3] on linux2
 Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
 &amp;gt;&amp;gt;&amp;gt; import libxml2 # works&lt;/pre&gt;
&lt;hr /&gt;
Ian applies Data Science as an AI/Data Scientist for companies in Mor Consulting, founded the image and text annotation API Annotate.io, co-authored SocialTies, programs Python, authored The Screencasting Handbook, lives in London and is a consumer of fine coffees.</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, the A.I. Cookbook and high-tech entrepreneurship</subtitle>
			<link rel="self" href="http://ianozsvald.com/category/python/feed/"/>
			<id>http://ianozsvald.com/category/python/feed/</id>
			<updated>2013-06-19T00:22:09+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Fastest way to thousands-commafy large numbers in Python/PyPy</title>
		<link href="http://www.peterbe.com/plog/thousands-commafy-large-numbers"/>
		<id>http://www.peterbe.com/plog/thousands-commafy-large-numbers</id>
		<updated>2012-10-13T18:32:53+00:00</updated>
		<content type="html">&lt;p&gt;Here are two perfectly good ways to turn &lt;code&gt;123456789&lt;/code&gt; into &lt;code&gt;&quot;123,456,789&quot;&lt;/code&gt;:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;locale&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setlocale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LC_ALL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'en_US.UTF-8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;','&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123456789&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'123,456,789'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123456789&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'123,456,789'&lt;/span&gt;    
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Which one do you think is the fastest?&lt;br /&gt;
&lt;!--split--&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Easy, write a benchmark:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'seconds'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And, drumroll, the results are:&lt;br /&gt;
&lt;/p&gt;
&lt;pre&gt;
peterbe@mpb:~$ python benchmark.py
f1 19.4571149349 seconds
f2 6.30253100395 seconds
&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;f2&lt;/code&gt; one looks very plain and a good candidate for &lt;a href=&quot;http://pypy.org/&quot;&gt;PyPy&lt;/a&gt;:&lt;br /&gt;
&lt;/p&gt;
&lt;pre&gt;
peterbe@mpb:~$ pypy dummy.py
f1 14.367814064 seconds
f2 0.77246594429 seconds
&lt;/pre&gt;

&lt;p&gt;...which is &lt;strong&gt;800% speed boost&lt;/strong&gt; which is cute. It's also kinda ridiculous that each iteration of &lt;code&gt;f2&lt;/code&gt; takes &lt;code&gt;0.0000008 seconds&lt;/code&gt;. What's that!?&lt;/p&gt;
&lt;p&gt;An obvious albeit somewhat risky optimization on &lt;code&gt;f1&lt;/code&gt; is this:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;locale&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setlocale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LC_ALL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'en_US.UTF-8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;...and now we get:&lt;/p&gt;
&lt;pre&gt;
peterbe@mpb:~$ python dummy.py
f1 16.3811080456 seconds
f2 6.14097189903 seconds
&lt;/pre&gt;

&lt;p&gt;Before you say it, yes I'm aware the &lt;a href=&quot;http://docs.python.org/library/locale.html&quot;&gt;locale&lt;/a&gt; can do much more but I was just curious and I scratched it.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Dave points out the built in function &lt;a href=&quot;http://docs.python.org/library/functions.html#format&quot;&gt;format&lt;/a&gt; (which was added in Python 2.6). So let's add it and kick ass!&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;','&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And we run the tests again:&lt;br /&gt;
&lt;/p&gt;
&lt;pre&gt;
peterbe@mpb:~$ python dummy.py
f1 16.4227910042
f2 6.13625884056
f3 0.892002105713
peterbe@mpb:~$ pypy dummy.py
f1 4.61941003799
f2 0.720993041992
f3 0.26224398613
&lt;/pre&gt;

&lt;p&gt;There's your winner!&lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">I Should Have Known Installing Windows Would Be Painful</title>
		<link href="http://feedproxy.google.com/~r/ForSomeValueOfMagic/~3/CNF0GMesZ20/i-should-have-known-installing-windows.html"/>
		<id>tag:blogger.com,1999:blog-496482.post-8192682757559689381</id>
		<updated>2012-10-12T02:38:02+00:00</updated>
		<content type="html">As a geek I tend to have a bit of hardware lying around unused, so when a neighbor told me his laptop was starting to flake I suggested he might want to borrow one from me rather than put his wallet under further strain.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Two likely candidates emerged. One was a venerable Dell Precision M6300 and the other a Lenovo ThinkPad X6. I thought both had Linux installed, so I was unpleasantly surprised to see that the Dell didn't have a bootable image on it. Never mind, I thought, I can use the ThinkPad. Alas, the person who'd installed Linux hadn't given me a record of any passwords, so I called his father and I'm expecting a message back soon enough that it didn't seem worth rooting the machine (which in retrospect seems like the best option).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Bright ideas can hit at any time, and it was now that I remembered I had both the original install disks and a Windows 7 Upgrade set. My neighbor is actually a Windows user, so it seemed like a friendly act to install Windows for him. Since the disk had nothing on it there seemed to be little harm in requesting a complete installation, which I did. After answering a few questions it was grinding away, so I went out. When I arrived back a couple of hours later the installation was almost complete, waiting for the entry of my Windows product key. Which I duly entered from the Windows 7 Upgrade box. Product key invalid.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Being of a dyslexic nature, not to mention getting on enough to be experiencing some long-sightedness, these episodes are painful for me. Suffice it to say that after three further attempts involving the use of a flashlight and a magnifying glass I was positive the product key was entered correctly. So I figured since I was installing an upgrade maybe the Windows product key required was that of my original Windows installation. So all I had to do was turn the laptop upside down and peer again. The same performance with flashlight and magnifying glass was again repeated multiple times. All no go.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
So there I was, with a stuck Windows installation. The only way out that I could see was to call Microsoft, who helpfully gave the support number in a little booklet in the Upgrade box. After I enter three or four digits to indicate I am having activation problems with Windows I am finally told that Microsoft are sorry, but they are now closed and I should call back during their normal working hours. &lt;i&gt;They do not tell me what their normal working hours are&lt;/i&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I guess I'll call back tomorrow, and bite my tongue rather than pointing out you never have any of this nonsense with Linux. When I need support there, the best in the world are available on the Internet.&lt;/div&gt;
&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?a=CNF0GMesZ20:c9bH46EBJZE: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=CNF0GMesZ20:c9bH46EBJZE:Jy2wSXVWK38&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/ForSomeValueOfMagic?i=CNF0GMesZ20:c9bH46EBJZE:Jy2wSXVWK38&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/ForSomeValueOfMagic/~4/CNF0GMesZ20&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">&quot;Any sufficiently advanced technology is indistinguishable from magic&quot; -- Arthur C Clarke
&lt;br /&gt;
Musings from the technological frontier</subtitle>
			<link rel="self" href="http://holdenweb.blogspot.com/atom.xml"/>
			<id>tag:blogger.com,1999:blog-496482</id>
			<updated>2013-05-16T00:22:18+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">hastebinit - quickly paste snippets into hastebin.com</title>
		<link href="http://www.peterbe.com/plog/hastebinit"/>
		<id>http://www.peterbe.com/plog/hastebinit</id>
		<updated>2012-10-11T05:27:12+00:00</updated>
		<content type="html">&lt;p&gt;I'm quite fond of &lt;a href=&quot;http://hastebin.com&quot;&gt;hastebin.com&lt;/a&gt;. It's fast. It's reliable. And it's got nice keyboard shortcuts that work for my taste.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;So, I created a little program to quickly throw things into hastebin. You can have one too:&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;First create &lt;code&gt;~/bin/hastebinit&lt;/code&gt; and paste in:&lt;br /&gt;
&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;

&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/python&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;urllib2&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;URL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'http://hastebin.com/documents'&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;extensions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;splitext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;extensions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;urlopen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;the_page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;the_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'key'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;http://hastebin.com/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extensions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extensions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'__main__'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then run: &lt;code&gt;chmod +x ~/bin/hastebinit&lt;/code&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Now you can do things like:&lt;br /&gt;
&lt;/p&gt;
&lt;pre&gt;
$ cat ~/myfile | hastebinit
$ hastebinit  ~/myfile
$ hastebinit ~/myfile myotherfile
&lt;/pre&gt;

&lt;p&gt;Hopefully it'll one day help at least one more soul out there!&lt;/p&gt;</content>
		<author>
			<name>Peter Bengtsson</name>
			<uri>http://www.peterbe.com/rss.xml</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>2013-06-19T00:22:06+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-US">
		<title type="html">Encrypted zip files on OSX</title>
		<link href="http://tartley.com/?p=1392"/>
		<id>http://tartley.com/?p=1392</id>
		<updated>2012-10-09T09:17:07+00:00</updated>
		<content type="html">&lt;p&gt;My passwords and other miscellany are in a plain text file within an encrypted zip. Since starting to use OSX I&amp;#8217;ve been looking for a way to access my passwords such that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I get prompted for the decryption password.&lt;/li&gt;
&lt;li&gt;The file gets unzipped, but not in the same directory, because that&amp;#8217;s synced to Dropbox, so would send my plaintext passwords to them every time I accessed them. Maybe to /tmp?&lt;/li&gt;
&lt;li&gt;The plaintext file within the zip is opened in $EDITOR.&lt;/li&gt;
&lt;li&gt;Wait for me to close $EDITOR, then remove my plaintext passwords from the filesystem.&lt;/li&gt;
&lt;li&gt;Before deleting the passwords, check if I&amp;#8217;ve updated them. If so, put the new updated version back into the original zip file.&lt;/li&gt;
&lt;li&gt;Don&amp;#8217;t forget to keep the updated zip file encrypted, using the same password as before, without prompting for it again.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I failed to find an existing app which would do all this (although I had no trouble on Linux or even on Windows.) Hence, resorting to good old Bash:&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;span&gt;#!/bin/bash&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;ZIPDIR&lt;/span&gt;=&lt;span&gt;&amp;quot;&lt;span&gt;$HOME&lt;/span&gt;/docs/org&amp;quot;&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;read&lt;/span&gt; &lt;span&gt;-s&lt;/span&gt; &lt;span&gt;-p&lt;/span&gt; &lt;span&gt;&amp;quot;Password:&amp;quot;&lt;/span&gt; key
&amp;nbsp;
&lt;span&gt;cd&lt;/span&gt; &lt;span&gt;$ZIPDIR&lt;/span&gt;
&lt;span&gt;unzip&lt;/span&gt; &lt;span&gt;-P&lt;/span&gt; &lt;span&gt;$key&lt;/span&gt; passwords.zip passwords.txt &lt;span&gt;-d&lt;/span&gt; &lt;span&gt;$TMPDIR&lt;/span&gt;
&lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt; &lt;span&gt;$?&lt;/span&gt; &lt;span&gt;!&lt;/span&gt;= &lt;span&gt;0&lt;/span&gt; &lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt; ; &lt;span&gt;then&lt;/span&gt;
    &lt;span&gt;exit&lt;/span&gt; &lt;span&gt;1&lt;/span&gt;
&lt;span&gt;fi&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;cd&lt;/span&gt; &lt;span&gt;&amp;quot;&lt;span&gt;$TMPDIR&lt;/span&gt;&amp;quot;&lt;/span&gt;
&lt;span&gt;touch&lt;/span&gt; passwords.datestamp
&lt;span&gt;$EDITOR&lt;/span&gt; passwords.txt
&lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt; passwords.txt &lt;span&gt;-nt&lt;/span&gt; passwords.datestamp &lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt; ; &lt;span&gt;then&lt;/span&gt;
    &lt;span&gt;zip&lt;/span&gt; &lt;span&gt;-P&lt;/span&gt; &lt;span&gt;$key&lt;/span&gt; &lt;span&gt;-r&lt;/span&gt; &lt;span&gt;&amp;quot;&lt;span&gt;$ZIPDIR&lt;/span&gt;/passwords.zip&amp;quot;&lt;/span&gt; passwords.txt
&lt;span&gt;fi&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;rm&lt;/span&gt; passwords.txt
&lt;span&gt;rm&lt;/span&gt; passwords.datestamp&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I don&amp;#8217;t expect this to be watertight, but seems good enough for today. I&amp;#8217;m happy to hear suggestions.&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>2013-04-25T10:22:39+00:00</updated>
		</source>
	</entry>

</feed>
