<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9320223</id><updated>2012-01-31T22:44:35.910+10:00</updated><category term='tech'/><category term='travel'/><category term='philosophy'/><category term='pulpdist'/><category term='fiction'/><category term='metablogging'/><category term='python'/><category term='kubuntu'/><category term='intarwebs'/><category term='science'/><category term='politics'/><title type='text'>Boredom &amp; Laziness</title><subtitle type='html'>&lt;i&gt;There are a couple of very, very scary things in this world.
&lt;br&gt;
The first is a bored human. Bored humans have time to indulge their curiosity, with potentially amazing results.
&lt;br&gt;
The second is a lazy human. Lazy humans can be quite inventive when it comes to figuring out how to do less work.
&lt;br&gt;&lt;br&gt;
So, here&amp;#39;s to boredom &amp;amp; laziness - two of the prime movers in human progress!&lt;/i&gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>54</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9320223.post-5675009986939198035</id><published>2012-01-31T22:44:00.001+10:00</published><updated>2012-01-31T22:44:35.918+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>WalkDir 0.3 released (for more Python versions, thanks to Shining Panda!)</title><content type='html'>&lt;a href="http://walkdir.readthedocs.org/"&gt;WalkDir&lt;/a&gt; is my Python support library that aims to make it as easy to work with filtered directory listings as it is to walk over entire directory trees with os.walk().&lt;br /&gt;&lt;br /&gt;The module's design tries to take full advantage of Python's iterator model - most of its functionality is provided by pipelined iterators that accept os.walk() style iterables and expose the same interface themselves. &lt;br /&gt;&lt;br /&gt;The only major functional change in version 0.3 is that these pipelined iterators now make sure they pass along the objects produced by the underlying iterators, and only use indexing operations to access the individual fields. Previously they would use tuple unpacking to access the directory details, which restricted the supported types to those with exactly 3 fields and also had the side effect of replacing the underlying objects with ordinary 3-tuples.&lt;br /&gt;&lt;br /&gt;I changed this mainly due to a new OS interface that is likely to be coming in Python 3.3: an &lt;a href="http://bugs.python.org/issue13734"&gt;os.walk() variant&lt;/a&gt; that produces a 4-tuple rather than a 3-tuple. The 4th value will be a file descriptor for the directory making it easier (in conjunction with new &lt;a href="http://docs.python.org/dev/whatsnew/3.3.html#os"&gt;file descriptor based APIs&lt;/a&gt; in the 3.3 os module) to write filesystem modification code that is robust against &lt;a href="http://bugs.python.org/issue4489"&gt;symlink attacks&lt;/a&gt;. By passing the underlying objects through unmodified, WalkDir is now compatible with this API - all the path based filtering will still work, but the file descriptor values will also be passed along correctly.&lt;br /&gt;&lt;br /&gt;For those that haven't seen any of my previous comments on WalkDir, the other parts of the API are just there for convenience - one factory function that constructs pipelines for you, and 3 terminal iterators that flatten out the os.walk() style triples into a simple series of paths (all paths, just the visited directories or just the file paths).&lt;br /&gt;&lt;br /&gt;The other notable change in 0.3 is the list of officially supported versions. Previously, the module was only known to work on 2.7 and 3.2+ (since they're the versions I have on my home development machine). However, thanks to a free open source account provided by the folks at &lt;a href="https://jenkins.shiningpanda.com/ncoghlan-devs-projects/job/WalkDir/"&gt;Shining Panda&lt;/a&gt;, WalkDir 0.3 is known to work on Python 2.6, 2.7 and 3.1+ (I even test it on PyPy and Stackless, just because I can). After pushing a broken package to PyPI for 0.2, I even have a &lt;a href="https://jenkins.shiningpanda.com/ncoghlan-devs-projects/job/WalkDirInstaller/"&gt;sanity check&lt;/a&gt; I can run that ensures the module can be downloaded with pip and then imported on all the supported versions.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-5675009986939198035?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/5675009986939198035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/5675009986939198035'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2012/01/walkdir-03-released-for-more-python.html' title='WalkDir 0.3 released (for more Python versions, thanks to Shining Panda!)'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-2110860213247921885</id><published>2012-01-18T19:47:00.001+10:00</published><updated>2012-01-18T19:47:40.878+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tech'/><category scheme='http://www.blogger.com/atom/ns#' term='intarwebs'/><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>Using the SOPA protests to highlight related problems in Australia</title><content type='html'>I figure this is the easiest place to publish the message I just sent to Larissa Waters, the Greens Senator that is one of Queensland's representatives in the Federal Senate. I also wrote to Yvette D'ath (our local MHR) a few days ago, but I didn't keep a copy of that one. Will this achieve anything? Probably not, but hey, at least I tried (and if none of their constituents ever write to them about it, our reps are quite entitled to assume we're all OK with them selling out the county to legacy US media interests): &lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;i&gt;Senator Waters,&lt;br /&gt;&lt;br /&gt;With today being the day Wikipedia and a wide range of other sites have either gone dark or taken other action to protest draconian internet censorship legislation making its way through the US Congress, it seems an opportune time to highlight our own government's ongoing concerning behaviour on that front.&lt;br /&gt;&lt;br /&gt;Of particular concern is their &lt;a href="http://delimiter.com.au/2012/01/17/govt-censors-secret-anti-piracy-meeting-notes/"&gt;continuing refusal&lt;/a&gt; to release details of a secretive meeting between government representatives and representatives of the same organisations that are behind the draconian US bills currently being protested. The government even &lt;a href="http://delimiter.com.au/2011/12/23/secret-piracy-talks-govt-banned-consumer-groups/"&gt;deliberately excluded&lt;/a&gt; representatives of a number of community interest organisations that sought to attend these discussions.&lt;br /&gt;&lt;br /&gt;These legacy media companies (aka horse drawn carriage manufacturers) are flailing around wildly as the rise of free and open digital communications networks (aka automobiles) threatens the cherished gatekeeper role they have enjoyed for the past few decades as media distributors. They have failed to adapt, and are increasingly being bypassed as artists, writers, musicians, comedians and other media creators find ways to use the power of the internet to connect more directly with their fans. These direct connections are great for both artists and fans, but place the intermediaries like YouTube, Apple iTunes, Amazon, BandCamp, Flickr, etc, in the role of service providers to the artists and fans rather than gatekeepers to widespread distribution. Unfortunately, instead of going gracefully into that good night, these organisations are investing inordinate sums of money worldwide in lobbying for legislation that would make the permissive, open practices of most of these new service providers a recipe for prohibitively high legal liabilities, effectively making those practices unsustainable and thus breaking the internet as we know it today.&lt;br /&gt;&lt;br /&gt;Australia already markedly shifted many intellectual monopoly policies to favour the interests of US copyright holders at the expense of Australian citizens when we signed the US-FTA some time ago. We have also participated in the secretive process of drafting the Anti-Counterfeiting Trade Agreement, which spends far more time considering digital copyright infringement than it does actual counterfeiting. The current negotiations over membership in the Trans-Pacific Partnership agreement raise legitimate fears that Australia's intellectual monopoly policy will be shifted even further towards the draconian position of the United State Trade Representative, even as those policies are being protested strongly within the US itself.&lt;br /&gt;&lt;br /&gt;In line with your &lt;a href="http://greens.org.au/policies/human-rights-democracy/community-participation-in-government"&gt;published policy&lt;/a&gt; on community participation in government, do the Greens plan to publicly question the government over their apparent willingness to place the interest of large US companies ahead of those of individual Australian citizens?&lt;br /&gt;&lt;br /&gt;Regards,&lt;br /&gt;Nick.&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-2110860213247921885?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/2110860213247921885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/2110860213247921885'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2012/01/using-sopa-protests-to-highlight.html' title='Using the SOPA protests to highlight related problems in Australia'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-4013410414190939362</id><published>2011-12-22T23:15:00.000+10:00</published><updated>2011-12-22T23:16:38.053+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>New Year Python Meme - December 2011</title><content type='html'>&lt;div class="entry-body"&gt;&lt;div&gt;&lt;div class="item-body"&gt;&lt;div&gt;I'm normally a curmudgeon about this kind of thing, but I enjoyed reading some of the other posts in this series &lt;a href="http://tarekziade.wordpress.com/2011/12/20/new-years-python-meme-2/" target="_blank"&gt;Tarek&lt;/a&gt; kicked off, so I decided to make my own contribution.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. What's the coolest Python application, framework or library you have discovered in 2011?&lt;/b&gt; &lt;br /&gt;The move to Red Hat marked my entry into the world of web development (previously I'd merely been in interested observer of that world, rather than a participant). By far my favourite discovery since making that change is &lt;a href="http://django-rest-framework.org/"&gt;django-rest-framework&lt;/a&gt; - with that, I can use my web browser to browse early iterations of my server's REST API directly, without needing to write custom clients to process the JSON data from APIs that are still in a state of flux.&lt;br /&gt;&lt;br /&gt;As a service, &lt;a href="http://readthedocs.org/"&gt;ReadTheDocs&lt;/a&gt; has been an absolute revelation - between that, code hosting &amp;amp; issue management sites like BitBucket and GitHub and of course PyPI itself, it's now possible for an open source project to have a quite respectable web presence without the developers needing to understand anything more than Sphinx, source control and the project they're working on.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. What new programming technique did you learn in 2011?&lt;/b&gt; &lt;br /&gt;REST would be the big one. I'd had some general exposure to the concept in the past, but there's no substitute for sitting down and building it into a product when it comes to understanding a programming or API design technique.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. What's the name of the open source project you contributed the most in 2011? What did you do?&lt;/b&gt; &lt;br /&gt;CPython, by far - kibbitzing on python-dev and python-ideas (and import-sig too these days), writing and reviewing several different PEPs, documentation updates, code reviews and patch applications, as well as working on my own things (including the still-in-progress integration work for the 'yield from' expression that's coming in 3.3).&lt;br /&gt;&lt;br /&gt;I also recently started up 4 separate open source projects - 3 PyPI modules to hopefully address deficiencies I see in the current standard library offerings, plus the upstream open source project for my current development efforts at Red Hat:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://contextlib2.readthedocs.org/"&gt;contextlib2&lt;/a&gt; (ContextStack has some potential as a new building block)&lt;/li&gt;&lt;li&gt;&lt;a href="http://walkdir.readthedocs.org/"&gt;WalkDir&lt;/a&gt; (the idea here is to be the "itertools for os.walk()")&lt;/li&gt;&lt;li&gt;&lt;a href="http://shell-command.readthedocs.org/"&gt;Shell Command&lt;/a&gt; (let Python handle control flow, the shell actual commands)&lt;/li&gt;&lt;li&gt;&lt;a href="https://fedorahosted.org/pulpdist/"&gt;PulpDist&lt;/a&gt; (Bringing a semblance of order to small-scale rsync mirror networks)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;4. What was the Python blog or website you read the most in 2011?&lt;/b&gt;  &lt;br /&gt;&lt;a href="http://planet.python.org/" target="_blank"&gt;Planet Python&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. What are the three top things you want to learn in 2012?&lt;/b&gt; &lt;br /&gt;From a work point of view, getting my RHCSA (Red Hat Certified System Administrator) is at the top of the list. Coming up to speed on AMQP (Advanced Message Queuing Protocol) is a close second. Finally, I want to fill in more of the gaps in my very sketchy knowledge of web UI development (i.e. HTML/CSS/Javascript).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6. What are the top software, app or lib you wish someone would write in 2012?&lt;/b&gt; &lt;br /&gt;I want to see the &lt;a href="http://readthedocs.org/docs/ncoghlan_devs-python-notes/en/latest/pep_ideas/preview_namespace.html"&gt;__preview__ namespace&lt;/a&gt; (in particular, the regex module) make it into Python 3.3. But that requires a volunteer to step up and write the PEP, write the code and generally champion the idea (if we have to wait for me to do it, there's no way it will happen before 3.4).&lt;br /&gt;&lt;br /&gt;Want to do your own list? here's how: &lt;br /&gt;&lt;ol&gt;&lt;li&gt;copy-paste the questions and answer to them in your blog&lt;/li&gt;&lt;li&gt;tweet it with the &lt;a href="https://twitter.com/#%21/search/%232012pythonmeme" target="_blank"&gt;#2012pythonmeme&lt;/a&gt; hashtag&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-4013410414190939362?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/4013410414190939362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/4013410414190939362'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/12/new-year-python-meme-december-2011.html' title='New Year Python Meme - December 2011'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-654364022669483110</id><published>2011-12-16T23:40:00.001+10:00</published><updated>2011-12-16T23:48:56.137+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Help improve the Python 3.3 Standard Library...</title><content type='html'>... and hopefully help yourself with current programming projects, too.&lt;br /&gt;&lt;br /&gt;Some recent programming activities left me underwhelmed by a few of the standard library's included batteries. This has already led to a significant revamp of the &lt;a href="http://docs.python.org/library/subprocess"&gt;subprocess module documentation&lt;/a&gt; to steer new users away from the Popen Swiss army knife (unless they really need it) and to explain the commonly needed parameters more clearly. It still needs work (the notes and warnings are far too repetitive), but it at least introduces things in the right order now (high level convenience API that most people want first, lower level Popen API that some people need second).&lt;br /&gt;&lt;br /&gt;However, for 3.3 I'd like to improve things even more in at least three areas: invocation of the system shell for administration tasks, better tools for traversing filesystem directories and programmatic management of deterministic resource cleanup (i.e. not relying on the garbage collector).&lt;br /&gt;&lt;br /&gt;Accordingly, I have 3 projects up on PyPI (with docs on ReadTheDocs and source control and issue tracking on BitBucket):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://walkdir.readthedocs.org/"&gt;WalkDir&lt;/a&gt;: os.walk() style iterators with file and directory filtering (both inclusion and exclusion), depth limiting and symlink loop detection, as well as convenience iterators to flatten os.walk() style iterators into a series of paths (either all walked paths, just the directories or just the files). I currently plan to make (at least some of) these part of the shutil module, but exactly &lt;i&gt;what&lt;/i&gt; gets added will be based on the feedback I receive on this module and its API design.&lt;/li&gt;&lt;li&gt;&lt;a href="http://shell-command.readthedocs.org/"&gt;Shell Command&lt;/a&gt;: Convenience APIs that combine subprocess invocation with string interpolation. Interpolated strings are escaped with shlex.quote() by default, with a custom conversion specifier ("!u", for unquoted) used to invoke the standard interpolation process. It also features an experimental API where I'm tinkering with the use of select.select() on subprocess pipes (I'm not sure it achieves a lot over simple blocking IO in its current form, though). The current plan for this API is that it will be added directly to the subprocess module (well, the stable and sensible parts will be, anyway - I still have my doubts about the select.select() experiment)&lt;/li&gt;&lt;li&gt;&lt;a href="http://contextlib2.readthedocs.org/"&gt;contextlib2&lt;/a&gt;: This module basically exists to let me publish and gather feedback on ContextStack, a proposed addition to contextlib for 3.3 that should make it easier to manage deterministic resource cleanup programmatically (i.e. without coupling it as directly to code layout as simple with statements do).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Feedback on any and all of these is appreciated, either here or on the respective issue trackers. It isn't a foregone conclusion that any of these APIs will be added at all, so examples of real world use cases would definitely be helpful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-654364022669483110?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/654364022669483110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/654364022669483110'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/12/help-improve-python-33-standard-library.html' title='Help improve the Python 3.3 Standard Library...'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-7842269612063719643</id><published>2011-10-08T06:03:00.001+10:00</published><updated>2011-10-08T06:03:47.624+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Correcting ignorance: learning a bit about Ruby blocks</title><content type='html'>Gary Bernhardt pointed out at PyCodeConf that I didn't know Ruby even half as well as I should if I wanted to really understand why Ruby programmers rave about blocks so much (I started this before his talk, but it touches on his key point about the centrality of blocks to Ruby's design, and Python's lack of a similarly endemic model for code interleaving). So I set about trying to fix that (at least, to the extent I can in 24 hours or so). Unsurprisingly (since I'm not interested in becoming a Ruby programmer at this point in time), I approached this task more in terms of what it could teach me about Python (and its limitations) rather than in figuring out the full ins and outs of idiomatic Ruby. So feel free to bring it up in the comments if you think I've fundamentally mischaracterised some aspect of Ruby here.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The first distinction: two kinds of function&lt;/h2&gt;It turns out the first distinction shows up at quite a fundamental level. Ruby has two kinds of function: named methods and anonymous procedures. The semantics of these are quite different, most notably that named methods create their own local namespace, while anonymous procedures just use the namespace of the method that created them (so they're almost like ordinary local code).&lt;br /&gt;&lt;br /&gt;Python also has two kinds of function: ordinary functions and generator functions. The name binding semantics are identical, but the invocation style and semantics are very different. Lambda expressions and generator expressions provide syntax for defining these inside an expression, but under the hood the semantics are still the same as those of the statement versions.&lt;br /&gt;&lt;br /&gt;The closest you can get to a Ruby style anonymous procedure in Python is to create a named inner function and declare every otherwise local variable explicitly 'nonlocal' (in Python 3 - nonlocal declarations aren't available in Python 2). Then all name binding operations in the inner scope would also affect those names in the outer scope.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Actually, make that three kinds of function&lt;/h2&gt;The named method vs anonymous procedure distinction actually doesn't fully capture Ruby's semantics. Blocks (which is what I was most interested in learning about), add a new set of semantics that don't apply to the full object versions: they not only use the namespace of the defining method for their local variables, but their parameters are pass-by-reference (so they can rebind names in the calling namespace) and their control flow can affect the calling method (i.e. a return from a block will cause the calling method to return, not just the block itself). While somewhat interesting, I don't think these are actually all that significant - the core semantic difference is the one between Ruby's anonymous closures and Python's generators, not the dynamic binding behaviour of blocks.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The implications: blocks versus coroutines&lt;/h2&gt;This initial difference in the object model for code execution has created a fundamental difference in the way the two languages approach the problem of interleaving distinct pieces of code. The Ruby way is to define a separate piece of the current function that can be passed to other code and invoked as if it was still inline in its original location, then resuming execution when the called operation is complete. The Python way is to suspend execution, hand control back to the invoking piece of code, and then resume execution of the current code block at a later time (as determined by the invoking code).&lt;br /&gt;&lt;br /&gt;Hence, where Ruby has specific syntactic sugar for passing a block of code to another method (do-end), Python instead has syntactic sugar for various invocation styles for coroutines (iteration via for loops, transactional code via with statements).&lt;br /&gt;&lt;br /&gt;It's also the case that coroutines are not (yet) as deeply bound into Python's semantics as blocks are into Ruby. Whereas Ruby had blocks from the beginning and defined key programming constructs in terms of them (such as iteration and transactional style code via blocks), Python instead is built around various task specific protocols that may *optionally* be implemented in terms of coroutines (e.g. for loops, the iterator protocol and generators, the with statement, the context manager protocol and the contextlib.contextmanager decorator applied to a generator).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Callback programming and hidden control flow&lt;/h2&gt;One interesting outgrowth of the Ruby approach is that callback programming actually becomes a fairly natural extension of the way the language works - since programming with blocks &lt;i&gt;is&lt;/i&gt; callback style programming, the invoking code doesn't really care if the called method runs the passed in block immediately or at some later time. Whether you consider this a good thing or a bad thing is going to depend on how you feel about the merits and dangers of hidden control flow.&lt;br /&gt;&lt;br /&gt;During the discussions that led to the introduction of the with statement in Python 2.5, Guido made a clear, conscious design decision: he wanted the possible flows of control through the function body to be visible &lt;i&gt;locally&lt;/i&gt; inside a function, without being dependent on the definitions of other methods (raising exceptions, of course, being an exception - &lt;i&gt;catching&lt;/i&gt; them, though, largely obeys this guideline). Most code is run immediately, code in if statements and exception handlers is run zero or one times, code in loops is run zero or more times, code in nested function definitions is executed at some later time when the function is called. The Ruby blocks design is the antithesis of this: your control flow is entirely dependent on the methods you call. The downside of wanting visible control flow, of course, is that iteration, transactional code and callback programming all end up looking different at the point of invocation. (If you read PEP 340, Guido's original proposal for what eventually became the with statement, and contrast it with PEP 343, the version that we finally implemented, you'll see that his original idea was a fair bit closer to Ruby's blocks in power and scope).&lt;br /&gt;&lt;br /&gt;So Ruby's flexibility comes at a price: when you pass a block to a method, you need to know what that method does in order to know how it affects your local control flow. Naming conventions can help reduce that complexity (such as the .each convention for iteration), but it does move control flow into the domain of programming conventions rather than the language definition.&lt;br /&gt;&lt;br /&gt;On the other hand, Python's choice of explicit control flow comes at a price in flexibility: callback programming looks starkly different to ordinary programming as you have to construct explicit closures in order to pass chunks of code around.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Two way data flow&lt;/h2&gt;With their functional API, blocks natively supported two-way data flow from the beginning: data was passed in by calling them, and then either returned as the result of the block or by manipulating the passed in name bindings.&lt;br /&gt;&lt;br /&gt;By contrast, Python's generators were originally output only, reflecting their target use case of iteration. You could input some initial data via parameters, but couldn't readily supply data to a running calculation. This has started to change in recent years, as generators now provide send() and throw() methods to pass data back in, and yield became an expression in order to provide access to the 'send()' argument. However, these features do not, at this stage, have deep syntactic support - there's a fairly obvious mapping from continue to send() and break to throw() that would tie them into the for loop syntax, but this capability has not garnered significant support when it has been brought up (I believe because it doesn't really help with the last major code execution model that Python doesn't provide nice native support for: callback programming).&lt;br /&gt;&lt;br /&gt;In Python 3.3, generators will gain the ability to return values, and better syntax for invoking them and getting that value, moving the language even further towards full coroutine support (see PEP 380 for details). However, that is merely the next step along the path rather than arrival at the destination. &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Reinventing blocks&lt;/h2&gt;I think the folks who accuse us of (slowly) reinventing blocks have a valid point - Python really is on the path of devising ways to handle tasks neatly with coroutines (i.e. functions that can be suspended and transparently resumed later without losing any internal state) that Ruby handles via blocks (i.e. extracting arbitrary fragments of a function body and passing them to other code). The fact that generators were &lt;i&gt;not&lt;/i&gt; built into Python from the outset but instead have been added later to make certain kinds of code easier to write does show through in a variety of ways - coroutine based code often doesn't play nicely with ordinary imperative code and vice-versa.&lt;br /&gt;&lt;br /&gt;Ruby's way has a definite elegance to it (despite the hidden control flow). I think aspiring to that kind of elegance for callback programming in Python would be a good thing, even if the semantic model is completely different (i.e. coroutine based rather than block based). The addition of actual block functionality remains unlikely, however - if they were as powerful as Ruby blocks, then it would create two ways to do too many things (with no obvious criteria to choose between the current technique and the block based technique), but if they were strictly less powerful, then reusing Ruby's block terminology would likely be confusing rather than enlightening. For better or for worse, Python is now well down the path of coroutine based programming and we likely need to see how far we can take that model rather than trying to shoehorn in yet another approach.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-7842269612063719643?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/7842269612063719643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/7842269612063719643'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/10/correcting-ignorance-learning-bit-about.html' title='Correcting ignorance: learning a bit about Ruby blocks'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-6242427849979717492</id><published>2011-09-28T02:23:00.000+10:00</published><updated>2011-09-28T02:25:55.764+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='pulpdist'/><title type='text'>Spinning up the pulpdist project</title><content type='html'>One novel aspect of the &lt;a href="http://www.boredomandlaziness.org/2011/09/mirror-all-things.html"&gt;pulpdist project&lt;/a&gt; is that it is starting with an almost completely blank slate from a technology point of view (aside from the decision to use Pulp as the main component of the mirroring network). Red Hat does have development standards for internal projects, of course (especially in the messaging space), but they're fairly flexible, leaving the individual tool development teams with a lot of options. If something ships with Fedora and/or RHEL, or is available under licensing terms that would be acceptable for inclusion in Fedora (and subsequently RHEL), then it's fair game.&lt;br /&gt;&lt;br /&gt;This post focuses on the design of the management server. I'll write up a separate post looking at the currently planned design for the Pulp data transfer plugins. &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Source Control&lt;/h2&gt;Unsurprisingly, Red Hat's internal processes are heavily influenced by Linux kernel processes. Accordingly, the source control tool of choice for new projects is Git. While I have a slight preference for Mercurial (due mainly to familiarity), I'm happy enough with any DVCS, so Git it is.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Primary Development Language&lt;/h2&gt;&lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;, of course. You don't hire a CPython core developer to get them to work on a Ruby or Perl project (although the current system I'm replacing was written in Perl). As a web application, there will naturally be some Javascript and CSS involved as well.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Web Framework&lt;/h2&gt;The main management application for pulpdist is going to be a full-scale web application. User profiles and authentication, database storage, communication with other web services, provision of a REST API, integration with the engineering tools messaging bus. Basically, micro-frameworks need not apply.&lt;br /&gt;&lt;br /&gt;While I expect Pyramid/Pylons would also have been able to do the job, I decided to go with Django 1.3. This was heavily influenced by social factors: I know a lot of Django devs that I can bug for advice, but the same is not true for Pyramid. The complexity of the whole Pyramid/Pylons/TurboGears setup is also not appealing - while veteran web developers may find the "you decide" approach a selling point, Django's batteries included approach makes it far simpler to get started quickly, and decide as I go along which pieces I should keep, discard or replace.&lt;br /&gt;&lt;br /&gt;I've heard some experienced Django developers muttering complaints about the class based views design in 1.3, but as someone coming in that is an experienced Python developer, but a relatively noobish web developer, the CBV approach seems eminently sensible, while the old function based approach looks repetitive and insane. Object oriented programming was invented for a reason!&lt;br /&gt;&lt;br /&gt;I'll admit that my perception may be biased by knowing exactly how to make multiple inheritance work the way I want it to, though :)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Web Server&lt;/h2&gt;The management server doesn't actually have that much work to do, so the basic Apache+mod_wsgi configuration will serve as an adequate starting point (any heavy lifting will be done by the individual Pulp instances, and the main data traffic on those doesn't run through their web service). WSGI provides the flexibility to revisit this later if needed.&lt;br /&gt;&lt;br /&gt;I've also punted on any web caching questions for now - the management server is low traffic and once the access to the Pulp sites is pushed out to a backend service, it should be fast enough at least for the early iterations. &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Authentication &amp;amp; Authorisation&lt;/h2&gt;The actual user authentication task will be handed off to Apache and all management application access will be restricted to Kerberos authenticated users over SSL. Django's own permissions systems will be used to handle authorisation restrictions. (The experimental prototype will use Basic Auth instead, since it is the Apache/Django integration the prototype needs to cover, not the Apache configuration for SSL and Kerberos authentication)&lt;br /&gt;&lt;br /&gt;Integration with Pulp's user access controls is via OAuth, but the design for configuration of user permissions in the Pulp servers is still TBD.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Database and ORM&lt;/h2&gt;Again, the management server isn't doing the heavy lifting in this application. The Pulp instances use MongoDB, but for the management server I currently plan to use the standard Django ORM backed by PostgreSQL. For the prototype instance, the database is actually just an SQLite3 file. I'm not quite sold on this one as yet - it's tempting to start playing with SQLAlchemy, since I've already had to hack around some of the limitations in the native ORM in order to &lt;a href="http://djangosnippets.org/snippets/2489/"&gt;store encrypted fields&lt;/a&gt;. OTOH, I already have a ton of things to do on this project, so messing with this is a long way down the priority list.&lt;br /&gt;&lt;br /&gt;Schema and data maintenance is handled using &lt;a href="http://south.aeracode.org/"&gt;South&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;HTML Templating&lt;/h2&gt;The standard Django templating engine should be sufficient for my needs. As with the ORM, it's tempting to look into upgrading it to something like Jinja2, but once again 'good enough' is likely to be the deciding factor.&lt;br /&gt;&lt;br /&gt;For data table display, I'm using &lt;a href="http://pypi.python.org/pypi/django-tables2"&gt;Django Tables 2&lt;/a&gt; and form display will use &lt;a href="http://pypi.python.org/pypi/django-uni-form"&gt;Django Uni-Form&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;REST API&lt;/h2&gt;The REST API for the service is currently there primarily as a development aid - it lets me publish the full data model to the web as soon as it stabilises (and even while its still in flux), even if the UI for end users hasn't been fully defined. This is particularly useful for the metadata coming back from the Pulp server, since it doesn't need much post-processing to be included as raw data in the management server's own REST API. The JSON interface will also allow much of the backend processing to be fully exercised by the test suite without worrying about web UI details.&lt;br /&gt;&lt;br /&gt;The design of the REST API was heavily influenced by this &lt;a href="http://readthedocs.org/docs/restful-api-design/en/latest/"&gt;Lessons Learned&lt;/a&gt; piece from the RHEV-M developers. The &lt;a href="http://django-rest-framework.org/"&gt;Django Rest Framework&lt;/a&gt; means I can just define the data I want to display as a list or dictionary and the framework takes care of formatting it nicely, including rendering URLs as hyperlinks. &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;AMQP Messaging&lt;/h2&gt;I haven't actually started on this aspect in any significant way, but the two main contenders I've identified are &lt;a href="http://www.silassewell.com/blog/tag/python-qpid/"&gt;python-qpid&lt;/a&gt; (which is what Pulp uses) and &lt;a href="http://ask.github.com/django-celery/"&gt;django-celery&lt;/a&gt; (which would also give me an internal task queue engine, which the management server is going to need - the prototype just does everything in the Django process, which is OK for experimentation on the LAN, but clearly inadequate long term when talking to multiple sites distributed around the planet). At this early stage, I expect the internal task management aspect is going to tip the decision in favour of the latter.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Testing Regime&lt;br /&gt;&lt;/h2&gt;As the foundation for the automated testing, I'm going with &lt;a href="http://devel.almad.net/docs/django-sane-testing/"&gt;Django Sane Testing&lt;/a&gt; (mainly based on the example of other internal Django projects). Michael Foord's &lt;a href="http://pypi.python.org/pypi/mock"&gt;mock module&lt;/a&gt; lets me run at least some of the tests without relying on an external Pulp instance (fortunately, the namespace conflict with Fedora's RPM building utility '&lt;a href="https://fedoraproject.org/wiki/Projects/Mock"&gt;mock&lt;/a&gt;' was recently resolved with the latter's support library being renamed to 'mockbuild').&lt;br /&gt;&lt;br /&gt;Continuous integration is an open question at this point. Pulp uses Jenkins for CI and I'm inclined to follow their lead. The other main possibility is to use &lt;a href="https://fedorahosted.org/beaker/"&gt;Beaker&lt;/a&gt;, Red Hat's internal test system originally set up for kernel testing (one key attraction Beaker offers is the ability to set up multi-server multi-site testing in a test recipe so I can run tests over the internal WAN).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Packaging&lt;br /&gt;&lt;/h2&gt;&lt;a href="https://github.com/dgoodwin/tito"&gt;Tito&lt;/a&gt; is a tool for generating SRPMs and RPMs directly from a Git repository. For my own packages, this is the approach I'm using (with handcrafted spec files). For some strange reason, the sysadmins around here like it when internal devs provide things as pre-packaged RPMs for deployment :)&lt;br /&gt;&lt;br /&gt;Packaging of upstream PyPI dependencies that aren't available as Fedora or RHEL packages is still a work in progress. I experimented with Tito and git submodules (which doesn't work) and git subtrees (which does work, but is seriously ugly). My next attempt is likely to be based on &lt;a href="http://pypi.python.org/pypi/py2pack"&gt;py2pack&lt;/a&gt;, so we'll see how that goes (I actually discovered that project by searching for 'cpanspec pypi' after hearing some of the Perl folks here extolling the virtues of cpanspec for easily packaging CPAN modules as RPMs).&lt;br /&gt;&lt;br /&gt;I also need to switch to using &lt;a href="http://pypi.python.org/pypi/virtualenv"&gt;virtualenv&lt;/a&gt; to get a clearer distinction between Fedora packages I added via yum install and stuff I picked up directly from PyPI with &lt;a href="http://pypi.python.org/pypi/pip"&gt;pip&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-6242427849979717492?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/6242427849979717492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/6242427849979717492'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/09/spinning-up-pulpdist-project.html' title='Spinning up the pulpdist project'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-1158560671114956528</id><published>2011-09-09T12:54:00.001+10:00</published><updated>2011-09-09T12:54:59.238+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='pulpdist'/><title type='text'>Mirror All The Things!</title><content type='html'>After describing the project I'm working on to a few people at PyConAU and BrisPy, I decided it might be a good idea to blog about it here. I do have a bit of an ulterior motive in doing so, though - I hope people will point out when I've missed useful external resources or applications, or when something I'm planning to do doesn't make sense to the assorted Django developers I know. Yes, that's right - I'd like to make being &lt;a href="https://www.xkcd.com/386/"&gt;wrong on the internet&lt;/a&gt; work in my favour :)&lt;br /&gt;&lt;br /&gt;The project is purely internal at this stage, but I hope to be able to publish it as open source somewhere down the line. Even being able to post these design concepts is pretty huge for me personally, though - before starting with Red Hat a few months ago, I spent the previous 12 and a half years working in the defence industry, which is about as far from Red Hat's &lt;a href="http://draft.blogger.com/goog_2071189574"&gt;"&lt;/a&gt;&lt;a href="http://draft.blogger.com/goog_2071189574"&gt;Default to Open" philosophy&lt;/a&gt; as it's possible to get.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Mirror, Mirror, On The Wall&lt;/h2&gt;The project Red Hat hired me to implement is the next generation of their internal mirroring system, which is used for various tasks, such as getting built versions of RHEL out to the hardware compatibility testing labs (and, when they're large enough, returning the generated log files to the relevant development sites), or providing internal Fedora mirrors at the larger Red Hat offices (such as the one here in Brisbane).&lt;br /&gt;&lt;br /&gt;There are various use cases and constraints that mean the mirroring system needs to operate at the filesystem level without making significant assumptions about the contents of the trees being mirrored (due to various details of the use cases involved, block level replication and approaches that rely on the transferred data being laid out in specific ways aren't viable alternatives for this project). The current incarnation of this system relies almost entirely on that venerable workhorse of the mirroring world, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;rsync&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;However, the current system is also showing its age and has a few limitations that make it fairly awkward to work with. Notably, there's no one place to go to get an overview of the entire internal mirroring setup, and the direct use of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;rsync&lt;/span&gt; means it isn't particularly friendly with other applications when it comes to sharing WAN bandwidth and the servers involved are wasting quite a few cycles recalculating the same deltas for multiple clients. Hence, the project I am working on, which is intended to replace the existing system with something a bit more efficient and easier to manage, while also providing a better platform for adding new features.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Enter Pulp&lt;/h2&gt;&lt;a href="http://pulpproject.org/"&gt;Pulp&lt;/a&gt; is an open source (Python) project created by Red Hat to make it easier to manage private &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;yum&lt;/span&gt; repositories. Via &lt;a href="http://katello.org/"&gt;Katello&lt;/a&gt;, Pulp is one of the upstream components for Red Hat's &lt;a href="https://www.redhat.com/solutions/cloud/cloudforms/"&gt;CloudForms&lt;/a&gt; product.&lt;br /&gt;&lt;br /&gt;The Pulp project is currently in the process of migrating from their original yum-specific architecture to a more general purpose &lt;a href="http://blog.pulpproject.org/2011/09/06/pulp-rearchitecture-sprint-update/"&gt;Generic Content plugin architecture&lt;/a&gt;. It's that planned plugin architecture that makes Pulp a useful basis for the next generation internal mirroring system, which, at least for now, I am imaginatively calling &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;pulpdist&lt;/span&gt; (referring to both "distribution with Pulp", since that's what the system does, and "distributed Pulp instances", since that's how the system will work).&lt;br /&gt;&lt;br /&gt;The main components of the initial &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;pulpdist&lt;/span&gt; architecture will be:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;a front-end (Django 1.3) web app providing centralised management of the entire distribution network&lt;/li&gt;&lt;li&gt;custom importer and distributor plugins for Pulp to handle distribution of tree changes within the distribution network&lt;/li&gt;&lt;li&gt;custom importer plugins to handle the import of trees from their original sources and generation of any additional metadata needed by the internal distribution plugins&lt;/li&gt;&lt;li&gt;generic (and custom, if needed) plugins to make the trees available to the applications that need them&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I'll be writing more on various details that I consider interesting as I go along. Initially, that will include my plan for the mirroring protocol to be used between the sites, as well as various decisions that need to be made when spinning up a Django project from scratch (while many of my specific answers are shaped by the target environment for internal deployment, the questions I needed to consider should be fairly widely applicable).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-1158560671114956528?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/1158560671114956528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/1158560671114956528'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/09/mirror-all-things.html' title='Mirror All The Things!'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-7154421811873266057</id><published>2011-08-27T22:16:00.000+10:00</published><updated>2011-08-28T01:41:21.762+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Open Source, Windows and Teaching Python to New Developers</title><content type='html'>A few questions and incidents recently prompted me to reflect on why I don't help with CPython support on Windows, even though I use Windows happily enough on my gaming system. Since this ended up being a rather pro-Linux article and upfront disclosure is a good thing, I'll note that while I do work for Red Hat now, that's a very recent thing - my adoption of Linux as my preferred development platform dates back to 2004 or so. I work for Red Hat because I like Linux, not the other way around :)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Availability of Professional Development Tools&lt;/h2&gt;I &lt;a href="http://mail.python.org/pipermail/python-dev/2011-August/113111.html"&gt;don't make a secret&lt;/a&gt; of my dislike of Windows as a hobbyist development platform. While Microsoft have improved things in recent years (primarily by releasing the Express editions of Visual Studio), there's still a huge difference between an operating system like GNU/Linux, which was built by developers for developers based on a foundation that was built by academics for academics, and Windows, which was built by a company that used deals with computer manufacturers to get it into end users' hands regardless of technical merit. Developers were forced to follow in order to reach that large installed user base. Those different histories are reflected in the different development cultures that surround the respective platforms.&lt;br /&gt;&lt;br /&gt;To get the same tool chain that professional Linux companies use, you don't need to do anything special - Linux distributions include the tools used to create them. If you have a distribution, you have everything you need to build applications for that distribution, including documentation. With the open source nature of the platform and almost all of the software (the occasionally binary driver notwithstanding), there's a vast range of tools out there to help you get things done (although sorting through the mass can be a little tricky sometimes, since it can be hard to tell the difference between stuff that doesn't exist and stuff that exists, but hasn't been uncovered by your research).&lt;br /&gt;&lt;br /&gt;As far as I'm aware, Mac OS X isn't quite as generous with freely available development utilities, but isn't all that far off the Linux approach (I'm not a Mac user or developer though, so there may be more hurdles than I am aware of - I recall some muttering about Apple beginning to charge a small fee for XCode. My opinion is based mostly on the fact that it seems pretty easy to find open source devs that use Macs). With the POSIX-ish underpinnings, many of the utilities from the *nix world also work in this environment.&lt;br /&gt;&lt;br /&gt;The minimum realistic standard for professional Windows development, though, is an MSDN subscription (to get full access to the OS documentation and various utilities), along with a professional copy of Visual Studio. The tools available for free (including the Express editions of Visual Studio) are clearly second rate. Even when the tools themselves are OK, the licensing restrictions on the applications they create may make them practically useless (and MS have the gall to call the GPL viral - at least the gcc team don't restrict how you license and distribute the binaries it creates). So why should a hobbyist develop for a system that thinks they should pay substantial sums for the privilege of developing for it, instead of one that welcomes all contributors, providing not only the end product, but the ingredients and recipes all for free?&lt;br /&gt;&lt;br /&gt;At the recent PyConAU sprints, one of the contributors (an existing Linux user that happened to have a Windows only laptop with them) became frustrated with getting all the necessary tools set up to work properly on Windows (configuring git+ssh for read/write access to a GitHub repo was one key point of irritation), and decided to dual boot Ubuntu on the machine instead. Twenty minutes later, she was up and running and hacking on the project she originally wanted to hack on. Granted, she already knew how to use Linux, but seriously, there's something fundamentally wrong with a platform when installing and dual-booting to a different OS is the easiest way to get a decent development environment up and running.&lt;br /&gt;&lt;br /&gt;All that ends up putting cross-platform languages like Python in an interesting position: when developing with Python, you can often get away with &lt;i&gt;not&lt;/i&gt; understanding the underlying details of your operating system, because the language runtime tries to provide a largely standardised interface on all platforms. However, many open source developers either don't use Windows at all, or genuinely dislike programming for it, so the burden of making things work properly on Windows falls on the shoulders of a comparatively small number of people, either those who genuinely like programming for the platform (yes, such people exist, I'm just not one of them), or those that are looking for any niche where they can usefully contribute and are happy enough to take on the task of improving Windows compatibility and support.&lt;br /&gt;&lt;br /&gt;I don't have particularly hard numbers to back this up (other than the skew in core developer numbers vs overall OS popularity), but my intuition is that, at least for CPython, the user:core developer ratio is orders of magnitude higher for Windows than it is for Linux or Mac OS X.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Implications for Teaching Python on Windows&lt;/h2&gt;Something cool that is going on at the moment is that a lot of folks are interested in the idea of teaching more people how to program with Python as the language used. However, the potential students (young and old) that they are wanting to teach often don't have any development experience at all and are using the most common consumer operating system (i.e. Windows). So good Windows support, and an easy installation experience are important considerations for these instructors. A request that is frequently made (with varying levels of respect and politeness), is that the official python.org Windows installer be updated to automatically adjust the PATH (or at least provide the option to do so), so that Python can be launched from the command line by typing "python" instead of something like "C:\Python27\python".&lt;br /&gt;&lt;br /&gt;If educators want that &lt;i&gt;right now&lt;/i&gt; their best bet is actually to direct their students towards the Windows versions of ActiveState's &lt;a href="http://www.activestate.com/activepython/downloads"&gt;ActivePython Community Edition&lt;/a&gt;. ActiveState add a few things to the standard installer, like PATH manipulation and additional packages (such as pywin32). They also bundle PyPM, which is a decent tool for getting PyPI packages on to Windows machines (at least, I've heard good things about it - I haven't actually used it myself). (That said, I believe I may need to caveat that recommendation a bit: as near as I can tell from their website, PyPM has been deliberately disabled for their 64-bit Windows Community Edition installer. Still, even in that case, you can easily grab additional packages direct from PyPI via "pip install" on the command line)&lt;br /&gt;&lt;br /&gt;Brian Curtin is working on adding optional PATH manipulation to the python.org installer for 3.3, and there's a chance such a change might be backported to the next maintenance releases for 3.2 and 2.7 (no promises, though). Even if it does make it in, it will still be a while before the change is part of a binary release (especially given that Brian has only just started tinkering with it).&lt;br /&gt;&lt;br /&gt;This is clearly a nice thing for beginners, especially those that aren't in the habit of tinkering with their OS settings, but I do honestly wonder how much of a difference it will make in the long run. In many ways, software development is one long exercise in frustration. You decide you want to fix bug X. But it turns out bug X is really due to bug Y. You could work around Y just to fix X, but the bigger bug would still be there. But then you discover that fixing bug Y properly requires feature Z, which doesn't exist yet, so a workaround (even an ugly one) starts to sound pretty attractive. "Yak shaving" (the highly technical term for things that you're working on solely because they're a prerequisite for what you actually &lt;i&gt;want&lt;/i&gt; to be working on) is so common it's almost the norm rather than the exception. The many and varied frustrations of trying to use Windows as a hobbyist open source developer also won't magically go away just because the python.org installer starts automating one environment variable update - as soon as people are introduced to sites like GitHub and BitBucket, they'll get to discover the joy that is SSH and source control on Windows. If they get past that hurdle, they'll likely start to encounter the multitude open source projects that don't even &lt;i&gt;offer&lt;/i&gt; Windows installers (if the project supports Windows at all), because their Windows developer count stands at a grand total of zero.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Final Thoughts&lt;/h2&gt;I hope the people teaching Python to beginners on Windows and the folks working on improving Windows support don't take this article as an attack on their efforts. I find both goals to be quite admirable, and wish those involved all the success they can find. But there are reasons I abandoned Windows as a personal development platform ~7 years ago and taught myself to use Linux instead. As far as I can tell, most of those reasons remain valid today, even after Microsoft started releasing the Express versions of Visual Studio in an attempt to stem the flood of hobbyist developers jumping ship.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.boredomandlaziness.org/2011/08/of-python-and-road-maps-or-lack-thereof.html"&gt;other day&lt;/a&gt; I called the relative lack of Windows developers in open source a vicious cycle and I stand by that. If someone can learn to program, mastering Linux is going to be comparatively easy. For anyone seriously interested in open source development, using Linux (even in a virtual machine, the way I do on my gaming laptop) is by far the path of least resistance. Getting more Windows developers in open source requires that people care sufficiently about Windows as a platform that they don't just switch to Linux, but care about open source enough to start contributing at all, and that seems to be a genuinely rare combination.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-7154421811873266057?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/7154421811873266057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/7154421811873266057'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/08/open-source-windows-and-teaching-python.html' title='Open Source, Windows and Teaching Python to New Developers'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-1425832369921237012</id><published>2011-08-24T22:37:00.000+10:00</published><updated>2011-08-24T22:37:48.289+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Scripting languages and suitable complexity</title><content type='html'>Steven Lott is a Python developer and blogger that I first came across via his prolific contributions to answering questions on Stack Overflow, and then later by reading his blog posts that appeared on Planet Python. His &lt;a href="http://homepage.mac.com/s_lott/books/python.html"&gt;Building Skills in Python&lt;/a&gt; book is a resource I've recently started suggesting newcomers to Python take a look at to see if his style works for them.&lt;br /&gt;&lt;br /&gt;Some time ago, he posted about what he called the &lt;a href="http://slott-softwarearchitect.blogspot.com/2011/05/curse-of-procedural-design.html"&gt;"Curse of Procedural Design"&lt;/a&gt;: the fact that, beyond a certain point, purely procedural code typically starts drowning in complexity and becomes an unmaintainable mess. Based on that, he then started questioning whether or not he was doing the right thing by teaching the procedural aspects of Python first and leaving the introduction of object oriented concepts until later in the book.&lt;br /&gt;&lt;br /&gt;Personally, I think starting with procedural programming is still the right thing to do. However, one of the key points of object-oriented design is that purely procedural programming &lt;i&gt;doesn't scale well&lt;/i&gt;. Even in a purely procedural language, large programs almost always define essential data structures, and functions that work on those data structures, effectively writing object oriented code by convention. Object support built into the language makes this &lt;i&gt;easier&lt;/i&gt; but it isn't essential (as large C projects like the Linux kernel and CPython itself demonstrate).&lt;br /&gt;&lt;br /&gt;Where languages like Java can be an issue as beginner languages is that by &lt;i&gt;requiring&lt;/i&gt; that all code be compiled in advance and written in an object oriented style, they set a minimum level of complexity for all programs written in that language. Understanding even the most trivial program in Java requires that you grasp the concepts of a module, a class, an instance, a method and an expression. Using a compiled procedural language instead at least lets you simplify that a bit, as you only need to understand modules, functions and expressions.&lt;br /&gt;&lt;br /&gt;But the scripting languages? By means of a read-eval-print loop in an interactive interpreter, they let you do things in the right order, starting with the minimum level of complexity possible: a single expression.&lt;br /&gt;&lt;br /&gt;For convenience, you may then introduce the concept of a 'script' early, but with an appropriate editor, scripts may be run directly in the application (giving an experience very similar to a REPL prompt) rather than worrying about command line invocation.&lt;br /&gt;&lt;br /&gt;More sophisticated algorithms can then be introduced by discussing conditional execution and repetition (if statements and loops), but still without any need to make a distinction between "definition time" and "execution time".&lt;br /&gt;&lt;br /&gt;Then, once the concept of algorithms has been covered, we can start to modularise blocks of execution as functions and introduce the idea that algorithms can be stored for use in multiple places so that "definition time" and "execution time" may be separated.&lt;br /&gt;&lt;br /&gt;Then we start to modularise data and the associated operations on that data as classes, and explore the ways that instances allow the same operations to readily be performed on different data sets.&lt;br /&gt;&lt;br /&gt;Then we start to modularise collections of classes (and potentially data and standalone functions) as separate modules (and, in the case of Python, this can be a good time to introduce the idea of "compilation time" as separate from both "definition time" and "execution time").&lt;br /&gt;&lt;br /&gt;Continuing up the complexity scale, modules may then be bundled into packages, and packages into frameworks and applications (introducing "build time" and "installation time" as two new potentially important phases in program execution).&lt;br /&gt;&lt;br /&gt;A key part of the art of software design is learning how to choose an appropriate level of complexity for the problem at hand - when a problem calls for a simple script, throwing an entire custom application at it would be overkill. On the other hand, trying to write complex applications using only scripts and no higher level constructs will typically lead to an unmaintainable mess.&lt;br /&gt;&lt;br /&gt;In my opinion, the primary reason that scripting languages are easier to learn for many people is that they permit you to start immediately with code that "does things", allowing the introduction of the "function" and "class" abstractions to be deferred until later.&lt;br /&gt;&lt;br /&gt;Starting with C and Java, on the other hand, always requires instructors to say "Oh, don't worry about that boilerplate, you'll learn what it means later" before starting in with the explanation of what can go inside a main() function or method. The "compilation time" vs "execution time" distinction also has to be introduced immediately, rather than being deferred until some later point in the material. There's also the fact that such languages are actually usually at least two languages in one: the top level "compile time" language that you use to define your data structures, functions and modules and the "run time" language that you actually use &lt;i&gt;inside&lt;/i&gt; functions and methods to get work done. Scripting languages don't generally have that distinction - the top level language is the same as the language used inside functions (in fact, that's my main criteria for whether or not I consider a language to be a scripting language in the first place).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-1425832369921237012?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/1425832369921237012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/1425832369921237012'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/08/scripting-languages-and-suitable.html' title='Scripting languages and suitable complexity'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-6235142900295197351</id><published>2011-08-24T15:16:00.006+10:00</published><updated>2011-08-26T10:14:02.102+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Of Python and Road Maps (or the lack thereof)</title><content type='html'>I gave my &lt;a href="http://www.youtube.com/watch?v=UZIq_9KgFEY"&gt;first ever full conference talk&lt;/a&gt; at PyCon AU this year, on the topic of how Python evolves over time.&lt;br /&gt;&lt;br /&gt;One notable absence from that talk is a discussion of any kind of specific 'road map' for the language as a whole. There's a reason for that: no such document exists. Guido van Rossum (as the language creator and Benevolent Dictator for Life) is the only person who could write an authoritative one and he's generally been happy to sit back and &lt;a href="http://mail.python.org/pipermail/python-dev/2011-March/108584.html"&gt;let things evolve organically&lt;/a&gt; since guiding the initial phases of the Py3k transition (which is now ticking along quite nicely and the outlook for 2.x being relegated to 'supported-but-now-legacy' status within the 2013/14 time frame is promising). &lt;a href="http://www.python.org/dev/peps/pep-0398/"&gt;PEP 398&lt;/a&gt;, the release PEP for Python 3.3 comes close to qualifying, but is really just a list of PEPs and features, with no context for why those ideas are even on the list.&lt;br /&gt;&lt;br /&gt;However, despite that, it seems worthwhile to make the effort to try to write a &lt;i&gt;descriptive&lt;/i&gt; road map for where I personally see current efforts going, and where I think the Python core has a useful role to play. Looking at the &lt;a href="http://www.python.org/dev/peps/"&gt;Python Enhancement Proposal index&lt;/a&gt; for the lists of Accepted and Open PEPs can be informative, but it requires an experienced eye to know which proposals are currently being actively championed and have a decent chance of being accepted and included in a CPython release.&lt;br /&gt;&lt;br /&gt;When reading the following, please keep in mind that the overall Python community is much bigger than the core development team, so there are plenty of other things going on out there. Others may also have differing opinions on which changes are most likely to come to fruition within the next few years.&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Always in Motion is the Future&lt;/h1&gt;&lt;h2&gt;Unicode is coming. Are you ready?&lt;/h2&gt;The Python 2.x series lets many developers sit comfortably in a pure ASCII world until the day when they have to debug a bizarre error caused by their datastream being polluted with non-ASCII data.&lt;br /&gt;&lt;br /&gt;That is only going to be a comfortable place to be for so long. More and more components of the computing environment are migrating from ASCII to Unicode, including filesystems, some network protocols, user interface elements, other languages and various other operating system interfaces. With the modern ease of international travel and the rise of the internet, even comfortable "we only speak ASCII in this office, dammit!" environments are eventually going to have to face employees and customers that want to use their own names in their own native, non-Latin character sets rather than being constrained by a protocol invented specifically to handle English.&lt;br /&gt;&lt;br /&gt;The Python 3.x series was created largely in response to that environmental transition - in many parts of the world where English isn't the primary spoken language, needing to deal with text in multiple disparate character encodings is already the norm, and having to deal regularly with non-ASCII data is only going to become more common even in English dominant areas.&lt;br /&gt;&lt;br /&gt;However, supporting Unicode correctly on this scale is something of a learning experience for the core development team as well. Several parts of the standard library (most notably the email package and wsgiref module) really only adjusted to the new Unicode order of things in the recent 3.2 release, and (in my opinion) we've already made at least one design mistake in leaving various methods on bytes and bytearray objects that assume the underlying data is text encoded as ASCII.&lt;br /&gt;&lt;br /&gt;The conversion to Unicode everywhere also came at a measurable cost in reduced speed and increased memory usage within the CPython interpreter. &lt;a href="http://www.python.org/dev/peps/pep-0393/"&gt;PEP 393&lt;/a&gt; ("Flexible String Representation") is an attempt to recover some of that ground by using a smarter internal representation for string objects.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Easier and more reliable distribution of Python code&lt;/h2&gt;Tools to package and distribute Python code have been around in various stages of usability since before the creation of distutils. Currently, there is a concerted effort by the developers of tools like pip, virtualenv, distutils2, distribute and the Python Package index to make it easier to create and distribute packages, to provide better metadata about packages (without requiring execution of arbitrary Python code), to install packages published by others, and to play nicely with distribution level package management techniques.&lt;br /&gt;&lt;br /&gt;The new 'packaging' module that will arrive in 3.3 (and will be backported to 3.2 and 2.x under the 'distutils2' name) is a visible sign of that, as are several Python Enhancement Proposals related to packaging metadata standards. These days, the CPython interpreter also supports direct execution of code located in &lt;a href="http://www.boredomandlaziness.org/2011/03/what-is-python-script.html"&gt;a variety of ways&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There's a significant social and educational component to this effort in addition to the technical underpinnings, so this is going to take some time to resolve itself. However, the eventual end goal of a Python packaging ecosystem that integrates nicely with the various operating system software distribution mechanisms without excessive duplication of effort by developers and software packagers is a worthy one.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Enhanced support for various concurrency mechanisms&lt;/h2&gt;The addition of the 'concurrent' package, and its sole member, 'concurrent.futures' to the Python 3.2 standard library can be seen as a statement of intent to provide improved support for a variety of concurrency models within the standard library.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.python.org/dev/peps/pep-3153/"&gt;PEP 3153&lt;/a&gt; ("Asynchronous IO support") is an early draft of an API standardisation PEP that will hopefully provide a basis for interoperability between components of the various Python asynchronous frameworks. It's a little hard to follow for non-Twisted developers at this stage, since there's no specific proposed stdlib API, nor any examples showing how it would allow things like plugging a Twisted protocol or transport into the gevent event loop, or vice-versa.&lt;br /&gt;&lt;br /&gt;While developers are still ultimately responsible for understanding the interactions between threading and multiprocessing on their platform when using those modules, there are things CPython could be doing to make it easier on them. Jesse Noller, the current maintainer of the multiprocessing package, is looking for someone to take over the responsibility for coordinating the related development efforts (between cross-platform issues and the vagaries of os.fork interactions with threading, this is a non-trivial task, even with the expertise already available amongst the existing core developers).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.python.org/dev/peps/pep-3143/"&gt;PEP 3143&lt;/a&gt; ("Standard daemon process library") may be given another look for 3.3, although it isn't clear if sufficient benefit would be gained from having that module in the stdlib rather than published via PyPI as it is currently.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Providing a better native Python experience on Windows&lt;/h2&gt;Windows is designed and built on the basis of a mindset that expects most end users to be good little consumers that buy software from developers rather than writing it themselves. Anyone writing software is thus assumed to be doing so for a living, and hence paying for professional development tools. Getting a decent development environment set up for free can be so tedious and painful that many developers (like me!) would rather just install and use Linux for development on our own time, even if we're happy enough to use Windows as a consumer (again, like me - mostly for games in my case). The non-existent "BUNDLE ALL THE THINGS!" approach to dependency management and the lack of any kind of consistent software updating interface just makes this worse, as does the fact that any platform API handling almost always has to special-case Windows, since their libc implementation is one of the more practically useless things on the face of this Earth.&lt;br /&gt;&lt;br /&gt;This creates a vicious cycle in open source, where most of the active developers are using either Linux or Mac OS X, so their tools and development processes are focused on those platforms. They're also typically very command line oriented, since the diverse range of graphical environments and the widespread usage of remote terminal sessions makes command line utilities the most reliable and portable. Quite a few new developers coming into the fold run into the Windows roadblocks and either give up or switch to Linux for development (e.g. by grabbing VirtualBox and running a preconfigured Linux VM to avoid any hardware driver issues), thus perpetuating the cycle.&lt;br /&gt;&lt;br /&gt;Personally, I blame the cross-platform hobbyist developer hostile nature of the platform on the Windows ecosystem itself and generally refuse to write code on it unless someone's paying me to do so. Fortunately for single-platform Windows users and developers, though, there are other open source devs that don't feel the same way. Some of them are working on tools (such as the script launcher described in &lt;a href="http://www.python.org/dev/peps/pep-0397/"&gt;PEP 397&lt;/a&gt;) that will make it easier to get usable development environments set up for new Python users.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Miscellaneous API improvements in the standard library&lt;/h2&gt;There are some areas of the standard library that are notoriously clumsy to use. HTTP/HTTPS comes to mind, as does date/time manipulation and filesystem access.&lt;br /&gt;&lt;br /&gt;It's hard to find modules that strike the sweet spot of being well tested, well documented and proven in real world usage, with mature, stable APIs that aren't overly baroque and complicated (yes, yes, I realise the irony of that criticism given the APIs I'm talking about replacing or supplementing). It's even harder to find such modules in the hands of maintainers that are willing to consider supporting them as part of Python's standard library (potentially with backports to older versions of Python) rather than as standalone modules.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.python.org/dev/peps/pep-3151/"&gt;PEP 3151&lt;/a&gt; ("Reworking the OS and IO exception hierarchy") is an effort to make filesystem and OS related exceptions easier to generate and handle correctly that is almost certain to appear in Python 3.3 in one form or another.&lt;br /&gt;&lt;br /&gt;In the HTTP/HTTPS space, I have some hopes regarding Kenneth Reitz's 'requests' module, but it's going to take more real world experience with it and stabilisation of the API before that idea can be given any serious consideration.&lt;br /&gt;&lt;br /&gt;The regex module (available on PyPI) is also often kicked around as a possible candidate for addition. Given the benefits it offers over and above the existing re module, it wouldn't surprise me to see a genuine push for its inclusion by default in 3.3 or some later version.&lt;br /&gt;&lt;br /&gt;A basic stats library in the stdlib (to help keep people from implementing their own variants, usually badly) is also a possibility, but again, depends on a suitable candidate being identified and put forward by people willing to maintain it.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The RFC treadmill&lt;/h2&gt;Many parts of the Python standard library implement various RFCs and other standards. While our release cycle isn't fast enough to track the newer, still evolving protocols, it's good to provide native support for the latest versions of mature, widely supported ones.&lt;br /&gt;&lt;br /&gt;For example, support for sendmg(), recvmsg() and recvmsg_into() methods will be available on socket objects in 3.3 (at least on POSIX-compatible platforms). Additions like &lt;a href="http://www.python.org/dev/peps/pep-3144/"&gt;PEP 3144&lt;/a&gt; ("IP Address Manipulation Library for the Python Standard Library") are also a potential possibility (although that particular example currently appears to be lacking a champion).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Defining Python-specific interoperability standards&lt;/h2&gt;Courtesy of the PEP process, python-dev often plays a role in defining and documenting interfaces that allow various Python frameworks to play nicely together, even if third party libraries are needed to make full use of them. WSGI, the Web Server Gateway Interface, is probably the most well-known example of this (the current version of that standard is documented in &lt;a href="http://www.python.org/dev/peps/pep-3333/"&gt;PEP 3333&lt;/a&gt;). Other examples include the database API, cryptographic algorithm APIs, and, of course, the assorted standards relating to packaging and distribution.&lt;br /&gt;&lt;br /&gt;PEP 3333 was a minimalist update to WSGI to make it Python 3 compatible, so, as of 3.2, it's feasible for web frameworks to start considering Python 3 releases (previously, such releases would have been rather challenging, since it was unclear how they should talk to the underlying web server). It likely isn't the final word on the topic though, as the web-sig folks still kick around ideas like &lt;a href="http://www.python.org/dev/peps/pep-0444/"&gt;PEP 444&lt;/a&gt; and &lt;a href="http://dirtsimple.org/2011/07/wsgi-is-dead-long-live-wsgi-lite.html"&gt;WSGI Lite&lt;/a&gt; &lt;a href="http://dirtsimple.org/2011/08/is-wsgi-lite-library-or-protocol-and.html"&gt;WSGI Lite&lt;/a&gt;. Whether anything actually happens on that front or if we keep chugging along with an attitude of "eh, WSGI gets the job done, quit messing with it" is an open question (and far from my area of expertise).&lt;br /&gt;&lt;br /&gt;One area that is being actively worked on, and will hopefully improve significantly in Python 3.3, is the low level buffer interface protocol defined by &lt;a href="http://www.python.org/dev/peps/pep-3118/"&gt;PEP 3118&lt;/a&gt;. It turned out that there were a few flaws in the way that PEP was implemented in CPython, so even though it did achieve the basic goal of allowing projects like NumPy and PIL to interoperate without needing to copy large data buffers around, there are still some rather rough edges in the way the protocol is exposed to Python code via memoryview objects, as well as in the respective obligations of code that produces and consumes these buffers. More details can be found on the &lt;a href="http://bugs.python.org/issue10181"&gt;issue tracker&lt;/a&gt; if you're interested in the gory details of defining conventions for reliable management of shared dynamically allocated memory in C and C++ code :)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Enhancing and refining the import system&lt;/h2&gt;The importer protocol defined by &lt;a href="http://www.python.org/dev/peps/pep-0302/"&gt;PEP 302&lt;/a&gt; was an ambitious attempt to decouple Python's import semantics from the underlying filesystem. It never fully succeeded - there's still a lot of Python code (including one or two components in the standard library!) that assumes the classical directories-on-a-disk layout for Python packages. That package layout, with the requirement for __init__.py files and restriction to a single directory for each package, is itself surprising and unintuitive for many Python novices.&lt;br /&gt;&lt;br /&gt;There are a few suggestions in the works ultimately aimed not only at cleaning up how all this is implemented, but also at further decoupling the module hierarchy from the on-disk file layout. There are significant challenges in doing this in a way that makes life easier for developers writing new packages, while also allowing those writing tools that manipulate packages to more easily do the right thing, but it's an area that can definitely do with some rationalisation.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Improved tools for factoring out and reusing code&lt;/h2&gt;Python 3.3 will at least bring with it &lt;a href="http://www.python.org/dev/peps/pep-0380/"&gt;PEP 380's&lt;/a&gt; "yield from" expression which makes it easy to take part of a generator and split it out into a subgenerator without affecting the overall semantics of the original generator (doing this correctly in the general case is currently significantly harder than you might think - see the PEP for details).&lt;br /&gt;&lt;br /&gt;I suspect that the next few years may bring some more tweaks to generators, generator expressions and context managers to make for loops and with statements even more powerful utilities for factoring out code. However, any adjustments in this area will be carefully balanced against the need for language stability and keeping things reasonably easy to learn.&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Not Even on the Radar&lt;/h1&gt;In addition to the various suggestions mentioned in PEP 3099 ("Things that Will Not Change in Python 3000"), there are a couple of specific items I think are worth calling out as explicitly &lt;i&gt;not&lt;/i&gt; being part of any realistic road map:&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Major internal architectural changes for CPython&lt;/h2&gt;Questions like 'Why not remove the GIL?', 'Why not switch to a register based VM?', 'Why not add a JIT to CPython?' and 'Why not make PyPy the reference interpreter?' don't really have straightforward obvious answers other than "that's harder than you might think and probably less beneficial than you might hope", so I expect people to continue asking them indefinitely. However, I also don't see any significant changes coming on any of these fronts any time soon.&lt;br /&gt;&lt;br /&gt;One of the key advantages of the CPython interpreter as a reference implementation is that it is, fundamentally, quite a &lt;i&gt;simple&lt;/i&gt; beast (despite a few highly sophisticated corners). If we can do things, chances are that the other implementations are also going to be able to support them. By contrast, the translation stage in their toolchain means that PyPy can contemplate features like the existing JIT, or their current exploration of Software Transactional Memory for removing their Global Interpreter Lock in a useful way that simply aren't feasible with less sophisticated tools (or a much bigger development team).&lt;br /&gt;&lt;br /&gt;Personally, I think the status quo in this space is in a pretty good place, with python-dev and CPython handling the evolution of the language specification itself, as well as providing an implementation that will work reasonably well on almost any platform with a C compiler (and preferably some level of POSIX compliance), while the PyPy crew focus on providing a fast, customisable implementation for the major platforms without getting distracted by arguments about possible new language features.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;More feature backports to the 2.x series&lt;/h2&gt;Aside from the serious backwards compatibility problems accompanying the Unicode transition, the Py3k transition was also strongly influenced by the concept of paying down technical debt. Having legacy cruft lying around made it harder to introduce language &lt;i&gt;improvements&lt;/i&gt;, since the additional interactions created more complexity to deal with, to the point where people just didn't want to bother any more.&lt;br /&gt;&lt;br /&gt;By clearing out a bunch of that legacy baggage, we created a better platform for &lt;i&gt;new&lt;/i&gt; improvements, like more pervasive (and efficient!) Unicode support, even richer metaclass capabilities, exception chaining, more intuitive division semantics and so on.&lt;br /&gt;&lt;br /&gt;The cost, borne mostly by existing Python developers, is a long, slow transition over several years as people deal with the process of not only checking whether the automated tools can correctly handle their own code, but also waiting for all of their dependencies to be available on the updated platform. This actually seems to be going fairly well so far, even though people can be quite vocal in expressing their impatience with the current rate of progress.&lt;br /&gt;&lt;br /&gt;Now, all of the major Python implementations are open source, so it's certainly &lt;i&gt;possible&lt;/i&gt; for motivated developers to fork one of those implementations and start backporting features of interest from 3.x that aren't already available as downloads from PyPI (e.g. it's easy to download unittest2 to get access to 3.x unittest enhancements, so there's no reason to fork just for that kind of backport). However, anyone doing so will be taking up the task in full knowledge of the fact that the &lt;i&gt;existing&lt;/i&gt; CPython development team found that process annoying and tedious enough that we got tired of doing it after two releases (2.6 and 2.7).&lt;br /&gt;&lt;br /&gt;So, while I definitely expect a certain level of ongoing griping about this point, but I don't expect it to rise to the level of anyone doing the work to backport things like function annotations or exception chaining to the 2.x series.&lt;br /&gt;&lt;i&gt;&lt;br /&gt;Update 1: Added missing section about RFC support&lt;br /&gt;Update 2: Fix sentence about role of technical debt in Py3k transition&lt;br /&gt;Update 3: Added a link to a relevant post from Guido regarding the challenges of maintaining official road maps vs one-off "where are we now?" snapshots in time (like this post)&lt;br /&gt;Update 4: Added missing section on defining Python-specific standards&lt;br /&gt;&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-6235142900295197351?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/6235142900295197351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/6235142900295197351'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/08/of-python-and-road-maps-or-lack-thereof.html' title='Of Python and Road Maps (or the lack thereof)'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-2657974305347470566</id><published>2011-07-17T03:04:00.000+10:00</published><updated>2011-07-17T03:04:44.684+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='metablogging'/><title type='text'>Sharing vs broadcasting</title><content type='html'>Even since I started playing with Google+ and its Circle mechanic, I've been trying to figure out why I don't like it. I thought it sounded great when I heard about it, but as soon as I started using it... meh :P&lt;br /&gt;&lt;br /&gt;I still haven't quite figured it out (although I mostly think it's the neither-chicken-nor-fowl aspect, along with it adding back ~500 useless "suggestions" from random Python mailing list contacts that I had already purged once), but it's certainly helped me see the way I communicate online in a different light.&lt;br /&gt;&lt;br /&gt;For a long time, my only real online presence was regular postings to Python mailing lists, commenting on various sites and the very occasional post here on B&amp;L.&lt;br /&gt;&lt;br /&gt;After enough of my friends joined, Facebook was added to the mix, but I do everything I can to keep that locked down so only acquaintances can see most things I post there.&lt;br /&gt;&lt;br /&gt;After going to PyconAU last year, and in the leadup to PyCon US earlier this year, I started up my @ncoghlan_dev account on Twitter, got the "python" category tag on here added to Planet Python, and started to develop a bit more of an online public presence.&lt;br /&gt;&lt;br /&gt;Here on the blog, I can, and do, tag each post according to areas of interest. As far as I know, the 'python' tag is the only one with any significant readership (due to the aggregation via Planet Python), but people could subscribe to the philosophy or metablogging tags if they really wanted to.&lt;br /&gt;&lt;br /&gt;When it comes to sharing information about myself, there's really only a few levels based on how much I trust the people involved: Friends&amp;Family, Acquaintances, General Public pretty much covers it. Currently I handle that via a locked down FB for Friends, Family &amp; Acquaintances (with a "Limited Access" list for people that I exclude from some things, like tagged photos) and completely public material on Twitter and Blogger.&lt;br /&gt;&lt;br /&gt;The public stuff is mostly Python related, since that's my main online presence, but I'm fairly open about political and philosophical matters as well. FB, by contrast, rarely sees any mention of Python at all (and I'm often a little more restrained on the political and philosophical front).&lt;br /&gt;&lt;br /&gt;Where I think Circles goes wrong is that it conflates &lt;i&gt;Access Control&lt;/i&gt; with &lt;i&gt;Topic Tagging&lt;/i&gt;. When I publish Python stuff, I'm quite happy for it to be public. However, I'd also be happy to tag it with "python", just as I do here on the blog, to make it easier for my friends to decide which of my updates they want to see.&lt;br /&gt;&lt;br /&gt;This is classic Publish/Subscribe architecture thinking. When Publishing, I normally want to be able to decide who *can* access stuff. That is limited by closeness, but typically unrelated to the topic. Having, tagging as a service to my subscribers, I am quite happy to do. When Subscribing, I want to be able to filter by topic.&lt;br /&gt;&lt;br /&gt;If I publish something to, say, my Pythonistas circle, than that does more than I want. Yes, it publishes it to them, but it also locks out everybody else. The ways I know people and the degree to which I trust them do not align well with the topics I like to talk about. I've already seen quite a few cases where the reshared versions of public statuses I have received have been limited access.&lt;br /&gt;&lt;br /&gt;The more I think about it, the more I think I'm going to stick with my current policy of using it as a public micro-blog and pretty much ignore the fact that the Circles page exists.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-2657974305347470566?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/2657974305347470566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/2657974305347470566'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/07/sharing-vs-broadcasting.html' title='Sharing vs broadcasting'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-337763672572153355</id><published>2011-07-10T17:10:00.000+10:00</published><updated>2011-07-10T17:10:48.158+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><title type='text'>Effective communication, brain hacking and diversity</title><content type='html'>&lt;a href="https://twitter.com/#!/jessenoller"&gt;Jesse Noller&lt;/a&gt; recently posted an interesting quote on Twitter:&lt;br /&gt;&lt;blockquote&gt;"One who feels hurt while listening to harsh language may lose his mindfulness and not hear what the other person is really saying."&lt;/blockquote&gt;When you think about it, human language is a truly awe inspiring tool. By the simple act of creating certain vibrations in the air, marks on a page or electromagnetic patterns in a storage system, we're able to project our thoughts and feelings across space and time, using them to shape the thoughts and feelings of others.&lt;br /&gt;&lt;br /&gt;While this ability to communicate is so thoroughly natural to most of us as humans that we typically take it for granted, it is actually an amazing world shaping capability &lt;a href="http://www.youtube.com/watch?v=J7E-aoXLZGY"&gt;deserving of our respect and attention&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;And once we start giving it the attention it deserves, then we realise that we can judge the &lt;i&gt;effectiveness&lt;/i&gt; of our own communication by looking at the communication that is subsequently reflected back at us. How well do those reflections mirror the thoughts and feelings that our own words were intended to create? It's the linguistic equivalent of running our code and seeing if it does what we wanted it to do.&lt;br /&gt;&lt;br /&gt;All communication is a form of brain hacking, even when the only target is ourselves. We write lists of goals - formulating for our own benefit concrete plans of action that we can then tackle one step at a time. We write polemics, trying to engender in others some dim sense of the joy or outrage we feel with respect to certain topics. Sometimes we succeed, sometimes we fail. Sometimes we assume certain shared beliefs and understanding, so the point completely fails to come across to those without that common background.&lt;br /&gt;&lt;br /&gt;For those closest to us, those with the most shared history, we have a rich tapestry of common knowledge to draw from. Movies we've all seen, books we've all read, events we all attended, discussions we were all part of - outsiders attempting to follow a transcript of our conversations would likely soon be utterly lost due to the shared subtext that isn't explicitly articulated (and the same is true for any group of close friends).&lt;br /&gt;&lt;br /&gt;As groups get larger, the amount of truly common knowledge decreases, but there's still plenty of unwritten subtext that backs up whatever is explicitly articulated. In a certain sense, that unwritten subtext can be seen as the very &lt;i&gt;definition&lt;/i&gt; of culture - it's the things you don't have to say because they're assumed. My past &lt;a href="http://www.boredomandlaziness.org/2011/04/musings-on-culture-of-python-dev.html"&gt;musings on the culture of python-dev&lt;/a&gt; are an example of this.&lt;br /&gt;&lt;br /&gt;And that brings us to the point of considering the opening quote, diversity and questions of common courtesy. When speaking to friends, I can share truly awful jokes without offence because of the shared background information as to what is and isn't acceptable (and what things should be taken seriously). As the group being addressed gets larger, then the valid assumptions I can make about shared views of the world become fewer and fewer, so I have to start explicitly articulating things I would otherwise assume, and simply not say some things because I know (or at least strongly suspect) that they won't come across correctly to the audience I'm attempting to reach. Sometimes even addressing similar groups of people in a different context can change the assumptions as to what is a reasonable way to phrase things.&lt;br /&gt;&lt;br /&gt;If a member of my target audience gets hung up on my wording or my choice of examples to the point where they miss the underlying message, then to a large degree, the responsibility lies with &lt;i&gt;me&lt;/i&gt; as the originator of the communication. Now, I'm not a saint and make no pretence of being one. The rich fields of metaphors in English include many relating to subjects that are truly quite horrific or otherwise offensive to various groups of people. Sometimes I'm going to use that kind of phrasing without thinking about it, especially when talking rather than writing (my own &lt;a href="http://www.mit.edu/~jcb/tact.html"&gt;innate tact filter&lt;/a&gt; is definitely set up to filter incoming communication, so applying tact in the outwards direction is a conscious process rather than something I do automatically). If such a miscommunication happens and someone points it out, then the onus is on me to admit that yes, my choice of words was poor and obscured my meaning rather than illuminating it. That's life, I make mistakes, and hopefully we can move on.&lt;br /&gt;&lt;br /&gt;It's not entirely a one way street, though. Just as we apply contextual analysis to our understanding of historical writings, so it can be useful to apply the same approach to things that are said by &lt;i&gt;current&lt;/i&gt; figures. Richard Dawkins recently made some ill-advised comments in relation to &lt;a href="http://skepchick.org"&gt;Skepchick's&lt;/a&gt; advice to men to avoid certain actions that make them look creepy (that's all she said, "Don't do this, it's creepy" and she copped flack for it, as if she'd said people doing it should be sent to prison or castrated or something equally extreme). Does the fact that Dawkins clearly didn't get why he was &lt;a href="http://skepchick.org/2011/07/dear-richard-dawkins/"&gt;in the wrong&lt;/a&gt; make him a horrible human being or devalue his extensive contributions to our understanding of evolutionary biology*? No, it doesn't, any more than Isaac Newton's obsession with alchemy devalued his contributions to physics and mathematics. It just makes him a product of the culture that raised him. Hopefully he'll eventually realise this and publicly apologise for failing to give the matter due consideration before weighing in.&lt;br /&gt;&lt;br /&gt;However, what really surprised me is the number of people that indicate they're &lt;i&gt;shocked&lt;/i&gt; by his words, or questioning their support for his other activities just because he so vividly demonstrated his cluelessness on this particular topic. The world is a complicated place and the social dynamics of privilege, cultural blindspots and effectively encouraging diversity aren't one of the easiest pieces to comprehend. Hell, as a middle-class, 30-something, white, English-speaking, straight, cisgendered male living in Australia I'm quite certain that my own grasp of the topic is heavily coloured by the fact that on pretty much &lt;i&gt;any&lt;/i&gt; of the typical grounds for discrimination I'm in the favoured majority (being an atheist is arguably the only exception, but that's far less of a problem here in Australia than it is in the US. Our Prime Minister is an acknowledged atheist and even the Murdoch media machine didn't really try to make much of an issue out of that before the last election). I do my best to understand the topic of diversity based on the experiences of those that actually have to deal with it on a daily basis, but it's still a far cry from seeing things first hand.&lt;br /&gt;&lt;br /&gt;So, since I don't believe I can speak credibly to the topic of diversity directly, I instead prefer to encourage people to reflect on the value and nature of communication and community in general. Martin Fowler &lt;a href="http://martinfowler.com/bliki/SmutOnRails.html"&gt;wrote an excellent piece&lt;/a&gt; about the challenge of creating communities that are welcoming to a diverse audience without rendering them bland and humourless (as the &lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/Theories_of_humor#Benign_Violation_Theory"&gt;benign violations&lt;/a&gt; of expectations and assumptions that are at the heart of most humour often depend on the shared context that welcoming communities can't necessarily assume). This &lt;a href="http://www.youtube.com/watch?v=b0Ti-gkJiXc"&gt;excellent video&lt;/a&gt; highlights the importance of focusing on &lt;i&gt;actions&lt;/i&gt; (e.g. "This thing you said was inappropriate and you should consider apologising for saying it") rather than &lt;i&gt;attributes&lt;/i&gt; (e.g. "You are a racist/misogynist/whatever"). If the latter is actually true, you're unlikely to change their mind and if it *isn't* true, you're likely to miss an opportunity to educate them as they get defensive and stop listening (refer back to that opening quote!).&lt;br /&gt;&lt;br /&gt;I don't pretend to have all (or even any of) the answers, I just believe the entire topic of effective communication and all it entails is one worthy of our collective consideration, since effective communication is almost always a necessary precursor to taking effective &lt;i&gt;action&lt;/i&gt; (e.g. on matters such as &lt;a href="http://www.boredomandlaziness.org/2011/03/climate-change-skepticism-text-book.html"&gt;mitigating and coping with climate change&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;In many respects though, the entire topic is really quite simple. To quote Abe Lincoln in one of my all time favourite movies:&lt;blockquote&gt;Be excellent to each other.&lt;/blockquote&gt;&lt;br /&gt;----&lt;br /&gt;&lt;i&gt;* Seriously, read the popular science books on biology that Dawkins has written, especially "The Greatest Show on Earth". They're orders of magnitudes better than "The God Delusion", which is far too laden with angry and aggressive undertones to be an effective tool for communicating with anyone that doesn't already agree with the thesis of the book. In his biology books, his obvious love and passion for the subject matter comes to the fore and they're by far the better for it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Note for Planet Python:&lt;/b&gt; even though this post is about communication rather than code, I have included the python tag since a couple of different diversity related issues have come up recently on python-dev and psf-members. It is no coincidence that "communication" and "community" share a common(!) root in "communis".&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-337763672572153355?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/337763672572153355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/337763672572153355'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/07/effective-communication-brain-hacking.html' title='Effective communication, brain hacking and diversity'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-4176733343326143412</id><published>2011-07-09T22:12:00.001+10:00</published><updated>2011-07-09T22:50:49.444+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Sure it's surprising, but what's the alternative?</title><content type='html'>Armin Ronacher (aka @mitsuhiko) did a really nice job of explaining &lt;a href="http://lucumr.pocoo.org/2011/7/9/python-and-pola/"&gt;some of the behaviours of Python&lt;/a&gt; that are often confusing to developers coming from other languages.&lt;br /&gt;&lt;br /&gt;However, in that article, he also commented on some of the behaviours of Python that &lt;i&gt;he&lt;/i&gt; still considers surprising and questions whether or not he would retain them in the hypothetical event of designing a new Python-inspired language that had the chance to do something different.&lt;br /&gt;&lt;br /&gt;My perspective on two of the behaviours he listed is that they're items that are affected by fundamental underlying concepts that we really don't explain well even to current Python users. This reply is intended to be a small step towards correcting that. I mostly agree with him on the third, but I really don't know what could be done as an alternative.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The dual life of "."&lt;/h3&gt;&lt;br /&gt;Addressing the case where I mostly agree with Armin first, the period has two main uses in Python: as part of floating point and complex number literals and as the identifier separator for attribute access. These two uses collide when it comes to accessing attributes directly on integer literals. Historically that wasn't an issue, since integers didn't really have any interesting attributes anyway.&lt;br /&gt;&lt;br /&gt;However, with the addition of the "bit_length" method and the introduction of the standardised numeric tower (and the associated methods and attributes inherited from the Complex and Rational ABCs), integers now have some public attributes in addition to the special method implementations they have always provided. That means we'll sometimes see things like:&lt;br /&gt;&lt;pre class="brush: py"&gt;1000000 .bit_length()&lt;/pre&gt;to avoid this confusing error:&lt;br /&gt;&lt;pre class="brush: py"&gt;&gt;&gt;&gt; 1000000.bit_length()&lt;br /&gt;  File "stdin", line 1&lt;br /&gt;    1000000.bit_length()&lt;br /&gt;                     ^&lt;br /&gt;SyntaxError: invalid syntax&lt;br /&gt;&lt;/pre&gt;This could definitely be avoided by abandoning Guido's rule that parsing Python shall not require anything more sophisticated than an &lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/LL_parser"&gt;LL(1) parser&lt;/a&gt; and require the parser to backtrack when float parsing fails and reinterpret the operation as attribute access instead. (That said, looking at the token stream, I'm now wondering if it may even be possible to fix this within the constraints of LL(1) - the tokenizer emits two tokens for "1.bit_length", but only one for something like "1.e16". I'm not sure the concept can be expressed in the Grammar in a way that the CPython parser generator would understand, though)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Decorators vs decorator factories&lt;/h3&gt;&lt;br /&gt;This is the simpler case of the two where I think we have a documentation and education problem rather than a fundamental design flaw, and it stems largely from a bit of careless terminology: the word "decorator" is used widely to refer not only to actual decorators but also to decorator &lt;i&gt;factories&lt;/i&gt;. Decorator expressions (the bit after a "@" on a line preceding a function header) are required to produce callables that accept a single argument (typically the function being defined) and return a result that will be bound to the name used in the function header line (usually either the original function or else some kind of wrapper around it). These expressions typically take one of two forms: they either reference an actual decorator by name, or else they will call a decorator factory to create an appropriate decorator at function definition time.&lt;br /&gt;&lt;br /&gt;And that's where the sloppy terminology catches up with us: because we've loosely used the term "decorator" for both actual decorators and decorator factories since the early days of PEP 318, decorator implementators get surprised at how difficult the transition can be from "simple decorator" to "decorator with arguments". In reality, it is just as hard as &lt;i&gt;any&lt;/i&gt; transition from providing a single instance of an object to instead providing a factory function that creates such instances, but the loose terminology obscures that.&lt;br /&gt;&lt;br /&gt;I actually find this case to be somewhat analogous to the case of first class functions. Many developers coming to Python from languages with implicit call semantics (i.e. parentheses optional) get frustrated by the fact that Python demands they always supply the (to them) redundant parentheses. Of course, experienced Python programmers know that, due to the first class nature of functions in Python, "f" just refers to the function itself and "f()" is needed to actually call it.&lt;br /&gt;&lt;br /&gt;The situation with decorator factories is similar. @classmethod is an actual decorator, so no parentheses are needed and we can just refer to it directly. Something like @functools.wraps on the other hand, is a decorator factory, so we need to call it if we want it to create a real decorator for us to use.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Evaluating default parameters at function definition time&lt;/h3&gt;&lt;br /&gt;This is another case where I think we have an underlying education and documentation problem and the confusion over mutable default arguments is just a symptom of that. To make this one extra special, it lies at the intersection of &lt;i&gt;two&lt;/i&gt; basic points of confusion, only one of which is well publicised.&lt;br /&gt;&lt;br /&gt;The immutable vs mutable confusion is well documented (and, indeed, Armin pointed it out in his article in the context of handling of ordinary function arguments) so I'm not going to repeat it here. The second, &lt;a href="http://bugs.python.org/issue12374"&gt;less well documented&lt;/a&gt; point of confusion is the lack of a clear explanation in the official documentation of the differences between compilation time (syntax checks), function definition time (decorators, default argument evaluation) and function execution time (argument binding, execution of function body). (Generators actually split that last part up even further)&lt;br /&gt;&lt;br /&gt;However, Armin clearly understands both of those distinctions, so I can't chalk the objection in his particular case up to that explanation. Instead, I'm going to consider the question of "Well, what if Python didn't work that way?".&lt;br /&gt;&lt;br /&gt;If default arguments aren't evaluated at definition time in the scope defining the function, what are the alternatives? The only alternative that readily presents itself is to keep the code objects around as distinct closures. As a point of history, Python had default arguments long before it had closures, so that provides a very practical reason why deferred evaluation of default argument expressions really wasn't an option. However, this is a hypothetical discussion, so we'll continue.&lt;br /&gt;&lt;br /&gt;Now we get to the first serious objection: the performance hit. Instead of just moving a few object references around, in the absence of some fancy optimisation in the compiler, deferred evaluation of even basic default arguments like "x=1, y=2" is going to require multiple function calls to actually run the code in the closures. That may be feasible if you've got a sophisticated toolchain like PyPy backing you up but is a serious concern for simpler toolchains. Evaluating some expressions and stashing the results on the function object? That's easy. Delaying the evaluation and redoing it every time it's needed? Probably not too hard (as long as closures are already available). Making the latter as fast as the former for the simple, common cases (like immutable constants)? Damn hard.&lt;br /&gt;&lt;br /&gt;But, let's further suppose we've done the work to handle the cases that allow constant folding nicely and we still cache those on the function object so we're not getting a big speed hit. What happens to our name lookup semantics from default argument expressions when we have deferred evaluation? Why, we get &lt;i&gt;closure&lt;/i&gt; semantics of course, and those are simple and natural and never confused anybody, right? (if you believe I actually mean that, I have an Opera House to sell you...)&lt;br /&gt;&lt;br /&gt;While Python's default argument handling is the way it is at least partially due to history (i.e. the lack of closures when it was implemented meant that storing the expressions results on the function object was the only viable way to do it), the additional runtime overhead and complexity in the implementation and semantics involved in delaying the evaluation makes me suspect that going the runtime evaluation path wouldn't necessarily be the clear win that Armin suggests it would be.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-4176733343326143412?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/4176733343326143412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/4176733343326143412'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/07/sure-its-surprising-but-whats.html' title='Sure it&apos;s surprising, but what&apos;s the alternative?'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-4664372698381067847</id><published>2011-06-29T15:27:00.000+10:00</published><updated>2011-06-29T15:27:17.626+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Updated to do list for Python 3.3</title><content type='html'>I wrote a &lt;a href="http://www.boredomandlaziness.org/2011/01/some-goals-for-python-33.html"&gt;to-do list&lt;/a&gt; for 3.3 back in January. It's already obsolete, so inspired by Brett's &lt;a href="http://sayspy.blogspot.com/2011/06/my-personal-plans-for-python-33.html"&gt;recent update&lt;/a&gt; I have a new list of my own:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Finish PEP 394 (The "python" command on *nix platforms)&lt;/h3&gt;This is the PEP clarifying that the current collective recommendation from python-dev to Linux distributions (et al) is to stick with Python 2.x as the system python for the moment. It also involves adding a python2 symlink to the next release of 2.7 so that we follow our own advice.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;PEP 3118 buffer API and memoryview fixes&lt;/h3&gt;On &lt;a href="http://bugs.python.org/issue10181"&gt;issue #10181&lt;/a&gt; I've been doing the software architect thing in devising a way to address the flaws in the design of memoryview objects. Absent further contributions I may resort to coding it myself, otherwise I'll at least review whatever patches are put forward.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;PEP 380 (yield from expressions)&lt;/h3&gt;Guido gave his approval to PEP 380 recently. This is almost ready to go in, but &lt;a href="http://bugs.python.org/issue11682"&gt;some work&lt;/a&gt; needs to be done on incorporating the tests neatly into the regression test suite.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Import engine&lt;/h3&gt;Import engine is a GSoC project I am mentoring that consolidates the scattered state for the import system into methods and attributes on a single object. While the "real" import system state will remain in the current locations for compatibility reasons, the import engine API will provide a more coherent interface to the whole mechanism. It will also allow creation of more limited engine instances for targeted imports (e.g. from plugin directories) that won't be confused by name conflicts with other libraries.&lt;br /&gt;&lt;br /&gt;I'm hopeful Greg will get as far as writing the PEP itself before the end of the summer, otherwise that will become a follow-up activity.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;CPython compiler enhancements&lt;/h3&gt;Eugene Toder put together a &lt;a href="http://bugs.python.org/issue11549"&gt;nice patch&lt;/a&gt; that refactors the CPython compiler to include an AST optimisation step as well as cleaning up several 2.x holdovers in the AST. Getting the AST compiler ready for Python 2.5 is one of the first things I ever hacked on as a core developer and it's still one of my main interest areas.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;PEP 395 (module aliasing)&lt;/h3&gt;After starting to work with Django and discovering it commits the sin of putting a package subdirectory on sys.path, I have even more motivation to provide a module aliasing mechanism that doesn't run the risk of accidentally getting multiple copies of the same module loaded in a process. That kind of thing should only happen when you do it on purpose.&lt;br /&gt;&lt;br /&gt;I need to review my proposal in PEP 395 to make sure it also covers the Django use case (and modify the proposal if it doesn't).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Core mentoring&lt;/h3&gt;There are still some coverage patches from the Pycon US sprints to be reviewed and committed, along with a couple from the core mentoring mailing list. I'm also likely to be leading the CPython sprints following PyconAU, so there'll be some more patches to review and commit as a result of that.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;importlib bootstrapping&lt;/h3&gt;While the migration to importlib is definitely Brett's project, it's also one I keep a close eye on in case he wants any reviews or feedback on elements of the design.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;PEP process tinkering&lt;/h3&gt;I'd still like to clean up PEP 0 by adding the "Consensus" state to PEP 1. However, it has dropped below the above items on the to-do list.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;With statement tinkering&lt;/h3&gt;Screwing up @contextmanager for 3.2 gives me even more motivation to want implicit context managers and Alex Gaynor tells me he has a use case for a context manager that can skip the with statement body. As with the PEP process tinkering, these are still on the "yes, please" list, but I'm unlikely to get a chance to work on them any time soon.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Other miscellaneous features&lt;/h3&gt;Resurrecting the post-import hooks PEP would be nice and I'd also like to add some of the ABC registration viewing and monitoring features proposed on the issue tracker.&lt;br /&gt;&lt;br /&gt;So, how long until 3.3 again? :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-4664372698381067847?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/4664372698381067847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/4664372698381067847'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/06/updated-to-do-list-for-python-33.html' title='Updated to do list for Python 3.3'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-128440334697078166</id><published>2011-06-16T00:33:00.000+10:00</published><updated>2011-06-16T00:33:40.030+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tech'/><title type='text'>Switching to Android</title><content type='html'>So my new HTC Desire S arrived today which means it is time for an app downloading spree... (starting with just freebies for now while I figure out what I do and don't like, and delete some of the cruft that HTC/Telstra added)&lt;br /&gt;&lt;br /&gt;Already grabbed:&lt;br /&gt;Google Goggles&lt;br /&gt;Google Sky&lt;br /&gt;Google Reader&lt;br /&gt;Dropbox&lt;br /&gt;Firefox&lt;br /&gt;KeepassDroid&lt;br /&gt;OI File Manager&lt;br /&gt;Shelves for Android (now actually *scanning* my book collection will be quite a project...)&lt;br /&gt;Barcode Scanner&lt;br /&gt;Compass&lt;br /&gt;&lt;br /&gt;And a ton of standard apps from Google/HTC/Telstra for all the basics (Phone, SMS, Music, Mail/Gmail, FB, Twitter, Camera, Calendar, Clock, Weather, Calculator, Adobe PDF Reader, Maps/Navigation, LED Flashlight, etc).&lt;br /&gt;&lt;br /&gt;Things I know I want but don't have yet:&lt;br /&gt;&lt;br /&gt;Ebook reader (I used Stanza from Lexcycle on the iPhone, but they don't make an Android version)&lt;br /&gt;Weight tracker (don't need anything fancy, just something that I can import old data into and will give me a time-weighted average)&lt;br /&gt;&lt;br /&gt;I'm also open to suggestions for things I might want but just don't know it yet, and of course I'll have to track down a few idle time games.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-128440334697078166?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/128440334697078166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/128440334697078166'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/06/switching-to-android.html' title='Switching to Android'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-8716774327242564229</id><published>2011-06-13T22:35:00.000+10:00</published><updated>2011-06-13T22:35:33.529+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kubuntu'/><title type='text'>Fixing GRUB2 update issues with Kubuntu 11.04</title><content type='html'>After doing a dist-upgrade to 11.04 a while back, my Kubuntu machine refused to boot.&lt;br /&gt;&lt;br /&gt;I eventually tracked this down to GRUB2 os-prober feature freaking out and trying to boot off the partition that held only the "/usr" directory rather than the one with the root and "/boot" directories. (Why, I have no idea. The latter is the first partition and the one that holds the MBR, so os-prober is clearly going to some effort to find and enforce the wrong partition).&lt;br /&gt;&lt;br /&gt;After searching on Google and with a bit of experimentation, I was able to fix it by booting off a LiveCD, adding the line "GRUB_DISABLE_OS_PROBER=true" to "/etc/default/grub" and then running "sudo update-grub".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-8716774327242564229?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/8716774327242564229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/8716774327242564229'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/06/fixing-grub2-update-issues-with-kubuntu.html' title='Fixing GRUB2 update issues with Kubuntu 11.04'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-2730723584809012928</id><published>2011-04-22T01:42:00.000+10:00</published><updated>2011-04-22T01:42:13.850+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Musings on the culture of python-dev</title><content type='html'>I mentioned at the end of my &lt;a href="http://www.boredomandlaziness.org/2011/03/thoughts-and-impressions-following.html"&gt;PyCon summary post&lt;/a&gt; that several people had told me that they find python-dev to be a hostile and unwelcoming environment, and that (after some reflection on the matter) I could actually see their point. We may be the model of civility compared to somewhere like the Linux Kernel Mailing List or (*shudder*) Blizzard's World of Warcraft forums, but mere civility is a far cry from being a consciously welcoming place.&lt;br /&gt;&lt;br /&gt;I'll say up front that &lt;a href="http://mail.python.org/mailman/listinfo/python-dev"&gt;python-dev&lt;/a&gt; itself is unlikely to change any time soon. There are reasons it is the way it is, and I'll elaborate on some of them later in this post. In the meantime, &lt;a href="http://mail.python.org/mailman/listinfo/python-ideas"&gt;python-ideas&lt;/a&gt; is available as a venue where outlandish ideas won't be rejected quite as abruptly, and the &lt;a href="http://mail.python.org/mailman/listinfo/core-mentorship"&gt;core-mentorship&lt;/a&gt; list has been set up specifically to provide a gentler introduction to the ways and means of core development without having to jump right in at the deep end by posting to python-ideas or python-dev. Questions about development &lt;i&gt;with&lt;/i&gt; Python will continue to be redirected in fairly short order to &lt;a href="http://mail.python.org/mailman/listinfo/python-list"&gt;python-list&lt;/a&gt; or &lt;a href="http://mail.python.org/mailman/listinfo/python-tutor"&gt;python-tutor&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;And, of course, what follows is just my opinion. Ask another veteran python-dev poster what they think, and you'll likely get a different answer. Ask an actual newcomer to (or lurker on) python-dev, and they'll probably have a different answer, too.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Python evolves too slowly!&lt;/h2&gt;&lt;h2&gt;You're changing the language too fast!&lt;/h2&gt;If I had to choose just one explanation for the frequency of abrupt responses in python-dev, the tension between the above two statements would be it. Compared to application-level open source projects, Python actually evolves quite slowly. 18+ months between minor version increments? 10 &lt;i&gt;years&lt;/i&gt; between major versions? That's crazy! Canonical releases an entire new OS version every 6 months!&lt;br /&gt;&lt;br /&gt;On the flip side, however, for a programming language definition, Python evolves quite fast. There's no such thing as a minor release for C or C++ - the last versions of those were C99 and C++98 respectively. We should see C++11 published by the end of the year, and C1X is still in development. CPython's own PEP 7 still mandates the use of C89 compatible constructs for portability reasons, even though C89 is older than one of our &lt;i&gt;release managers&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Java hasn't had a major feature update since 2006, and even C# is only running at a new version every 2-3 years (with the last formally standardised version being 2.0 back in 2006).&lt;br /&gt;&lt;br /&gt;Python also has a history of being more aggressive with deprecations than are languages backed by large corporate sponsors. We only have limited volunteer resources, so rather than letting old code bitrot (or else take up maintenance time when it breaks), we'd prefer to rip it out in favour of an improved alternative. However, "more aggressive" is still pretty slow - some deprecated features stuck around for nearly 10 years (until Python 3 came out) and even a "fast" deprecation has historically taken at least 3 years (x.y contains feature, x.y+1 deprecates it, x.y+2 removes it). It's highly likely that that deprecation period will be extended out by a release for the 3.x series, pushing the minimum lifetime of a new feature that later proves to be a mistake out to nearly 5 years.&lt;br /&gt;&lt;br /&gt;The task of updating the language and the standard library is a balancing act between those two forces - we want to make life easier for programmers adopting Python for new activities, while preserving backwards compatibility for existing applications. This is why Python 3 is such a big deal - most decisions are made with the emphasis on the needs of existing Python programmers, but the decision to create Python 3 was largely for the benefit of &lt;i&gt;future&lt;/i&gt; Python programmers. That means that all current Python programmers are lumped with the task of actually managing a disruptive transition that wasn't really designed for their immediate benefit. Obviously, the collective opinion of python-dev is that it will be worth the pain in the long run, but those anticipated benefits don't make the migration any easier to deal with right now.&lt;br /&gt;&lt;br /&gt;We get quite a few people coming into python-dev and betraying quite quickly that they don't have any respect for the time frames involved in language (rather than application) development. Telling someone "You're wrong, but explaining the real reasons why would require that I distil decades of experience down into a single email post and I don't feel like taking the time to do that right now, since even if I tried you would ignore me anyway" tends to be difficult to phrase politely.&lt;br /&gt;&lt;br /&gt;A lot of the rest of this post is really just elaborations on the theme of &lt;i&gt;why&lt;/i&gt; a programming language needs to evolve more slowly than most other pieces of software.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Heart of the ecosystem, but far from the whole of it&lt;/h2&gt;I've elaborated on the cost of change before, when discussing the design principle &lt;a href="http://www.boredomandlaziness.org/2011/02/status-quo-wins-stalemate.html"&gt;"Status Quo Wins a Stalemate"&lt;/a&gt;. The core point is that any significant change made by python-dev, even one that will ultimately be a positive one, imposes a high near-term cost as the implications of the change ripple out across the whole Python ecosystem. As noted above, newcomers can easily perceive this as high-and-mighty arrogance rather than the voice of experience.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What do you mean by "cognitive burden"?&lt;/h2&gt;Even without considering the near-term cost of changes, every addition to the language (and even the standard library) imposes a potential burden on anyone &lt;i&gt;learning&lt;/i&gt; the language in the future. You can't just say, "Oh, I won't worry about learning that feature" if the code base you've been asked to maintain uses it, or if it is offered as an answer to a query posted on python-list or Stack Overflow or the like. The principle of "There Should Be One - and preferably only one - Obvious Way To Do It" is aimed squarely at reducing the cognitive load on people trying to learn the language. Quite clearly, the "only one" aspect is an ideal rather than a practical reality (two kinds of string formatting and three argument parsing libraries in the standard library all say "Hi!"), but in such cases we do try to indicate that the most recently added (and hopefully least quirky) approach is the preferred way to do it.&lt;br /&gt;&lt;br /&gt;This idea is also encountered as the aphorism "Not every three line function needs to be a builtin". Again, new posters may not take kindly to being told that their idea simply doesn't cut it as a potential language addition.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Gee, how dumb are you lot? Why don't you just...?&lt;/h2&gt;Another favourite bugbear is posters that bounce into python-dev assuming that we're a collection of clueless idiots that can't see the obvious. Collectively, we &lt;i&gt;do&lt;/i&gt; pay quite a bit of attention to what other language communities are doing, as well as having personal experience with what does and doesn't work in actual programming practice. There's a reason that "new" Python features are generally modelled on something that has been demonstrated to work elsewhere (e.g. list comprehensions et al inspired by Haskell, the with statement partially inspired by C++ RAII, the new string formatting syntax inspired by C# string formatting).&lt;br /&gt;&lt;br /&gt;New posters that give the list a tiny bit of credit and do us the courtesy of at least asking "Has this been thought of or discussed before? Are there any problems with it that I haven't considered?" tend to get &lt;i&gt;significantly&lt;/i&gt; more positive reactions than those that start with a tone closer to "Here is my awesome idea, and you are seriously dumb if you don't get it and decide to adopt it immediately!". Positive responses are even more likely if ideas are posted to the right list (i.e. python-ideas).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;You do remember you didn't have to pay a cent for this, right?&lt;/h2&gt;A fortunately rare (but still annoying when it arises) source of negative reactions is the end user that comes in demanding to know why certain things aren't being done, when the answer is "Because nobody stepped up to either do it themselves, or to pay for someone else to do it". It's a pretty simple equation, really, and not demonstrating understanding of it suggests a complete disregard for the volunteer nature of so many of the contributions that have been made to Python over the years.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;In the end, we're still just people&lt;/h2&gt;We like &lt;a href="http://bikeshed.org/"&gt;painting bikesheds&lt;/a&gt; (or, more to the point, we can't always help ourselves, even when we know better). We like to be right and "win" arguments (or sometimes simply take time to process and properly understand the point someone else is trying to make). Even the mailing list members that are paid to work with Python by our employers are typically still participating in python-dev and hacking on CPython in our spare time rather than as a job, so there's not a lot of tolerance for "noise" and "time wasting".&lt;br /&gt;&lt;br /&gt;As I'm a firm believer in the phrase "Vigorous criticism is the only known antidote to error", there are limits to how much I would personally &lt;i&gt;want&lt;/i&gt; the culture of python-dev to change. Moving "blue sky" dreaming to python-ideas, "how does the process work?" coaching to core-mentorship and VCS management issues to python-committers allow them to develop cultures more appropriate to those specific activities, allowing python-dev to really focus in on the "vigorous criticism" part of the story. Keeping that from crossing the line into excessive negativity and a total reluctance to change is an ongoing challenge, but hopefully an awareness of that danger and the occasional pause for reflection will be enough to keep things on the right track.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-2730723584809012928?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/2730723584809012928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/2730723584809012928'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/04/musings-on-culture-of-python-dev.html' title='Musings on the culture of python-dev'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-5777242676606703956</id><published>2011-04-09T22:47:00.001+10:00</published><updated>2011-04-09T23:15:30.097+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>The benefits (and limitations) of PYC-only Python distribution</title><content type='html'>&lt;a href="http://programmers.stackexchange.com/questions/66616/ways-to-prevent-client-seeing-my-code"&gt;This Stack Overflow question&lt;/a&gt; hit my feed reader recently, prompting the usual discussion about the effectiveness of PYC only distribution as a mechanism for obfuscating Python code.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;PYC Only Distribution&lt;/h3&gt;In case it isn't completely obvious from the name, PYC only distribution is a matter of taking your code base, running "compileall" (or an equivalent utility) over it to generate the .pyc files, and then removing all of the original .py source files from the distributed version.&lt;br /&gt;&lt;br /&gt;Plenty of Python programmers (especially the pure open source ones) consider this practice an absolute travesty and would be quite happy to see it disallowed entirely. Early drafts of PEP 3147 (PYC Repository Directories) in fact proposed exactly that - in the absence of the associated source file, a compiled PYC file would have been ignored.&lt;br /&gt;&lt;br /&gt;However, such blatant backwards incompatibility aroused protests from several parties (including me), and support for PYC-only distribution was restored in later versions of the PEP (although "compileall" now requires a command line switch in order to generate the files in the correct location for PYC-only distribution).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Use Cases&lt;/h3&gt;As I see it, there are a couple of legitimate use cases for PYC-only distribution:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Embedded firmware: If your code is going onto an embedded system where space is at a premium, there's no point including both your source code &lt;i&gt;and&lt;/i&gt; the PYC files. Better to just include the compiled ones, as that is all you really need&lt;/li&gt;&lt;li&gt;Cutting down on support calls (or at least making the ones you do get more comprehensible): Engineers and scientists like to tinker. It's in their nature. When they know just enough Python to be a danger to themselves and others, you can get some truly bizarre tickets if they've been fiddling with things and failed to revert their changes correctly (or didn't revert them at all). Shipping only the PYC files can help make sure the temptation to fiddle never even arises&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Of the two, the former is by far the stronger use case. The latter is attempting a technical solution to a social problem and those rarely work out well in the long run. Still, however arguable its merits, I personally consider deterrence of casual modifications a valid use case for the feature.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Drawbacks&lt;/h3&gt;Stripping the source code out of the distribution does involve some pretty serious drawbacks. The main one is the fact that you no longer have the ability to fall back to re-compilation if the embedded magic cookie doesn't match the execution environment.&lt;br /&gt;&lt;br /&gt;This restricts practical PYC-only distribution to comparatively constrained environments that can ensure a matching version of Python is available to execute the PYC files, such as:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Embedded systems&lt;/li&gt;&lt;li&gt;Corporate SOEs (Standard Operating Environments)&lt;/li&gt;&lt;li&gt;Bundled interpreters targeting a specific platform&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Cross-platform compatibility of PYC files (especially for 32-bit vs 64-bit and ARM vs x86) is also significantly less robust than the cross-platform compatibility of Python source code.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Limitations&lt;/h3&gt;Going back to the SO question that most recently got me thinking about this topic, the big limitation to keep in mind is this: &lt;i&gt;shipping only PYC files will not reliably keep anyone from reading your code&lt;/i&gt;. While comments do get thrown away by the compilation process, and docstrings can be stripped with the "-OO" option, Python will always know the &lt;i&gt;names&lt;/i&gt; of all the variables at runtime, so that information will always be present in the compiled bytecode. Given both the code structure and the original variable names, most decent programmers are going to be able to understand what the code was doing, even if they don't have access to the comments and docstrings.&lt;br /&gt;&lt;br /&gt;While there aren't any currently active open source projects that provide full decompilation of CPython bytecode, such projects have existed in the past and could easily exist again in the future. There are also companies which provide Python decompilation as a paid service (decompyle and depython are the two that I am personally aware of).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Alternatives&lt;/h3&gt;You can deter casual tinkering reasonably well by placing your code in a zip archive with a non-standard extension (even .py!). If you prepend an appropriate shebang line, you can even mark it as executable on POSIX based systems (see &lt;a href="http://www.boredomandlaziness.org/2011/03/what-is-python-script.html"&gt;this post&lt;/a&gt; for more information).&lt;br /&gt;&lt;br /&gt;You could also write your code in Cython or RPython instead of vanilla Python and ship fully compiled executable binaries.&lt;br /&gt;&lt;br /&gt;There are minifier projects for Python (such as &lt;a href="http://pypi.python.org/pypi/mnfy"&gt;mnfy&lt;/a&gt;) that could be fairly readily adapted to perform obfuscation tricks (such as replacing meaningful variable names with uninformative terms like "_id1").&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-5777242676606703956?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/5777242676606703956/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/04/benefits-and-limitations-of-pyc-only.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/5777242676606703956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/5777242676606703956'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/04/benefits-and-limitations-of-pyc-only.html' title='The benefits (and limitations) of PYC-only Python distribution'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-8588280205576978634</id><published>2011-03-30T00:44:00.002+10:00</published><updated>2011-03-30T01:15:39.805+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='science'/><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>Climate change "skepticism": a text book case of the "Tragedy of the Commons"</title><content type='html'>So, with the government moving to implement a carbon tax, the issue of climate change and attempts to mitigate it are once again a big deal here in Australia.&lt;br /&gt;&lt;br /&gt;Inspired by a friend's comment comparing carbon taxes with fines for littering, along with a few of the  responses to that comment, I started pondering the similarities and differences between the current attempts to deal with carbon dioxide emissions, and the &lt;a href="http://www.edf.org/page.cfm?tagID=1085"&gt;effective cost internalisation schemes created&lt;/a&gt; in the 1990's that severely reduced industrial sulphur dioxide emissions, as well as various current laws that prohibit dumping of toxic waste in developed nations (and their &lt;a href="http://www.ehow.com/info_8012059_causes-dumping-third-world-countries.html"&gt;unintended side effects&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;i&gt;(Fair warning before I wade in: I've simplified quite a few things, particularly on the acid rain front. This post is long enough as it is, without making it even longer with all the relevant caveats about other causes of acid rain and any other details I've glossed over as being irrelevant to the main point of the article. It's a general overview, not a peer reviewed scientific paper)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A tale of two gases&lt;/b&gt;&lt;br /&gt;The key similarity between sulphur dioxide induced acid rain and carbon dioxide induced global warming is hopefully fairly obvious: they both represent a classic economic "externality", a cost borne by someone other than the person responsible for causing it. The industries and individuals emitting these pollutants don't suffer any immediate harmful consequence through the normal action of nature.&lt;br /&gt;&lt;br /&gt;In situations like that, regulation in one form or another is the only effective tool we have to ensure that at least some portion of those external costs is reflected back on the responsible individuals. As noted in the link above, this approach proved extraordinarily effective in reducing acid rain in the US, drastically cutting sulphur emissions at a fraction of the originally predicted cost.&lt;br /&gt;&lt;br /&gt;However, there are a few key differences that have contributed to the discussion over carbon dioxide taking a rather different path to that over sulphur dioxide:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It's hard to deny the harmful effects of sulphur dioxide emissions when plants, fish and insects are dying due to the excessive levels of acidity in rain and ground water. By contrast, it is very hard to convey clearly why a small rise in average global temperatures is going to be such a bad thing, or even how human carbon dioxide emissions contribute to that happening.&lt;/li&gt;&lt;li&gt;Acid rain from sulphur emissions is generally a &lt;i&gt;local&lt;/i&gt; problem with local causes (from a continental perspective, anyway). Stop emitting sulphur dioxide in the US and acid rain stops falling in the US. Significantly reduce carbon dioxide emissions in Australia (or even the US) though, and we're likely still screwed if other countries don't follow suit.&lt;/li&gt;&lt;li&gt;The "sulphur" cycle (how long it takes for the sulphur emissions to be deposited back on the ground as acid rain) is significantly shorter than that of carbon, so efforts to reduce emissions will have an effect on water acidity levels in a reasonably short time frame&lt;/li&gt;&lt;/ol&gt;Comparisons with anti-waste dumping laws are similar: the effects of toxic waste dumping are generally both local, obvious and able to be cleaned up within years rather than decades, so it is easy to get support for laws prohibiting such practices, even if the end result of those laws is just to export the problem to a poorer country.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Manufacturing doubt and exploiting the "Grey Fallacy"&lt;/b&gt;&lt;br /&gt;Acid rain is an easy problem to sell: the acid damages plants and objects directly, so the harm can be easily conveyed through pictures and videos. The problem of climate change, though is far, far harder to illustrate simply, since it is a signal buried in some very noisy weather patterns.&lt;br /&gt;&lt;br /&gt;A fundamental issue is the fact that people don't really experience climate, but instead experience weather. The day to day and seasonal variations in the weather massively exceed the scale of the underlying trends being discussed by climate scientists. The fact that predicting the weather in a few days time is harder than predicting long term climate trends is actually massively counterintuitive, even though almost all scientists and engineers are familiar with the fact that random fluctuations at a small scale may average out to something almost perfectly predictable at a large scale (compare the unpredictable nature of quantum physics with the straightforward determinism of classical Newtonian mechanics).&lt;br /&gt;&lt;br /&gt;We're also not really used to the idea of directly affecting the balance of the planet on a global scale. In absolute terms, the effects of the sun, the oceans and the plants on the carbon cycle all dwarf the human contribution. The idea that the non-human forcings were actually largely in balance with each other, and that the comparatively small human contribution is enough to tip that balance to the point of producing more carbon than can be absorbed by natural mechanisms is really quite a subtle one.&lt;br /&gt;&lt;br /&gt;The scientific background needed to truly understand and come to grips with the hows and the whys of the IPCC predictions reminds me of &lt;a href="http://abstrusegoose.com/272"&gt;this comic&lt;/a&gt; regarding the knowledge needed to even begin to understand the vagaries of string theory (make sure to click through on the comic itself to see the whole chain of images).&lt;br /&gt;&lt;br /&gt;If there wasn't anyone around with a vested interest in maintaining the status quo (at least for a while longer), this likely wouldn't be a problem. Scientists, politicians, economists and engineers could proceed with the development of mitigation strategies, while also attempting to educate the general populace as to the reasons behind any actions taken. Since such vested interests do exist, however, their opposition makes it significantly harder to convince the lay public that there is a real problem here.&lt;br /&gt;&lt;br /&gt;Because climate science is such a complex topic, it is actually quite hard to explain to a non-scientist just &lt;i&gt;why&lt;/i&gt; the scientific consensus is as strong as it is. If you oversimplify, you veer into territory where statements are so oversimplified that they border on being false. However, if you're coming from the other angle and want to persuade people that the science "isn't settled", then you're no longer constrained by the need to be accurate and can just go with whatever sounds more intuitively plausible and/or better caters to people's natural inclinations and prejudices.&lt;br /&gt;&lt;br /&gt;Sites like &lt;a href="http://www.skepticalscience.com/"&gt;Skeptical Science&lt;/a&gt; do their best to clearly explain why the oft-repeated "skeptic" arguments are basically BS (and do it well), but to someone only following the Cliff Notes mainstream media version of the debate, the temptation is still very, very strong to just assume the truth lies somewhere between the two positions being debated.&lt;br /&gt;&lt;br /&gt;Telling people to "do their own research" doesn't really help all that much in practice. Telling the BS from the valid science is itself a fine art that takes a great deal of skill and experience. Being a veteran of arguments with creationists (and even intelligent design advocates) is actually quite beneficial, since the global warming "skeptics" use many of the same rhetorical tricks as creationists do when attempting to deny the fact of evolution (incessant use of such deceptive tactics is actually one of the major hints that someone is trying to sell you a line rather than just stating the truth as they see it). The most common tactic used by both groups is to drag out a thoroughly rebutted argument for each new audience, in hopes that they aren't aware of the existence of a rebuttal.&lt;br /&gt;&lt;br /&gt;For example, just as most people can't answer "How could a bombardier beetle possibly evolve?" off the top of their heads - I've actually forgotten all of the plausible answers myself - neither can they answer questions like "If the climate is supposed to be warming, why is it colder now than it was during the Middle Ages?". While that one is actually fairly straightforward to answer (ice cores and other data shows that the medieval warming was likely localised to Europe due to various currents in the Atlantic, but this merely shifted heat around, so that other parts of the world were correspondingly colder), there are dozens of other oft-repeated thoroughly debunked arguments, and it's basically impossible for a mere interested observer to remember them all. As it turns out, I had actually misremembered the correct explanation for the Medieval warm period, so the point above isn't quite right and invites an attack on the grounds that I don't know what I'm what I'm talking about. To some extent that's actually true - my opinion on climate science issues is based on a meta-analysis of the trustworthiness of various information sources (including the full &lt;a href="http://www.ipcc.ch/publications_and_data/publications_and_data_reports.shtml"&gt;IPCC reports&lt;/a&gt;), since I'm not inclined to spend a few decades studying up and redoing all the science myself. Fortunately, Skeptical Science has the &lt;a href="http://www.skepticalscience.com/medieval-warm-period.htm"&gt;full story&lt;/a&gt; for this question and many others (the MWP was actually colder than the latter half of this century, despite higher solar activity and lower volcanic activity), so correcting my error is the task of a few moments. And if you're still wondering about the bombardier beetle thing, TalkOrigins has the &lt;a href="http://www.talkorigins.org/faqs/bombardier.html"&gt;full story for that&lt;/a&gt;, too.&lt;br /&gt;&lt;br /&gt;Fortunately, at the decision making level here in Australia, this part of the debate seems to be coming to a close, with even Toby Abbott (the leader of the opposition) at least paying lip service to the fact that human-induced increases in average global temperatures are now a fact of life. However, the mainstream media is still happy to "teach the controversy" in the hopes of picking up a few more eyeballs (or ears) to sell to their advertisers.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;But the problem is so much bigger than us!&lt;/b&gt;&lt;br /&gt;However, even once you get agreement that human-induced global warming due to excessive carbon dioxide emissions is a genuine problem, you then run into the "But we can't do anything about it!" attitude.&lt;br /&gt;&lt;br /&gt;Many Australians (including some elected members of our Federal parliament) go "Oh, but the US/Europe/Brazil/Russia/India/China have a much bigger impact than we do. Doing anything will hurt our international competitiveness without really achieving anything, so we shouldn't bother."&lt;br /&gt;&lt;br /&gt;Even the higher emission countries point fingers at each other. The US won't budge until China does. The BRIC countries are waiting for the US to make a move, and use US inaction as justification for similarly doing nothing in the meantime.&lt;br /&gt;&lt;br /&gt;An absolutely textbook "Tragedy of the Commons" reaction. And we know how that story ends, don't we? In the long run everybody loses, nobody wins.&lt;br /&gt;&lt;br /&gt;How do you fix it? Rules, regulations and social pressure. The "community of nations" isn't just words. The complex web of interdependencies that spans the world gives countries real power to exert influence on each other. Once some countries start to make a move towards serious carbon emission control strategies, then that becomes a bargaining chip to use in international negotiations. Will it work? Who knows. The only thing we know for sure is that the more carbon we pump into the atmosphere over the next few decades, the higher the impact from global warming will be (it's now guaranteed that there will be &lt;i&gt;some&lt;/i&gt; impact - the carbon cycle is too long for us to prevent that at this late stage of the game).&lt;br /&gt;&lt;br /&gt;Ideally you would want to adopt an emissions trading scheme along the lines of that used to curb sulfur emissions, but the wholehearted embrace of dodgy pseudoscience by far too many members of our Federal Opposition party spiked that particular barrel.&lt;br /&gt;&lt;br /&gt;So a carbon tax it is (for now, anyway). The hysterical cries of "Oh my god, you've doomed the country!" ring loudly from those that will bear most of the direct costs of actually internalising the negative effects their carbon emissions have on the wider environment. Their motives are, to say the least, a little bit suspect. The political opportunism involved in our Federal Opposition leader backing them is disappointing, but unsurprising.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;In the PM's words&lt;/b&gt;&lt;br /&gt;There's a nice summary of the current situation in a Fairfax &lt;a href="http://www.smh.com.au/opinion/politics/extreme-views-must-not-decide-carbon-tax-20110323-1c6ky.html"&gt;opinion piece&lt;/a&gt; that went out over Gillard's byline:&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;The longer we leave it the harder action on climate change gets. This reform road is a hard one to walk. Just as doing nothing is not an option, we need to be careful to ensure that we do not make decisions that will cost our economy and jobs.&lt;/i&gt;&lt;/blockquote&gt;There's a definite risk that the government's plans won't live up to their ambitions. However, the world's past experience with the sulfur dioxide doomsayers should arouse some deep skepticism and not directed towards those wanting to press forward with plans to curb carbon emissions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-8588280205576978634?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/8588280205576978634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/03/climate-change-skepticism-text-book.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/8588280205576978634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/8588280205576978634'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/03/climate-change-skepticism-text-book.html' title='Climate change &quot;skepticism&quot;: a text book case of the &quot;Tragedy of the Commons&quot;'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-8147183473372421562</id><published>2011-03-29T21:47:00.002+10:00</published><updated>2011-03-29T22:09:53.782+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>Queensland's "unelected" leader of the opposition</title><content type='html'>Following the declaration of Brisbane's Lord Mayor that he is running for state parliament at the next election, and will be the leader of the opposition for that campaign, there is a trope making the rounds that he is somehow "unelected".&lt;br /&gt;&lt;br /&gt;Out of curiosity, I decided to see how his numbers in the Brisbane City Council elections in 2008 stacked up against Anna Bligh's numbers in the 2009 state election.&lt;br /&gt;&lt;br /&gt;The internet being what it is, official sources for these numbers weren't too hard to dig up:&lt;br /&gt;I found the &lt;a href="http://www.brisbane.qld.gov.au/about-council/elections/previous-election-results/index.htm"&gt;Lord Mayoral&lt;/a&gt; results on the Brisbane City Council site&lt;br /&gt;I found the &lt;a href="http://www.ecq.qld.gov.au/elections/state/state2009/results/district73.html"&gt;Electorate of South Brisbane&lt;/a&gt; results on the Electoral Commission Qld site (with the preferences taken into account &lt;a href="http://www.ecq.qld.gov.au/elections/state/state2009/results/summary.html#12"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Results:&lt;br /&gt;Campbell Newman received 335,076 first preference votes for Lord Mayor (60% of the total).&lt;br /&gt;After distribution of preferences, he received a total of 339,320 votes (66% of the total).&lt;br /&gt;It's probably worth noting that the second placed candidate received 29% of the first round votes, increasing to 34% after distribution of preferences, so Newman actually did receive the majority of the remaining preferences, there just weren't many to go around.&lt;br /&gt;&lt;br /&gt;Anna Bligh received 12,243 first preference votes in her electorate of South Brisbane (48% of the total).&lt;br /&gt;After distribution of preferences, she received a total of 14,697 votes (65% of the total).&lt;br /&gt;&lt;br /&gt;So, our State Premier holds her position on the back of the support of her party and around 15k people living in or near South Brisbane.&lt;br /&gt;&lt;br /&gt;The new leader of the opposition will hold that position on the back of the support of his party and around 340k people living in the City of Brisbane.&lt;br /&gt;&lt;br /&gt;Since the current population of Qld is estimated at 4.5 million people, effectively 7.5% of the state voted for Newman to be Brisbane's Lord Mayor, while only 0.3% voted for Bligh to represent the seat of South Brisbane.&lt;br /&gt;&lt;br /&gt;And people are calling &lt;i&gt;Newman&lt;/i&gt; an unelected leader?&lt;br /&gt;&lt;br /&gt;(Yes, I'm aware that the nature of parliamentary governments based on geographic representation means that most constituents don't get to vote directly for their parliamentary leaders. The only purpose of this post is to point out how &lt;i&gt;dumb&lt;/i&gt; that makes the "unelected" gibe sound when it is aimed at the directly elected Lord Mayor of a city the size of Brisbane)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-8147183473372421562?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/8147183473372421562/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/03/queenslands-unelected-leader-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/8147183473372421562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/8147183473372421562'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/03/queenslands-unelected-leader-of.html' title='Queensland&apos;s &quot;unelected&quot; leader of the opposition'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-1272817508883660370</id><published>2011-03-20T06:20:00.000+10:00</published><updated>2011-03-20T06:20:45.969+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Thoughts and Impressions following PyCon 2011</title><content type='html'>I'm back home following my inaugural trip to PyCon, so it seems like a good time to record my impressions of the summits, conference and sprints.&lt;br /&gt;&lt;br /&gt;I really enjoyed the whole experience - kudos to Van Lindbergh, Jesse Noller and the rest of the volunteer team for organising everything. I'm glad to see the "apprenticeship" setup for the conference leadership continuing, with Jesse (the deputy coordinator this year) stepping up to coordinate Santa Clara, with the future coordinator for Montreal assisting during those two years.&lt;br /&gt;&lt;br /&gt;The personal connection side of things was brilliant. When it comes to the folks that were already on python-dev before I really started to follow it back in late 2003, I've been interacting and working with them online for 8+ years, and there are of course many others that have joined python-dev in the intervening time. I'd seen a few of them in photos and videos, and heard a few in videos and podcasts, but by and large, this was the first time I had been able to connect faces and voices to names on the screen. Very cool stuff, including getting to meet Raymond Hettinger (who accepted my first patches back in '04, among them the looks-insane-but-it-works string hack to speed up the 2.x decimal module) and of course Guido himself (who was the one who actually granted me commit rights, essentially for making sense while arguing with him about PEP 340/346/343).&lt;br /&gt;&lt;br /&gt;Getting ready for Pycon was actually also the motivation behind restarting this blog and adding it to Planet Python, finally getting myself a Twitter account (&lt;a href="http://twitter.com/ncoghlan_dev"&gt;@ncoghlan_dev&lt;/a&gt;) and (after getting home) hooking my DISQUS profile up to that. They're all aspects of taking a bit more of an active part in the wider Python community after getting a taste of it at PyconAU last year (despite the fact that I have yet to make it to a BrisPy meeting... Wednesday night just isn't a good night for me these days).&lt;br /&gt;&lt;br /&gt;From a more technical perspective, there were a few things that I found particularly interesting:&lt;br /&gt;&lt;br /&gt;1. PyPy is definitely starting to make the transition from "experimental platform for research into dynamic language optimisation" to "let's use this to make production code go faster". This shows not only in their benchmark results, but also in their efforts to update their website to be more production-user friendly and the effort to get more major projects running on it at the sprints, including those that stress the boundaries of the distinction between the language definition and CPython implementation details (*cough*SQLAlchemy*cough*). One of those efforts actually revealed &lt;a href="http://bugs.python.org/issue11477"&gt;a bug&lt;/a&gt; in one of the dark corners of the CPython implementation (folks in Hanover F at the sprints may have heard me swearing about my various attempts at fixing that one...)&lt;br /&gt;&lt;br /&gt;2. There is definite interest in supporting Python 3 in more modules and packages, as well as improving the available information out there regarding published packages. There's likely to be at least one after-the-fact PEP to better explain one of the major C API changes that bit some sprinters attempting to forward port zc.buildout (I think that was the affected package), there is collaboration developing amongst the Linux distros (and others) to get more existing packages on Python 3 (join the &lt;a href="https://anonbadger.wordpress.com/2010/10/25/python3-porting-organization/"&gt;python-porting&lt;/a&gt; list if that project interests you), there are a couple of &lt;a href="http://py3ksupport.appspot.com/"&gt;new&lt;/a&gt; &lt;a href="http://getpython3.net/"&gt;sites&lt;/a&gt; with improved information on the level of Python 3 support in various modules, and the team behind &lt;a href="http://www.djangopackages.com"&gt;djangopackages&lt;/a&gt; are working on providing the same service for the whole of PyPI (and, no doubt, Python 3 support will end up being one of the points of comparison).&lt;br /&gt;&lt;br /&gt;3. With distutils2 entering the standard library as "packaging" in 3.3 (to reflect the scope creep in the mission of the package, as well as to avoid name conflicts with future backports of distutils2 post 3.3 release), it was fascinating listening to the sprinters discussing how to take their clean 3.3 code from the standard library and backport it (as distutils2) to run on 3.2, 3.1, 2.7, 2.6, 2.5 and 2.4 without cluttering the stdlib version with backwards compatibility cruft. If their results are a match for their goals, then their new 2to3 and 3to2 inspired tool may end up becoming the basis for a general purpose Python "backport" transformation technique that is able to iteratively downgrade Python code to support earlier versions, while still allowing the use of clean, idiomatic code in the latest version.&lt;br /&gt;&lt;br /&gt;4. The understanding of how best to leverage the Mercurial transition is still evolving on python-dev. My personal opinion has now developed towards one where I hope we will start using more feature clones (rather than branches within the main repository), with the main cpython repository only being used to accept feature-complete (or near complete) contributions. We're actually pretty close to supporting that model now, it just needs a few tweaks to the way builds are pushed to the buildbots to get us the rest of the way to being able to trial code on the full buildbot fleet without having to push it into the main repository first.&lt;br /&gt;&lt;br /&gt;5. Collaboration efforts between the 5 biggest Python implementations (CPython, PyPy, Jython, IronPython, Stackless) continue to evolve. The PSF announced $10k in direct funding to PyPy at the start of the conference proper, the &lt;a href="http://www.python.org/download/"&gt;main python.org download page&lt;/a&gt; now includes links to the sites of the other 4 major implementations, more contributors to the other projects were given CPython push rights to allow standard library fixes to be contributed upstream rather than maintained in downstream forks, there are plans in progress to create a collaborative "speed.python.org" modelled on the existing &lt;a href="http://speed.pypy.org/"&gt;PyPy benchmark site&lt;/a&gt; and Brett Cannon plans to revive the PEP about splitting the standard library out to a separate source control repository.&lt;br /&gt;&lt;br /&gt;6. Brian Curtin has a &lt;a href="http://blog.briancurtin.com/2011/03/16/pycon-2011-cpython-sprint-newcomers/"&gt;nice write-up&lt;/a&gt; welcoming several newcomers that made their first submissions to the CPython bug tracker at the sprints. Brett's idea of improving test coverage as an introductory activity is a *great* idea, since such changes are relatively easy to get started with, relatively easy to review, low risk of breaking anything (except the buildbots) and involve actually writing code. I'll also note here that Eric Snow spent the sprints working on a more esoteric idea that came out of a python-ideas discussion: see what would be involved in providing a variant on exec() that allowed an actual function body to be executed in a designated namespace.&lt;br /&gt;&lt;br /&gt;I was also surprised (and somewhat concerned) at the number of people that perceived python-dev as a hostile, unwelcoming place. On further reflection, I realised there was actually some merit to that point of view, but that's a topic for another post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-1272817508883660370?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/1272817508883660370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/03/thoughts-and-impressions-following.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/1272817508883660370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/1272817508883660370'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/03/thoughts-and-impressions-following.html' title='Thoughts and Impressions following PyCon 2011'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-2003066447775169302</id><published>2011-03-11T22:39:00.000+10:00</published><updated>2011-03-11T22:39:57.024+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python Language Summit - Highlights</title><content type='html'>The language summit covered a fair bit more ground than the VM summit did, so this post only covers the topics that I personally found particularly interesting. My &lt;a href="http://www.boredomandlaziness.org/2011/03/python-language-summit-rough-notes.html"&gt;rough notes&lt;/a&gt; at least mention everything that was discussed.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Moar Speed&lt;/b&gt;&lt;br /&gt;The question of speed, optimisations and benchmarking came up again. A lot of this was just retreading the ground from the &lt;a href="http://www.boredomandlaziness.org/2011/03/python-vm-summit-somewhat-coherent.html"&gt;VM summit&lt;/a&gt; with a wider audience. One thing that did become clearer is that the near-term points of contact for the speed.python.org concept are Maciej Fijałkowski from the PyPy team for the technical issues and Jesse Noller on the PSF side for the hosting/organisational issues (although I expect Jesse would welcome offers of assistance if anyone else, particularly existing PSF members, wanted to step up and help coordinate things).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Communicating the collective opinions of python-dev&lt;/b&gt;&lt;br /&gt;Where are we going, what are we doing? The main communications channels for python-dev have historically been PEPs (including release PEPs), the What's New document for each release and of course the mailing list itself. The python-dev summaries project has been tried a couple of times, but generally burned out the people involved.&lt;br /&gt;&lt;br /&gt;Doug Hellman (PSF communications officer) would like to try a setup where there is an official python-dev technical blog where major discussions and decisions (including the outcomes of PEPs) can be presented in easier to swallow chunks, giving the gist of significant decisions and discussions, with references back to the source PEPs and mailing list threads.&lt;br /&gt;&lt;br /&gt;It's an interesting idea, but, as Guido pointed out, will likely require *new* people to step forward to do it that are interested in the idea of helping to provide a window into the goings-on of python-dev (hopefully the more interesting parts, where we aren't just arguing about the colour of the current bikeshed du jour). From a personal point of view, I know I've only just really started using *this* blog to talk about my own perspective on Pythonic stuff. Something that may be practical is for the python.org technical blog to highlight blog posts where existing core devs are talking about new and upcoming stuff on their personal blogs.&lt;br /&gt;&lt;br /&gt;Doug Hellman is the point of contact for anyone interested in following up on this.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Policy on use of accelerator modules&lt;/b&gt;&lt;br /&gt;There are a few unwritten policies regarding the use of implementation-specific accelerator modules to speed up parts of the standard library (such as "always test both versions", "the accelerated version should be API compatible with the Python version", "the interpreter should still work if the accelerated version is missing").&lt;br /&gt;&lt;br /&gt;Brett Cannon has volunteered to write these down in an official policy PEP. While CPython is likely the main offender here, it will be suggested that other implmentations follow the same policy for their own accelerator modules. Patches to bring CPython more inline with this policy, include providing pure Python alternative of existing C-only modules, are definitely of interest.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Compatibility warnings&lt;/b&gt;&lt;br /&gt;With the rise in significance of alternate implementations, some grey areas in the language definition (such as the reliance on refcounting semantics, abuse of the ability to store non-string keys in CPython namespaces, storing objects that implement the descriptor protocol in classes without considering the consequences) are potential sources for confusion when they break on other versions (or potentially even in future versions of CPython.&lt;br /&gt;&lt;br /&gt;ResourceWarning was added a while back to cover the refcounting issue, and uncovered a few bugs in CPython and its test suite. The proposal is to add CompatibilityWarning as a peer exception to ResourceWarning and use it for cases where people are relying on CPython implementation accidents that aren't officially supported by the language definition.&lt;br /&gt;&lt;br /&gt;Nobody has stepped forward to write the PEP for this as yet, but it may make an interesting sprint topic (I know at least Brett and I are around for the sprints, and there should be a few other CPython core devs kicking around).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Better exception info&lt;/b&gt;&lt;br /&gt;ImportWarning will likely acquire a "module" attribute during the sprints (this is an easy one, since it will just reference the module's name). There are other expections that could probably do with having the repr() of critical bits of information stored separately on the exception object (e.g. KeyError, ValueError, IndexError) for easy programmatic access.&lt;br /&gt;&lt;br /&gt;Using repr() helps avoid issues with reference cycles keeping things along longer than intended. However, the API for creating such enhanced exceptions would still need to be worked out, as well as how best to deal with cases where third party code has only populated the exception message without filling in the specific details. Technically, even ImportError isn't immune to that concern, as raising it is sometimes the responsibility of third party PEP 302 importers and loaders.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-2003066447775169302?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/2003066447775169302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/03/python-language-summit-highlights.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/2003066447775169302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/2003066447775169302'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/03/python-language-summit-highlights.html' title='Python Language Summit - Highlights'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-5898390423979634017</id><published>2011-03-11T08:31:00.001+10:00</published><updated>2011-03-11T11:31:41.285+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python Language Summit - Rough Notes</title><content type='html'>Same drill, different day, more people, more notes :)&lt;br /&gt;&lt;br /&gt;Still just my interpetation, though. Will probably highlight a few things I find particularly interesting again tomorrow (as I did for the VM summit).&lt;br /&gt;&lt;br /&gt;PSF Communications (Doug Hellman)&lt;br /&gt;- currently writing about PSF funding and similar activities&lt;br /&gt;- would like to include more technical material summarising python-dev discussions&lt;br /&gt;- how best to go about that&lt;br /&gt;- new blog, not existing PSF blog&lt;br /&gt;- existing PSF board not in the position to do it&lt;br /&gt;- Guido: core devs already do a lot via PEPs and mailing list, likely not keen to write blog as well&lt;br /&gt;- may be better to get others to do it, willing to follow discussions of interest&lt;br /&gt;- posts may be primarily pointers to other resources (e.g. PEPs, mailing list posts)&lt;br /&gt;- all implementations&lt;br /&gt;- major new releases should go on python.org as NEWS items&lt;br /&gt;&lt;br /&gt;Warnings for things that may cause problems on different implementations&lt;br /&gt;- ResourceWarning helps to pick up reliance on CPython specific refcounting&lt;br /&gt;- CompatibilityWarning for reliance on non-strings in namespaces (e.g. classes)&lt;br /&gt;- update Language Spec to clarify ambiguous situations&lt;br /&gt;- like ResourceWarning, silence CompatibilityWarning by default&lt;br /&gt;- what to do about builtin functions that currently aren't descriptors (i.e. doesn't change behaviour when retrieved from a class)&lt;br /&gt;- e.g. make staticmethod objects directly callable&lt;br /&gt;- big gray area in language spec - callables may not be descriptors&lt;br /&gt;- perhaps change CPython builtin descriptors to warn about this situation&lt;br /&gt;- another use case for CompatibilityWarning&lt;br /&gt;- Guido not convinced the builtin function problem can be handled in general&lt;br /&gt;- a better callable variant of staticmethod may be better, that allows the default descriptor behaviour to be easily stripped from any function&lt;br /&gt;- doesn't want to require that all builtin functions follow descriptor protocol, since it is already the case that many callables don't behave like methods&lt;br /&gt;- a better staticmethod would allow the descriptor protocol to be stripped, ensuring such functions can be safely stored in classes without changing behaviour&lt;br /&gt;&lt;br /&gt;Standard Library separation&lt;br /&gt;- see VM summit notes&lt;br /&gt;- over time, migrate over to separate repository for standard lib, update &lt;br /&gt;- need Python and C modules stay in sync&lt;br /&gt;- buildbots for standard library&lt;br /&gt;- challenge of maintaining compatibility as standard lib adopts new language changes&lt;br /&gt;- need a PEP to provide guarantees that C accelerators are kept in sync (Brett Cannon volunteered to write test)&lt;br /&gt;- bringing back pure Python alternatives to C standard library is encouraged, but both need to be tested&lt;br /&gt;- accelerator modules should be subsets of the Python API  &lt;br /&gt;- Brett will resurrect standard library PEP once importlib is done&lt;br /&gt;- full consolidation unlikely to be possible for 2.7 (due to CPython maintenance freeze)&lt;br /&gt;&lt;br /&gt;Speed Benchmarking&lt;br /&gt;- see VM summit notes&lt;br /&gt;- really good for tracking performance changes across versions&lt;br /&gt;- common set of benchmarks&lt;br /&gt;- OSU OSL are willing to host it&lt;br /&gt;- backend currently only compares two versions&lt;br /&gt;- first step is to get up and running with Linux comparisons first, look at other OS comparisons later&lt;br /&gt;- hypervisors mess with performance benchmarks, hence need real machines&lt;br /&gt;- should set up some infrastructure on python.org (benchmark SIG mailing list, hg repository)&lt;br /&gt;- eventually, redirect speed.pypy.org to new speed.python.org&lt;br /&gt;- longer term, may add new benchmarks&lt;br /&gt;&lt;br /&gt;Exception data&lt;br /&gt;- need to eliminate need to parse error strings to get info from exceptions&lt;br /&gt;- should be careful that checks of message content aren't overly restrictive&lt;br /&gt;- PEP 3151 to improve IO error handling? (Guido still has some reservations)&lt;br /&gt;- ImporError needs to name module&lt;br /&gt;- KeyError, IndexError, ValueError?&lt;br /&gt;- need to be careful when it comes to creating reference loops&lt;br /&gt;- exception creation API also an issue, since structured data needs to be provided&lt;br /&gt;&lt;br /&gt;Contributor Licensing Agreements&lt;br /&gt;- Jesse and Van looking to get electronic CLAs set up&lt;br /&gt;- will ensure adequately covers non-US jurisdictions&lt;br /&gt;&lt;br /&gt;Google Summer of Code&lt;br /&gt;- encouraging proposals under the PSF umbrella&lt;br /&gt;&lt;br /&gt;Packaging&lt;br /&gt;- distutils2 should land in 3.3 during the sprints&lt;br /&gt;- namespace packages (PEP 382) will land in 3.3&lt;br /&gt;- external name for backports should be different from internal name&lt;br /&gt;- too late to introduce a standard top level parent for stdlib packages&lt;br /&gt;- external backports for use in older versions is OK&lt;br /&gt;- external maintenance is bad&lt;br /&gt;- hence fast development cycles incompatible with stdlib&lt;br /&gt;- want to give distutils2 a new name in stdlib for 3.3, so future backports based on version in 3.4 won't conflict with the standard version in 3.3&lt;br /&gt;&lt;br /&gt;Python 3 adoption&lt;br /&gt;- py3ksupport.appspot.com (Brett Cannon)&lt;br /&gt;- supplements inadequate trope data on PyPI with manual additions&lt;br /&gt;- Georg Brandl has graphical tracker of classification data on PyPI over time&lt;br /&gt;- Allison Randall/Barry Warsaw have been doing similar dependency tracking and migration info for Ubuntu&lt;br /&gt;- giant wiki page for Fedora Python app packaging&lt;br /&gt;- good dependency info would provide a good ranking system for effectively targeting grants&lt;br /&gt;- 3.python.org? getpython3.com? need to choose an official URL&lt;br /&gt;- funding may help with PyPy migration&lt;br /&gt;- IronPython will be looking at 3.x support once 2.7 is available (this week/next week timeframe)&lt;br /&gt;- Jython focused on 2.6 now, may go direct to 3.x after that (haven't decided yet)&lt;br /&gt;- PSF funding needs a specific proposal with specific developer resources with the necessary expertise and available time&lt;br /&gt;- CObject-&gt;Capsule change is a compatibility issue for C extension modules&lt;br /&gt;- Django targeting Python 3 support by the end of summer&lt;br /&gt;- zc.buildout is a dependency of note that hasn't been ported yet (Pycon sprint topic)&lt;br /&gt;- other migration projects being tackled at Pycon sprints (webop?)&lt;br /&gt;&lt;br /&gt;Python upstream and distro packaging&lt;br /&gt;- PEP 394 - recommendations for symlinks practices&lt;br /&gt;- PEP 3147 and 3149 were heavily targeted at helping distros share directories across versions&lt;br /&gt;- namespace packages (PEP 382)&lt;br /&gt;- PEP 384 stable ABI (done for 3.2)&lt;br /&gt;- better tools needed to help with migration to stable ABI&lt;br /&gt;&lt;br /&gt;Baseline Python distro installs&lt;br /&gt;- system python varies in terms of what is installed&lt;br /&gt;- challenging to target, as available modules vary&lt;br /&gt;- "build from source" is only a partial answer as some build dependencies are optional&lt;br /&gt;- distros make some changes to support differences in directory layouts&lt;br /&gt;- some changes affect Python app dependencies (e.g. leaving out distutils)&lt;br /&gt;- conflict between "system Python" use case of what is needed to run distro utilities and "arbitrary app target" for running third party apps&lt;br /&gt;- distributing separate Python under app control is not ideal, due to security patch management issues&lt;br /&gt;- specific problems are caused by removal of stuff from base install (e.g. distutils)&lt;br /&gt;- other problem is when distro uses old versions of packages (but virtualenv can help with that)&lt;br /&gt;- may help if a "python-minimal" was used for the essential core, with "python" installing all the extras (including distutils, tkinter, etc)&lt;br /&gt;- then have a further python-extras (or equivalent) that adds everything else the distro needs for its own purposes&lt;br /&gt;- distros tend to work by taking a CPython build and then splitting it up into various distro packages&lt;br /&gt;- to handle additions, would be good to be able to skip site-packages inclusion in sys.path (ala virtualenv).&lt;br /&gt;- "-S" turns off too much (skips site.py entirely, not just adding site-packages to sys.path)&lt;br /&gt;- "-s" only turns off user site-packages, not system site-packages&lt;br /&gt;&lt;br /&gt;Python 3.3 proposed changes to strings to reduce typical memory usage&lt;br /&gt;- PEP 393 changes to internal string representation (implementation as GSoC project)&lt;br /&gt;- Unicode memory layout currently split in order to more easily support resizing and subclassing in C&lt;br /&gt;- need to build and measure to see speed and memory impacts&lt;br /&gt;- alternative idea may be to explore multiple implementation techniques (similar to PyPy)&lt;br /&gt;&lt;br /&gt;Speed (again!)&lt;br /&gt;- Unladen Swallow dormant. Major maintainers moved on to other things, fair bit of work in picking it up&lt;br /&gt;- even trying to glean piecemeal upgrades (e.g. to cPickle) is a challenge&lt;br /&gt;- interest in speeding up Python has really shifted to PyPy&lt;br /&gt;- for CPython, gains would need to be really substantial to justify additional complexity&lt;br /&gt;- really need to get the macro benchmarks available on 3.x&lt;br /&gt;- Guido: pickle speedup experience is to be cautious, even when the speed gains are large. &lt;br /&gt;- speed hack attempts on CPython are still of interest, especially educational ones&lt;br /&gt;- speeding up overall is a very hard problem, but fixing specific bottlenecks is good&lt;br /&gt;- stable ABI will help&lt;br /&gt;- PyPy far more sensitive to refcounting bugs than CPython&lt;br /&gt;- static analysis to pick up refcounting bugs could help a great deal&lt;br /&gt;- "Here there be dragons": Unladen Swallow shows that overall speedups are not easy to come by&lt;br /&gt;&lt;br /&gt;Regex engine upgrade&lt;br /&gt;- new regex library proposed&lt;br /&gt;- added many new features, including the Unicode categories needed to select out Python 3.x identifiers&lt;br /&gt;- potentially big hassle for other implementations since re module includes a lot of C&lt;br /&gt;- IronPython currently translates to .NET compatible regexes, but could rewrite more custom code&lt;br /&gt;&lt;br /&gt;GUI Library&lt;br /&gt;- Guido: GUI libraries are nearly as complicated as the rest of Python put together and just aren't a good fit with the release cycle of the standard lib&lt;br /&gt;- Don't want to add another one, but don't want to remove Tcl/Tk support either&lt;br /&gt;&lt;br /&gt;twisted.reactor/deferred style APIs in the standard library&lt;br /&gt;- asyncore/aynchat still has users&lt;br /&gt;- would like to have an alternative in the stdlib that offers a better migration path to Twisted&lt;br /&gt;- deferred could be added, such that asyncore based apps can benefit from it&lt;br /&gt;- reactor model separates transport/protocol concerns far more cleanly than asyncore&lt;br /&gt;- protocol level API and transport level API for asyncore may be a better option&lt;br /&gt;- would allow asyncore based applications to more easily migrate to other async loops&lt;br /&gt;- defining in a PEP would allow this to be the "WSGI" for async frameworks ("asyncref", anyone?) (Jesse suggested concurrent.eventloop instead)&lt;br /&gt;- still need someone to step up to write the PEP and integrate the feedback from the Twisted team and the other async frameworks&lt;br /&gt;- plenty of async programming folks able to help and provide feedback (including glyph)&lt;br /&gt;- having this standardised would help make event loop based programming more pluggable&lt;br /&gt;- Guido still doesn't like the "deferred" name&lt;br /&gt;- Glyph considers deferred to be less important than standardising the basic event loop interface&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-5898390423979634017?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/5898390423979634017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/03/python-language-summit-rough-notes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/5898390423979634017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/5898390423979634017'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/03/python-language-summit-rough-notes.html' title='Python Language Summit - Rough Notes'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-6475912885206211547</id><published>2011-03-10T22:38:00.005+10:00</published><updated>2011-03-11T22:00:28.259+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python VM Summit - Somewhat Coherent Thoughts</title><content type='html'>Yay, sleep :)&lt;br /&gt;&lt;br /&gt;Last night I just dumped my relatively &lt;a href="http://www.boredomandlaziness.org/2011/03/python-vm-summit-rough-notes.html"&gt;raw notes&lt;/a&gt; into a post. This review is more about distilling what was discussed over the day into a few key themes.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Speed Good&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;One major point was to do with "How do we make Python fast?". Dave Mandelin (Mozilla Javascript dev) was asking how open CPython was to people tinkering with JIT and other technologies to try and speed up execution, and it was acknowledged that python-dev's reaction to such proposals is rarely more than lukewarm. A large part of that resistance comes from the fact that CPython is generally portable to many more architectures than the real speed hacks (which are generally x86 + x86-64 + ARM at best, and sometimes not even all 3 of those). Unladen Swallow also lost a lot of steam, as so much of their effort was going into tasks not directly related to "make CPython faster" (e.g. fixing LLVM upstream bugs, getting benchmarks working on new versions).&lt;br /&gt;&lt;br /&gt;Instead, we tend to push people more towards PyPy if they're really interested in that kind of thing. Armin decided years ago (when switching his efforts from psyco to PyPy) that "we can't get there from here", and it's hard to argue with him, especially given the recent results from the benchmarks executed by speed.pypy.org.&lt;br /&gt;&lt;br /&gt;There was definitely interest in expanding the speed.pypy.org effort to cover more versions of more interpeters. We don't actually have any solid data in CPython regarding the performance differences between 2.x and 3.x (aside from an expectation that 3.x is slower for many workloads due to the loss of optimised 32 bit integers, additional encoding/decoding overhead when working with ASCII text, the new IO stack, etc). We aren't even sure of the performance changes within the 2.x series.&lt;br /&gt;&lt;br /&gt;That last is the most amenable to resolution in the near term - the benchmarks run by speed.pypy.org are all 2.x applications, so the creation of a speed.python.org for the 2.x series could use the benchmarks as is. Covering 3.x as well would probably be possible with a subset of the benchmarks, but others would require a major porting effort (especially the ones that depend on twisted).&lt;br /&gt;&lt;br /&gt;Champions and specific points of contact for this idea aren't particularly obvious at this stage. Jesse is definitely a fan of the idea, but has plenty on his plate already, so it isn't clear how that will work out from a time point of view. There'll likely need to be some self-organisation from folks that are both interested in the project and aren't already devoting their Python-relates energies to something else.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Python Software Foundation, not the CPython Software Foundation&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The second major key point was the PSF (as represented by Jesse Noller from the board, and several other PSF members, including me, from multiple VMs) wanting to do more to support and promote implementations other than CPython. We are definitely at the point where all 4 big implementations are an excellent choice depending on the target environment:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;CPython: the venerable granddaddy, compatible with the most C extensions and target environments, most amenable to "stripping" (i.e. cutting it down to a minimal core), likely the easiest sell in a corporate environment (due to age and historically closest ties to the PSF)&lt;/li&gt;&lt;li&gt;Jython: the obvious choice when using Python as a glue language for Java components, or as a scripting language embedded in a Java environment&lt;/li&gt;&lt;li&gt;IronPython: ditto for .NET components and applications&lt;/li&gt;&lt;li&gt;PyPy: now at the point where deployments on standard server and desktop environments should seriously consider it as an alternative to CPython. It's not really appropriate for embedded environments, but when sufficient resources are available to let it shine, it &lt;i&gt;will&lt;/i&gt; run most workloads significantly faster than CPython. It even has some support for C extensions, although big ticket items like full NumPy support are still a work in progress. However, if you're talking something like a Django-based web app, then "CPython or PyPy" is now becoming a question that should be asked.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;It didn't actually come up yesterday, but Stackless probably deserves a prominent mention as well, given the benefits that folks such as CCP are able to glean from the microthreading architecture.&lt;br /&gt;&lt;br /&gt;Currently, however, python.org is still very much the CPython website. It will require a lot of work it to get to a place where the other implementations are given appropriate recognition. It also isn't clear whether or not the existing pydotorg membership will go along with a plan to modernise the website design to something that employs more modern web technologies, and better provides information on the various Python implementation and the PSF. While the current site is better than what preceded it, a lot of pydotorg members are still gun shy due to the issues in managing that last transition (even the recent migration of the development process docs over to a developer-mainted system on docs.python.org encountered some resistance). However, when the broader Python community includes some of the best web developers on the planet, we can and &lt;i&gt;should&lt;/i&gt; do better. (A personal suggestion that I didn't think of until this morning: perhaps a way forward on this would be to first build a new site as "beta.python.org", without making a firm commitment to switch until after the results are available for all to see. It's a pretty common way for organisations to experiment with major site revamps, after all, and would also give the pydotorg folks a chance to see what they think of the back-end architecture)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Standardising the Standard Library&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Finally, with the hg transition now essentially done, efforts to better consolidate development effort on the standard library (especially the pure Python sections) and the associated documentation will start to gather steam again. As a preliminary step, commit rights (now more accurately called "push rights") to the main CPython repository are again being offered to maintainers from the other major interpreter implementations so they can push fixes upstream, rather than needing to maintain them as deltas in their own repositories and/or submit patches via the CPython tracker.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-6475912885206211547?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/6475912885206211547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/03/python-vm-summit-somewhat-coherent.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/6475912885206211547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/6475912885206211547'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/03/python-vm-summit-somewhat-coherent.html' title='Python VM Summit - Somewhat Coherent Thoughts'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-9219488990372399911</id><published>2011-03-10T11:28:00.002+10:00</published><updated>2011-03-10T12:30:53.032+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python VM Summit - Rough Notes</title><content type='html'>In parallel with the the 2 days of tutorials at Pycon, there are a couple of day long meetings for invited folks active in the evolution of the language itself. Today was the VM summit, which focuses on the major Python interpreter implementations (CPython, PyPy, Jython, IronPython), the current status of each, and where things are likely to head in the near- and long-term. (The Thursday session focuses more on the evolution of the language itself, as well as of the wider ecosystem).&lt;br /&gt;&lt;br /&gt;CPython and PyPy both had multiple devs at the summit, IronPython and Jython devs were also there (although IronPython got to share their's with CPython). We also has some Parrot VM folks there, as well as one of the Mozilla Javascript devs - a bunch of issues with VM development for dynamic languages apply across languages, despite differences in the surface syntax.&lt;br /&gt;&lt;br /&gt;The notes below are probably too cryptic to make sense out of context, bit will hopefully give the gist of what was discussed. These notes are my interpretation of what was said, and may or may not reflect what people actually meant. Names omitted to protect the guilty (and because I didn't write them down)&lt;br /&gt;&lt;br /&gt;Commit rights for other VM core devs&lt;br /&gt;&amp;nbsp; - good idea&lt;br /&gt;&amp;nbsp; - did some of this last Pycon US&lt;br /&gt;&amp;nbsp; - will look into adding more this week&lt;br /&gt;&lt;br /&gt;Splitting out the standard library and test suite (again)&lt;br /&gt;&amp;nbsp; - duplication of effort between CPython/IronPython/Jython/PyPy&lt;br /&gt;&amp;nbsp; - shared commit rights intended to make it easier near term to use CPython as master, allowing bugs to be fixed "upstream"&lt;br /&gt;&amp;nbsp; - hg transition should make sharing easier&lt;br /&gt;&amp;nbsp; - main CPython release will stay "batteries included"&lt;br /&gt;&amp;nbsp; - open to the idea of providng "CPython minimal" and "standard library" downloads (but much work to be done in defining a minimum set)&lt;br /&gt;&amp;nbsp; - longer term, may want to separate pure-Python stdlib development from "C skills required" hacking on the CPython interpreter core and C accelerated implementation modules for the stdlib&lt;br /&gt;&lt;br /&gt;Speed benchmarking&lt;br /&gt;&amp;nbsp; - speed.pypy.org (very cool!)&lt;br /&gt;&amp;nbsp; - benchmarks originally chosen by Unladen Swallow team&lt;br /&gt;&amp;nbsp; - PSF may talk to OSU OSL about setting up speed.python.org&lt;br /&gt;&amp;nbsp; - benchmark multiple versions of CPython, as well as Jython and IronPython&lt;br /&gt;&amp;nbsp; - currently benchmarks are 2.x specific, may be a while before 3.x can be compared fully&lt;br /&gt;&amp;nbsp; - may be GSoC projects in:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - improving backend infrastructure to handle more interpreters&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; - porting benchmarks to Python 3&lt;br /&gt;&amp;nbsp; - can highlight key performance differences between the implementations (e.g slowspitfire vs spitfire-cstringio)&lt;br /&gt;&lt;br /&gt;Python.org download pages&lt;br /&gt;&amp;nbsp; - should start recommending alternative interpreters more prominently&lt;br /&gt;&amp;nbsp; - PyPy likely to be faster for pure Python on major platforms&lt;br /&gt;&amp;nbsp; - IronPython/Jython/CPython still best at integration with their respective environments (Java libraries, .NET linraries, C extensions)&lt;br /&gt;&lt;br /&gt;Cool hacks&lt;br /&gt;&amp;nbsp; - Maciel: pypy JIT viewer&lt;br /&gt;&amp;nbsp; - Dave Malcolm: CPython HEAP viewer in GDB 7&lt;br /&gt;&amp;nbsp; &lt;br /&gt;Parrot VM (and JIT for dynamic languages)&lt;br /&gt;&amp;nbsp; - target VM for dynamic languages (primarily Perl 6 and Tcl at the moment)&lt;br /&gt;&amp;nbsp; - loadable operations, loadable object types&amp;nbsp; &lt;br /&gt;&amp;nbsp; - dynamic ops were original speed target, now moving towards dynamic types instead&lt;br /&gt;&amp;nbsp; - exploring reducing number of core ops to make JIT more practical&lt;br /&gt;&amp;nbsp; - looking into taking advantage of LLVM&lt;br /&gt;&amp;nbsp; - Unladen Swallow blazed this trail, so LLVM has better dynamic language support&lt;br /&gt;&amp;nbsp; - PyPy has tried and failed to use LLVM as an effective backend&lt;br /&gt;&amp;nbsp; - some issues may have been fixed due to Unladen Swallow's efforts, but others still exist (e.g. problems with tail recursion)&lt;br /&gt;&amp;nbsp; - SpiderMonkey similarly struggles with JIT and dynamic patching issues&lt;br /&gt;&amp;nbsp; - GNU Lightning and LiveJIT projects noted, but nobody really familiar with them&amp;nbsp; &lt;br /&gt;&amp;nbsp; - any future Python-on-Parrot efforts likely to focus on using PyPy frontend with Parrot as a backend&lt;br /&gt;&amp;nbsp; - proof-of-concept written (for a thesis?) that used .NET as a backend target for PyPy&lt;br /&gt;&amp;nbsp; - original Python-on-Parrot ran into problems due to semantic mismatches between Perl 6 and Python - reached the limits of the degree of difference the Perl 6 toolchain was willing to tolerate)&lt;br /&gt;&amp;nbsp; &lt;br /&gt;Role of the PSF&lt;br /&gt;&amp;nbsp; - supports Python the Language, not just CPython the Reference Interpreter&lt;br /&gt;&amp;nbsp; - could use additional feedback on how to better fulfill that role&lt;br /&gt;&amp;nbsp; - getting the "boring stuff" done?&lt;br /&gt;&amp;nbsp; - project-based grants, not blanket personal funding&lt;br /&gt;&amp;nbsp; - project proposals requiring more funds than the PSF can provide are still valuable, as PSF can help facilitate co-sponsorships (however, still a novel concept - only been done once so far).&lt;br /&gt;&lt;br /&gt;2.7 to 3.2&lt;br /&gt;&amp;nbsp; - PyPy just reaching feature parity with 2.7&lt;br /&gt;&amp;nbsp; - PyPy now becoming far more interesting for production usage&lt;br /&gt;&amp;nbsp; - treat PyPy Python 3 dialect like a major Python library (e.g. sponsored by PSF)&lt;br /&gt;&lt;br /&gt;CPython warnings for reliance on implementation details&lt;br /&gt;&amp;nbsp; - ResourceWarning was a nice addition (detects reliance on refcounting for resource cleanup&lt;br /&gt;&amp;nbsp; - non-string keys in class namespaces would be another good candidate for a warning&lt;br /&gt;&amp;nbsp; - clarifying finalisation-at-shutdown semantics would be nice (but fixing those semantics in CPython first would help with that)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-9219488990372399911?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/9219488990372399911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/03/python-vm-summit-rough-notes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/9219488990372399911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/9219488990372399911'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/03/python-vm-summit-rough-notes.html' title='Python VM Summit - Rough Notes'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-3641520569439614366</id><published>2011-03-07T00:19:00.000+10:00</published><updated>2011-03-07T00:19:51.985+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>What is a Python script?</title><content type='html'>This is an adaptation of a &lt;a href="http://python.mirocommunity.org/video/1766/pyconau-2010-lightning-talks-s"&gt;lightning talk&lt;/a&gt; I gave at PyconAU 2010, after realising a lot of the people there had no idea about the way CPython's concept of what could be executed had expanded over the years since version 2.4 was released. As of Python 2.7, there are actually 4 things that the reference interpreter will accept as a main module.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Ordinary scripts:&lt;/b&gt; the classic main module identified by filesystem path, available for as long as Python has been around. Can be executed without naming the interpreter through the use of file associations (Windows) or shebang lines (pretty much everywhere else).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Module name:&lt;/b&gt; By using the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-m&lt;/span&gt; switch, a user can tell the interpreter to locate the main module based on its position in the module hierarchy rather than by its location on the filesystem. This has been supported for top level modules since Python 2.4, and for all modules since Python 2.5 (via PEP 338). Correctly handles explicit relative imports since Python 2.6 (via PEP 366 and the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;__package__&lt;/span&gt; attribute). The classic example of this usage is the practice of invoking &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"python -m timeit 'snippet'"&lt;/span&gt; when discussing the relative performance of various Python expressions and statements.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Valid sys.path entry:&lt;/b&gt; If a valid sys.path entry (e.g. the name of a directory or a zipfile) is passed as the script argument, CPython will automatically insert that location at the beginning of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sys.path&lt;/span&gt;, then use the module name execution mechanism to look for a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;__main__&lt;/span&gt; module with the updated &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sys.path&lt;/span&gt;. Supported since Python 2.6, this system allows quick and easy bundling of a script with its dependencies for internal distribution within a company or organisation (external distribution should still use proper packaging and installer development practices). When using zipfiles, you can even add a shebang line to the zip header or use a file association for a custom extension like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.pyz&lt;/span&gt; and the interpreter will still process the file correctly.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Package name: &lt;/b&gt;If a package name is passed as the value for the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-m&lt;/span&gt; switch, the Python interpreter will reinterpret the command as referring to a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;__main__&lt;/span&gt; submodule within that package. This version of the feature was added in Python 2.7, after some users objected to the removal in Python 2.6 of the original (broken) code that incorrectly allowed a package's &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;__init__.py&lt;/span&gt; to be executed as the main module. Starting in Python 3.2, CPython's own test suite supports this feature, allowing it to be executed as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"python -m test"&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The above functionality is exposed via the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;runpy&lt;/span&gt; module, as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;runpy.run_module() &lt;/span&gt;and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;runpy.run_path()&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;If anyone ever sees me (metaphorically) jumping up and down about making sure things get mentioned in the What's New document for a new Python version, this is why. Python 2.6 was released in October 2008, but we didn't get the note about the zipfile and directory execution trick into the What's New until February 2010. It is described in the documentation, but really, who reads the command line documentation, or is likely to be casually browsing the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;runpy&lt;/span&gt; docs? This post turning up on Planet Python will probably do more to get the word out about the functionality than anything we've done before now :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-3641520569439614366?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/3641520569439614366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/03/what-is-python-script.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/3641520569439614366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/3641520569439614366'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/03/what-is-python-script.html' title='What is a Python script?'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-5745931175148588221</id><published>2011-02-28T01:07:00.001+10:00</published><updated>2011-02-28T01:21:12.152+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Status quo wins a stalemate</title><content type='html'>Sometimes language design arguments can reach a point of stalemate. The status quo is only arguably flawed, and there are also perceived flaws in any or all of the proposed alternatives. An appropriate shared design principle can help identify when this point has been reached, and let the discussion die a natural death rather than endlessly rehashing the same points without anyone changing their opinion.&lt;br /&gt;&lt;br /&gt;Every time we (python-dev) change anything significant, no matter how positive the end result, it can create a lot of churn in the community. Books need to be rewritten, other implementations modified, advice, recipes and examples updated, questions clarified as to which version they relate to, and version compatibility issues need to be monitored closely for projects that need to cope with older execution environments.&lt;br /&gt;&lt;br /&gt;So, before any significant changes are made, we want to be fairly certain that the gain in clarity for future Python programs is worth the inevitable near term costs as the update ripples across the Python ecosystem. Sometimes newcomers have some interesting ideas, but still fail to clear this hurdle. The simple "it's not worth the hassle" response they're likely to receive may then come across as stodgy developers rejecting an outsider's ideas without adequate consideration.&lt;br /&gt;&lt;br /&gt;This was something that came up fairly often during the Python 3000 mailing list discussions, to the point where I posted a message explaining why the principle of &lt;a href="http://mail.python.org/pipermail/python-3000/2006-May/001936.html"&gt;"Status quo wins a stalemate"&lt;/a&gt; is a very practical way to avoid meaningless churn in the language design and to cut short design discussions that obviously aren't going anywhere productive.&lt;br /&gt;&lt;br /&gt;Python 3000 was already going to have a lot of major changes (most notably, finally improving the non-ASCII text handling story, in a way that means most Python 3 libraries and applications will be more likely to get it right). We needed to ride close herd on the design discussions to try to make sure that gratuitous changes with insufficient long term benefits were avoided.&lt;br /&gt;&lt;br /&gt;So, lambda eventually stayed and map() and filter() were retained as builtins, while the attractive nuisance that is reduce() was merely banished to the functools module rather than getting dropped entirely as was originally proposed. PEP 348 was rejected to be replaced by the far less ambitious PEP 352. str.format() was still added, but as a complement to the legacy percent formatting mechanism rather than as a wholesale replacement.&lt;br /&gt;&lt;br /&gt;Untold numbers of ideas on the mailing lists and the tracker were dropped with "too much pain for not enough benefit" as the rationale. More recently, PEP 3003 was instituted to enforce a moratorium on core language changes for Python 3.2 in order to give the rest of the community more time to catch up to Python 2.7 and the 3.x series, even though we knew it meant delaying good ideas like the improved generator refactoring capabilities provided by PEP 380.&lt;br /&gt;&lt;br /&gt;The fact that Python 3 migration support tools like 2to3, 3to2 and the six module work as well as they do is probably due to this principle of language design as much as it is to any other factor (not to take anything away from the fine work that has gone into implementing them, of course!).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-5745931175148588221?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/5745931175148588221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/02/status-quo-wins-stalemate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/5745931175148588221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/5745931175148588221'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/02/status-quo-wins-stalemate.html' title='Status quo wins a stalemate'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-9165436440299582790</id><published>2011-02-27T19:43:00.001+10:00</published><updated>2011-02-27T19:52:51.838+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='metablogging'/><title type='text'>Posting code and syntax highlighting</title><content type='html'>Before publishing the previous post, I looked into recommendations for syntax highlighting in coding-oriented blogs. In a quick search, syntaxhighlighter showed up repeatedly as the preferred choice, so that's what I went with.&lt;br /&gt;&lt;br /&gt;It looks like I'm not the only one &lt;a href="http://www.knowthytools.com/2010/03/blogging-with-restructuredtext-and.html"&gt;that isn't entirely happy with that solution&lt;/a&gt; (although by using the "pre" tags rather than "script", my code should at least appear in the RSS feed).&lt;br /&gt;&lt;br /&gt;Working with ReST would certainly be easier than the semi-HTML I'm currently using. Still, I think I have plenty to learn about Blogger's formatting tools before I abandon them entirely in favour of preformatted posts (which have their own drawbacks).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-9165436440299582790?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/9165436440299582790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/02/posting-code-and-syntax-highlighting.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/9165436440299582790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/9165436440299582790'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/02/posting-code-and-syntax-highlighting.html' title='Posting code and syntax highlighting'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-4496045007317678506</id><published>2011-02-27T19:13:00.007+10:00</published><updated>2011-03-05T09:40:06.899+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Justifying Python language changes</title><content type='html'>A few years back, I &lt;a href="http://mail.python.org/pipermail/python-dev/2008-October/082831.html"&gt;chipped in on python-dev&lt;/a&gt; with a review of syntax change proposals that had made it into the language over the years. With Python 3.3 development starting and the language moratorium being lifted, I thought it would be a good time to tidy that up and republish it as a blog post.&lt;br /&gt;&lt;br /&gt;Generally speaking, syntactic sugar (or new builtins) need to take a construct in idiomatic Python that is fairly obvious to an experienced Python user and make it obvious to even new users, or else take an idiom that is easy to get wrong when writing (or miss when reading) and make it trivial to use correctly.&lt;br /&gt;&lt;br /&gt;Providing significant performance improvements (usually in the form of reduced memory usage or increased speed) also counts heavily in favour of new constructs.&lt;br /&gt;&lt;br /&gt;I strongly suggest browsing through past PEPs (both accepted and rejected ones) before proposing syntax changes, but here are some examples of syntactic sugar proposals that were accepted.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;List/set/dict comprehensions&lt;/b&gt;&lt;br /&gt;(and the reduction builtins any(), all(), min(), max(), sum())&lt;br /&gt;&lt;pre class="brush: py"&gt;target = [op(x) for x in source]&lt;/pre&gt;instead of:&lt;br /&gt;&lt;pre class="brush: py"&gt;target = []&lt;br /&gt;for x in source:&lt;br /&gt;    target.append(op(x))&lt;/pre&gt;The transformation (`op(x)`) is far more prominent in the comprehension version, as is the fact that all the loop does is produce a new list. I include the various reduction builtins here, since they serve exactly the same purpose of taking an idiomatic looping construct and turning it into a single expression.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Generator expressions&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: py"&gt;total = sum(x*x for x in source)&lt;/pre&gt;instead of:&lt;br /&gt;&lt;pre class="brush: py"&gt;def _g(source):&lt;br /&gt;    for x in source:&lt;br /&gt;        yield x*x&lt;br /&gt;total = sum(_g(x))&lt;/pre&gt;or:&lt;br /&gt;&lt;pre class="brush: py"&gt;total = sum([x*x for x in source])&lt;/pre&gt;Here, the GE version has obvious readability gains over the generator function version (as with comprehensions, it brings the operation being applied to each element front and centre instead of burying it in the middle of the code, as well as allowing reduction operations like sum() to retain their prominence), but doesn't actually improve readability significantly over the second LC-based version. The gain over the latter, of course, is that the GE based version needs a lot &lt;i&gt;less memory&lt;/i&gt; than the LC version, and, as it consumes the source data&lt;br /&gt;incrementally, can work on source iterators of arbitrary (even infinite) length, and can also cope with source iterators with large time gaps between items (e.g. reading from a socket) as each item will be returned as it becomes available (obviously, the latter two features aren't useful when used in conjunction with reduction operations like sum, but they can be helpful in other contexts).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;With statements&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: py"&gt;with lock:&lt;br /&gt;    # perform synchronised operations&lt;/pre&gt;instead of:&lt;br /&gt;&lt;pre class="brush: py"&gt;lock.acquire()&lt;br /&gt;try:&lt;br /&gt;    # perform synchronised operations&lt;br /&gt;finally:&lt;br /&gt;    lock.release()&lt;/pre&gt;This change was a gain for both readability and writability - there were plenty of ways to get this kind of code wrong (e.g. leave out the try-finally altogether, acquire the resource inside the try block instead of before it, call the wrong method or spell the variable name wrong when attempting to release the resource in the finally block), and it wasn't easy to audit because the resource acquisition and release could be separated by an arbitrary number of lines of code. By combining all of that into a single line of code at the beginning of the block, the with statement eliminated a lot of those issues, making the code much easier to write correctly in the first place, and also easier to audit for correctness later (just make sure the code is using the correct context manager for the task at hand).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Function decorators&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: py"&gt;@classmethod&lt;br /&gt;def f(cls):&lt;br /&gt;    # Method body&lt;/pre&gt;instead of:&lt;br /&gt;&lt;pre class="brush: py"&gt;def f(cls):&lt;br /&gt;    # Method body&lt;br /&gt;f = classmethod(f)&lt;/pre&gt;Easier to write (function name only written once instead of three times), and easier to read (decorator names up top with the function signature instead of buried after the function body). Some folks still dislike the use of the @ symbol, but compared to the drawbacks of the old approach, the dedicated function decorator syntax is a huge improvement.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conditional expressions&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: py"&gt;x = A if C else B&lt;/pre&gt;instead of:&lt;br /&gt;&lt;pre class="brush: py"&gt;x = C and A or B&lt;/pre&gt;The addition of conditional expressions arguably wasn't a particularly big win for readability, but it &lt;i&gt;was&lt;/i&gt; a big win for correctness. The and/or based workaround for the lack of a true conditional expression was not only hard to read if you weren't already familiar with the construct, but using it was also a potential source of bugs if A could ever be False while C was True (in such cases, B would be returned from the expression instead of A).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Except clause&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: py"&gt;except Exception as ex:&lt;/pre&gt;instead of:&lt;br /&gt;&lt;pre class="brush: py"&gt;except Exception, ex:&lt;/pre&gt;Another example of changing the syntax to reduce the potential for non-obvious bugs (in this case, except clauses like `except TypeError, AttributeError:`, that would actually never catch AttributeError, and would locally do AttributeError=TypeError if a TypeError was caught).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-4496045007317678506?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/4496045007317678506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/02/justifying-python-language-changes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/4496045007317678506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/4496045007317678506'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/02/justifying-python-language-changes.html' title='Justifying Python language changes'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-6339674811309705885</id><published>2011-02-15T23:29:00.000+10:00</published><updated>2011-02-15T23:29:45.486+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='metablogging'/><title type='text'>Bye-bye Blogilo</title><content type='html'>OK, when a blogging app can't figure out my blog identity automatically and crashes every time I submit a post (but after submitting the post to blogger), 'tis clearly not the app for me.&lt;br /&gt;&lt;br /&gt;I'm just happy the first 3 posts didn't properly include the 'python' tag either, so at least Planet Python shouldn't have been spammed with any noise.&lt;br /&gt;&lt;br /&gt;Back to the in-browser editor for now...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-6339674811309705885?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/6339674811309705885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/02/bye-bye-blogilo.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/6339674811309705885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/6339674811309705885'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/02/bye-bye-blogilo.html' title='Bye-bye Blogilo'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-155949996452757388</id><published>2011-02-15T23:21:00.002+10:00</published><updated>2011-02-16T10:50:17.846+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>To Pycon and beyond...</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;p&gt;All these Planet Python posts about interesting talks and info at Pycon finally tipped me over the edge into making the trek across the Pacific to meet some of these people I've been working with online for the past half-dozen years or so.&lt;/p&gt;&lt;p&gt;With 3.3 still 18-24 months away, we should be able to get a pretty good road map thrashed out for ideas we want to explore for possible inclusion. Some face-to-face discussions will be especially handy for me, given the things I'd like to see sorted out: module aliasing to clean up __main__ handling once and for all, bringing back implicit context managers now we have more collective experience with explicit ones, an alternative to PEP 377 that will allow context managers to do some additional setup inside the scope of the try block, clarifying the semantic questions raised by discrepancies between the PEP 3118 buffer API spec and its implementation.&lt;/p&gt;&lt;p&gt;I still have some paperwork to sort out once my renewed passport arrives, but aside from that, the trip is good to go. I did stuff my travel dates up a bit and will have a day to kill in Atlanta on the 9th, but I'm sure I'll be able to figure out something interesting to do :)&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-155949996452757388?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/155949996452757388/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/02/to-pycon-and-beyond_8775.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/155949996452757388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/155949996452757388'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/02/to-pycon-and-beyond_8775.html' title='To Pycon and beyond...'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-3407724408989675799</id><published>2011-02-05T00:30:00.000+10:00</published><updated>2011-02-07T22:30:41.142+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='metablogging'/><title type='text'>Linking sites in blog posts</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;p&gt;Call me paranoid, but the idea of trusting a blogging app with my Google account details really doesn't appeal to me. So, "BlogThis!" on the links bar it is.&lt;br/&gt;&lt;br/&gt;It would be nice if BlogThis! popped up the full Blogger editor instead of a partial one (missing features like editing the post tags), but using it to save pre-linked drafts should be more than adequate for those occasions when I'm commenting on a link rather than writing something from scratch.&lt;/p&gt;&lt;p&gt;Test: editing an existing post...&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-3407724408989675799?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/3407724408989675799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/02/linking-sites-in-blog-posts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/3407724408989675799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/3407724408989675799'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/02/linking-sites-in-blog-posts.html' title='Linking sites in blog posts'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-4173644948231621615</id><published>2011-01-27T22:50:00.001+10:00</published><updated>2011-01-27T23:13:28.773+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='metablogging'/><title type='text'>Comments update and site to-do list</title><content type='html'>Having used DISQUS elsewhere as a commenter and not being a great fan of the default Blogger comment system, I've configured the blog to use DISQUS instead.&lt;br /&gt;&lt;br /&gt;I've also asked to have the blog's python related posts added to the Planet Python feed, so we'll see how that pans out.&lt;br /&gt;&lt;br /&gt;The main thing I'm still not entirely happy with is the site colour scheme - while I'm still a fan of the whole light-text-on-dark-background style, the contrast between clicked links and the current black background really isn't significant enough. I'll probably tinker with that a bit over the next few days.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-4173644948231621615?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/4173644948231621615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/01/comments-update-and-site-to-do-list.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/4173644948231621615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/4173644948231621615'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/01/comments-update-and-site-to-do-list.html' title='Comments update and site to-do list'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-6489967966314701145</id><published>2011-01-27T22:45:00.000+10:00</published><updated>2011-01-27T22:45:05.305+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Some goals for Python 3.3</title><content type='html'>With 3.2 nearly out the door, it's time to think seriously about goals for Python 3.3 and anything else I'd like to get done on the Python front this year. This post will serve as a to-do list of sorts.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;PEP 1 Update&lt;/b&gt;&lt;br /&gt;When cleaning up PEP 0 to clear out some of the accumulated cruft in the lists of Meta and Informational PEPs, I ran into a problem where the API specification PEPs use the "Final" state to indicate when consensus has been reached and the API has been locked in. This conflicts with the normal use of the Final state to indicate that a PEP is over a done with and is only being kept around for historical reasons.&lt;br /&gt;&lt;br /&gt;A brief discussion on python-dev suggested "Consensus" as a new end state for these PEPs. I like that solution, but adopting it requires an update to PEP 1. I'd like to get to that sometime this year.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;PEP 343 and 377, redux&lt;/b&gt;&lt;br /&gt;There are a couple of rough edges on the with statement and the associated context management protocol that still bother me.&lt;br /&gt;&lt;br /&gt;Firstly, the fact that there is no way for a context manager to skip the body of a with statement means certain constructs simply can't be factored out properly. I previously tried to address this with PEP 377, but that solution was rightly rejected as having too great an impact on common cases which didn't need the extra complexity. I have since thought of an alternative approach that is both more flexible and has a much lower impact on ordinary cases, so it has a higher chance of acceptance.&lt;br /&gt;&lt;br /&gt;Secondly, I'd like to revisit the idea of implicit context managers. These were dropped from PEP 343 due largely to terminology problems - we weren't sure whether the term "context manager" referred to objects with enter and exit methods, or to the objects that were able to create such an object on demand. With the meaning of context manager now well established, I believe it should be possible to implement and document this in a way that makes intuitive sense, while making it significantly easier to write context managers that are both stateful and reusable.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;That's my __name__, don't wear it out&lt;/b&gt;&lt;br /&gt;As per a &lt;a href="http://mail.python.org/pipermail/python-ideas/2011-January/008983.html"&gt;recent python-ideas discussion&lt;/a&gt;, __name__ currently serves multiple masters, which leads to conflicts in certain situations (with __name__ set to a value that is correct for some purposes, but wrong for others). This is especially prevalent with the __main__ module, but can also apply to pseudo-packages, where something is documented as a single unified namespace, but is actually implemented as multiple files combined into a package.&lt;br /&gt;&lt;br /&gt;For Python 3.3, I'd like to have a mechanism in place to start sorting this out without breaking every Python script on the planet that relies on the "if __name__ == '__main__':" idiom.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Other PEPs (e.g. PEP 380, 393)&lt;/b&gt;&lt;br /&gt;There are a few other PEPs that will hopefully be landing for 3.3, including the subgenerator and memory efficient string PEPs. While I probably won't take much of an active hand in implementing those, there will still be plenty of related python-dev discussion and checkins to review.&lt;br /&gt;&lt;br /&gt;And on a completely non-code-related front... with any luck I'll be able to find myself a more directly open source focused job this year. I have the luxury of being fussy in my choice of employment though, so I can happily sit back and relax while waiting to see how that pans out :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-6489967966314701145?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/6489967966314701145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/01/some-goals-for-python-33.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/6489967966314701145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/6489967966314701145'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/01/some-goals-for-python-33.html' title='Some goals for Python 3.3'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-5900846803184105554</id><published>2011-01-11T03:21:00.001+10:00</published><updated>2011-08-27T18:40:12.052+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><title type='text'>Which matters more to you: being right or staying friends?</title><content type='html'>Browsing through the &lt;a href="http://www.religioustolerance.org"&gt;Religious Tolerance&lt;/a&gt; site, I felt inspired to turn my Ethos post into a Visitor Essay submission. I have no idea if they will ever post it (as it turns out, they did so quite promptly, &lt;a href="http://www.religioustolerance.org/coghlan01.htm"&gt;here&lt;/a&gt;), but decided to put the whole thing up here (after the jump) regardless.&lt;a name='more'&gt;&lt;/a&gt;The role of faith in my life has been a varied one. My parents are Roman Catholics (albeit ones with more than a few issues with the way the Church hierarchy run the show), and so I grew up doing the traditional Roman Catholic thing - convent primary school (although there were no teaching nuns by the time I came through) followed by a Christian Brothers high school (although again, one with mostly lay teachers). Church on Sunday was a weekly family ritual, and after drifting away into the typical agnosticism of the Australian teenager, I rediscovered my faith through the National Evangelisation Teams program. Enthused about my faith again, I started actually studying it - reading the Bible, looking at church teachings, that kind of thing. But something strange happened - the more I studied, the more hollow it all seemed. I *didn't* agree with everything the Bible said, or everything the Church taught, and neither did my parents. Clearly I was using something else as the basis for my moral decisions in which Church teachings I chose to agree with and which I chose to reject, but what was it?A Star Wars fan website (of all things [1]) led me to encounter the phrase "secular humanism". Reading up on that, I found it agreed perfectly with the criteria I had been applying in picking and choosing amongst the teachings of the Catholic Church. I was happy to have found a term for my beliefs that focused on what I believed in, rather than simply highlighting one thing I had chosen to reject (i.e. "atheism"). One cognitive science degree and a whole lot of reading later (including the likes of Dawkins, Dennett, Hofstadter, Pinker and Sagan), and I was even happier with the idea of a world where we create our own meaning rather than having it passed down to us from on high.The journey from childhood faith, through teenage agnosticism to adult faith and my eventual deliberate choice of a naturalistic world view was something that involved a lot of thought and introspection, that I was fortunate enough to have the time for. However, it left me with a problem. Many of my family are still devout (or not-so-devout) Catholics and my friends embrace a variety of religious traditions. How could I align what I had discovered for myself with their different points of view, without coming off (to myself or to others) as a condescending twit making allowances for the "less enlightened"?The militant atheists (such as Dawkins) often come across as wanting to see the religious baby thrown out with the fundamentalist bathwater. Others (such as Dennett) are able to put forward a more nuanced view, that attempts to better understand the whole of religion, so that we can more effectively harness the positive aspects while reducing the negative effects. Having been a believer as an adult, and having suffered no significant negative experiences through my faith, I have a much easier time seeing the good side of religious belief than many atheists, so Dennett's line of rapprochement seemed far more appealing to me.Eventually, I was able to distil my personal ethos down into a belief that the pillars of ethical and moral living consist of just 5 basic concepts: honesty, compassion, justice, freedom and hope. As I see it, we have to believe in something, otherwise nihilism wins and there is no point in getting out of bed in the morning. For myself, and humanists like me, I see those five things as products of evolution. I see them as glorious, beautiful things in their own right, the most profound creations of the human race. It is up to each of us to honour and steward each of the principles as best we can. Others choose to see those 5 principles as something that was gifted to us by a higher power, rather than something we created collectively ourselves over the course of time. I don't agree with such beliefs, but that is only because I see them as unnecessary. In practice, if the outcome is a personal faith that accepts and promotes the same 5 principles I believe in, then I don't really care all that much as to why somebody agrees they're important.Where I start to have an issue is when groups and individuals either consciously or inadvertently start to disrespect those ideals. Whether the offenders are governments, organised religions, corporations, or specific individuals, malicious deceit, discounting of the feelings of others, inequitable treatment, unnecessary coercive restraints and excessive pessimism and fatalism are all concepts I have fundamental problems with. Of course, balancing all of those principles means that there are many situations encountered in the real world that have no right answers, only less bad wrong ones, which is why reasonable people may disagree on the correct courses of action. Simply "getting rid of religion" doesn't magically make the underlying issues go away.The dangerous religions are the ones that create a priestly caste and then say to everyone else "It's complicated, it's a mystery, don't worry your pretty little head about it". By convincing people to shut down their capacity for critical thinking, they are trampling over a number of those principles I value (especially honesty and freedom). Religious traditions that instead encourage their believers to adopt an attitude of constant questioning are far more compatible with the humanist point of view, as it allows members of that faith to make their own judgments based on universal ethical principles in addition to the teachings of that specific tradition.This separation of beliefs from consequences (similar to the distinction made between beliefs and actions here at OCRT) and individual believers from religious organisations was the insight I needed to realise that it was possible to be religiously tolerant without feeling (or being) condescending about it.[1] For the record, it was &lt;a href="http://www.stardestroyer.net"&gt;Stardestroyer.net&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-5900846803184105554?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.religioustolerance.org/coghlan01.htm' title='Which matters more to you: being right or staying friends?'/><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/5900846803184105554/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2011/01/which-matters-more-to-you-being-right.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/5900846803184105554'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/5900846803184105554'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2011/01/which-matters-more-to-you-being-right.html' title='Which matters more to you: being right or staying friends?'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-1302673954966215100</id><published>2010-12-12T23:29:00.000+10:00</published><updated>2010-12-12T23:29:15.926+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='metablogging'/><title type='text'>Joining the modern era of blogging</title><content type='html'>Wow, that template was old. OK, brushed the dust out of the corners (i.e. switched to the modern Blogger template engine and away from the old crappy one) and correctly configured the domain delegation for the www.boredomandlaziness.org address.&lt;br /&gt;&lt;br /&gt;Once the DNS updates filter through the intarwebs, I'll reconfigure Blogger to use that address instead of the default one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-1302673954966215100?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/1302673954966215100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2010/12/joining-modern-era-of-blogging.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/1302673954966215100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/1302673954966215100'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2010/12/joining-modern-era-of-blogging.html' title='Joining the modern era of blogging'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-7534730323890101593</id><published>2010-12-12T20:54:00.014+10:00</published><updated>2011-02-15T23:58:45.828+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fiction'/><title type='text'>Musings on the LotR movie adaptations</title><content type='html'>A friend recently asked me how I thought the major changes Peter Jackson made when adapting Lord of the Rings to the screen were received by fans of the book. Even with a few years perspective, I can only speak for myself and the fans that I know personally in saying they were well received. However, they were all also well-justified from a movie crafting perspective, so that definitely helped with the way they were perceived.&lt;br /&gt;&lt;br /&gt;In general, I believe each of the changes was greeted with grumbling in some places, but the whole of the work was so obviously respectful of the original, and such an excellent movie for fans of the genre, that all the changes were forgiven. I'm also ignoring things that were cut from the theatrical releases, but included in the extended DVD versions (e.g. Galadriel's gifts).&lt;br /&gt;&lt;br /&gt;Be warned, there are plenty of spoilers for both the books and the movies ahead, so if you're at all sensitive about such things, stop reading now :)&lt;br /&gt;&lt;br /&gt;(And yes, I &lt;span style="font-style: italic;"&gt;was&lt;/span&gt; able to name all these discrepancies off the top of my head... I probably missed some, though, since I forced myself not to look anything up on the web while writing it). Details after the jump...&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;Show a bit of urgency, people&lt;/span&gt;&lt;br /&gt;In the book, 17 years pass between Bilbo's birthday party (Bilbo 111, Frodo 33) and the time when Gandalf tells Frodo to get out of the shire. Such a lack of urgency really wouldn't have worked for the movie, and the loss of the One Ring adequately explains Bilbo's rapid aging in the time he was at Rivendell before Frodo arrives. Most people I know thought the original time frame in the book was kind of dumb, so speeding it up for the movie met with general approval.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Removal of Old Man Willow, Tom Bombadil and the Barrows&lt;/span&gt;&lt;br /&gt;Some people love this part of the books, many (*ahem*) see it as a relatively pointless detour that needlessly delays the arrival at Bree and the introduction of Aragorn as a character. You can get away with that kind of slow introduction in a long novel, but there was no way it was going to fit into the movie version of Fellowship. There was still plenty of tension in the journeys to Bree and Rivendell with just the Dark Riders as the threat.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Arwen stealing Glorfindel's lines&lt;/span&gt;&lt;br /&gt;In the books, Arwen is actually portrayed as a princess type that actually doesn't &lt;span style="font-style: italic;"&gt;do&lt;/span&gt; a great deal. Giving her Glorfindel's part in addition to her own gave the character more screen time and set her up as a &lt;span style="font-style: italic;"&gt;far&lt;/span&gt; more suitable match for Aragorn. If they hadn't done this, I think people that &lt;span style="font-style: italic;"&gt;weren't&lt;/span&gt; familiar with the books would have been (justifiably) up in arms about Aragorn choosing her over Eowyn. (Heck, even in the books Aragorn's choice isn't well justified - while Arwen is established as a generally competent lass in the Tolkien's notes, she really isn't portrayed as such in the books).&lt;br /&gt;&lt;br /&gt;Also, it meant one less character to introduce within the time constraints of a movie (particularly since Glorfindel basically disappears from the story after Rivendell).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Aren't those separate stories?&lt;/span&gt;&lt;br /&gt;The Two Towers actually has a fairly questionable story telling structure. The first half is the tale of what happened to Merry, Pippin, Aragorn, Legolas and Gimli, while the second is the tale of Frodo and Sam. Interleaving them was an obvious change to make for movie adaptation, and I don't think there was even any significant grumbling about that one.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Hey, let's throw Aragorn off a cliff!&lt;/span&gt;&lt;br /&gt;Given the number of things from the books that were cut, this random addition was actually the change I found most irritating (and I'm not alone). In the books, nothing much of significance happens on the journey to Helm's Deep that I can recall.&lt;br /&gt;&lt;br /&gt;That said, this sequence did give them a chance to practice a bit of "show, don't tell" as far as Eowyn's feelings for Aragorn went, so it made a certain amount of sense from that point of view. On the commentaries, I believe Jackson said they were concerned about the lack of threat to Aragorn for most of the movie and put this in to spice things up a bit.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Elves in Rangers' clothing&lt;/span&gt;&lt;br /&gt;In the book, there are no elves at Helm's Deep. Instead, a bunch of Aragorn's fellow Rangers (i.e. long-lived Men of Numenor, like Aragorn) turn up. However, using the Rangers in the movie would have required setting up the Rangers as a group that existed, what their relationship was with Aragorn, and why their assistance was to be valued so much more than a similarly sized group of ordinary men. By using elves instead, Jackson was able to achieve a similar effect without trying to cram in all that additional exposition to established just who these people were.&lt;br /&gt;&lt;br /&gt;Most people I know were happy to accept the troop of elves as the spiritual representatives of the Rangers from the books, but there was definitely some online griping about this one.&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The outcome of the Entmoot&lt;/span&gt;&lt;br /&gt;In the books, the result of the Entmoot is a decision to go destroy Isengard. After-the-fact persuasion by Merry, a curious perceptive blindness by Treebeard as to the  state of the forests near Isengard and a subsequent unilateral decision to attack on seeing them in person are nowhere to be found. At this stage of the books, Merry and Pippin are still really just along for the ride - their characters arcs really don't start properly until Return of the King, and culminate in the Scouring of the Shire.&lt;br /&gt;&lt;br /&gt;So, while I don't particularly like what Jackson, Walsh and Boyens did here (mainly because I think it disagrees with Tolkien's lore on what Ents can perceive within their own forests), I can understand the desire to give Merry and Pippin more of an active role earlier in the story, since the end of their pre-established arcs was going to be left out (more on that later).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Hobbits in Osgiliath&lt;/span&gt;&lt;br /&gt;Another controversial one - in the books, Frodo and Sam are never in Osgiliath, and Faramir doesn't get there until some time in Return of the King. Instead, Faramir encounters the two hobbits and takes them back to his base in Ithilien. They there convince him of their purpose and he releases them to continue on their journey.&lt;br /&gt;&lt;br /&gt;I suspect the screenwriters had two motives in making Faramir a bit more hardnosed about things and relocating the Ithilien part of the story. Firstly, it allowed the two halves of the story to be better weaved together at the end of second movie. As noted above, the book treats the two storylines as completely separate, which didn't really fit with the interleaved structure of the movie.&lt;br /&gt;&lt;br /&gt;Secondly, it saved them the hassle of creating the Ithilien base as a location. (at least, I don't recall the movie making much, if any, use of that base).&lt;br /&gt;&lt;br /&gt;I actually didn't mind this change, but a lot of people didn't like what they felt it implied about Faramir's character (personally, I thought making him a bit more hard-nosed than the book version wasn't a bad thing).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Giant spiders can't read calendars&lt;/span&gt;&lt;br /&gt;The encounter with Shelob is actually part of The Two Towers. The screenwriters postponed it to Return of the King in order to balance out the screen time in the final movie a little better. This change also fit with the change to make their release by Faramir the climax of this half of the storyline in the second movie.&lt;br /&gt;&lt;br /&gt;This was a change that made a lot of sense and I don't believe there were many complaints about it. Without it, The Two Towers ends on a serious downer with Frodo trapped in the tower, and their storyline in Return of the King consists of escaping from the tower and an awful lot of trudging across the Plains of Gorgoroth.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;He's dead, Jim&lt;/span&gt;&lt;br /&gt;Saruman didn't die at Isengard in the books. Instead, they get the palantir because Wormtongue throws it at them, and then they leave him in the tower under the guard of the Ents. This is important, since he plays a vital role in the Scouring of the Shire.&lt;br /&gt;&lt;br /&gt;When they dropped the Scouring from the movies, they decided to make sure people knew he was quite assuredly dead by not only dropping him from a great height, but also making sure he landed on some big spikes that not only went all the way through him, but also were conveniently mounted on a wheel that could put him underwater as well. Just in case you were thinking he might have survived falling off Orthanc. I was somewhat surprised nobody carved out his heart and ate it on screen just to further make the point "No, he's really, really dead. He's NOT coming back at the end of the movie."&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Pippin the pyromaniac&lt;/span&gt;&lt;br /&gt;I believe the scene with Pippin sneaking up to light the signal fire was a new addition for the movie (although I don't recall what happened in the book instead - while Gandalf certainly argued with Denethor a lot about calling for the Rohirrim, I seem to recall Denethor grudgingly authorising the signal). I didn't mind it, since it gave Pippin more of an active role in the story, a necessary change due to the final (and likely least popular) change, which we move on to now...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The (non-)Scouring of the Shire&lt;/span&gt;&lt;br /&gt;Wow, this one upset a lot of people. People that haven't read the books probably don't realise just &lt;span style="font-style: italic;"&gt;how much&lt;/span&gt; Jackson cut from the denouement following the destruction of the ring.&lt;br /&gt;&lt;br /&gt;It was a genuine loss that this had to go, but it really &lt;span style="font-style: italic;"&gt;did&lt;/span&gt; have to go. The Scouring is a great story - it was the real payoff for Pippin and Merry's character arcs as they become the first true hobbit warriors the world has ever seen and take back the Shire from the nefarious villain that has taken control of it (who turns out, *gasp*, to be a certain prisoner that has escaped from Orthanc and wants revenge on those darn hobbits that ruined his schemes).&lt;br /&gt;&lt;br /&gt;The other part of the Scouring is that after Merry and Peppin do the actual scouring part, the start of the rebuilding is what truly closes off &lt;span style="font-style: italic;"&gt;Sam's&lt;/span&gt; story arc, as he takes the seed he received as a gift from Galadriel and plants it as a replacement for the party tree that was destroyed in their absence.&lt;br /&gt;&lt;br /&gt;However, the problem with the Scouring from a movie makers point of view is that it is also quite a &lt;span style="font-style: italic;"&gt;long&lt;/span&gt; story that takes place after the climax of the main storyline (i.e. the destruction of the ring and Sauron). Return of the King had a good dozen or so endings as it was, there was absolutely no way for them to also try to cram the Scouring in there.&lt;br /&gt;In addition, the Scouring is all about the indomitable spirit of the hobbits when given a little bit of hope in the form of the mature and battle hardened Merry and Pippin and the ever-resilient Sam, despite the physical destruction and dominant presence of "Sharkey". That kind of thing is quite hard to portray on screen - an-indomitable-spirit-despite-surrounding-destruction looks an awful lot like plain old destruction to the viewer's eye.&lt;br /&gt;&lt;br /&gt;So, they took the simpler option of leaving the Scouring out of the story altogether, with a homage to it included in Fellowship when Frodo looks into Galadriel's mirror.  As noted in the relevant sections above, this also forced them to bring the development of Merry and Pippin forward a bit, and give them more to do in other parts of the story. (The bit with Merry stabbing the Witch King in the leg so Eowyn could kill him, though? Yeah, that was from the book - you know, with the whole prophecy thing and all...)&lt;br /&gt;&lt;br /&gt;As I said above, I actually agree with their decision to drop the Scouring of the Shire. As cool a story as it is, it just didn't fit into the limitations of the movie format. Better to leave it out completely than try to jam it in where it didn't fit and do a poor job of it as result.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-7534730323890101593?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/7534730323890101593/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2010/12/musings-on-lotr-movie-adaptations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/7534730323890101593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/7534730323890101593'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2010/12/musings-on-lotr-movie-adaptations.html' title='Musings on the LotR movie adaptations'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-3128769168021432160</id><published>2010-12-12T17:19:00.009+10:00</published><updated>2011-06-22T23:58:32.618+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><title type='text'>An Ethos</title><content type='html'>(Note: I expanded this post into a &lt;a href="http://www.boredomandlaziness.org/2011/01/which-matters-more-to-you-being-right.html"&gt;more comprehensive essay&lt;/a&gt;)&lt;br /&gt;Somewhat inevitably, Howard Tayler's review of Voyage of the Dawn Treader over on the Schlock Mercenary blog got into something of a religious debate in the comments.&lt;br /&gt;&lt;br /&gt;My &lt;a href="http://www.schlockmercenary.com/blog/dawn-treader#comment-110549921"&gt;contribution to the thread&lt;/a&gt; was an attempt at writing down the core concepts of a personal ethos I have been formulating over the last decade or so. I quite liked how it came out, so I figured I would capture it here as well.&lt;br /&gt;&lt;blockquote&gt;For mine, I see the pillars of ethical and moral living as a belief in 5 basic concepts: honesty, compassion, justice, freedom and hope. We have to believe in &lt;span style="font-style: italic;"&gt;something&lt;/span&gt;, otherwise nihilism wins and there is no point in getting out of bed in the morning.&lt;br /&gt;&lt;br /&gt;For myself, and humanists like me, I see those five things as products of evolution. I see them as glorious, beautiful things in their own right, the most profound creations of the human race. It is up to each of us to honour and steward each of the principles as best we can.&lt;br /&gt;&lt;br /&gt;Others choose to see those 5 principles as something that was gifted to us by a higher power, rather than something we created collectively ourselves over the course of time. I don't &lt;span style="font-style: italic;"&gt;agree&lt;/span&gt; with such beliefs, but that is only because I see them as unnecessary. In practice, if the outcome is a personal faith that accepts and promotes the same 5 principles I believe in, then I don't really care all that much as to &lt;span style="font-style: italic;"&gt;why&lt;/span&gt; somebody agrees they're important.&lt;br /&gt;&lt;br /&gt;Where I start to have an issue is when groups and individuals either consciously or inadvertently start to disrespect those ideals. Whether the offenders are governments, organised religions, corporations, or specific individuals, malicious deceit, discounting of the feelings of others, inequitable treatment, unnecessary coercive restraints and excessive pessimism and fatalism are all concepts I have fundamental problems with.&lt;br /&gt;&lt;br /&gt;Of course, balancing all of those principles means that there are many situations encountered in the real world that have no right answers, only less bad wrong ones, which is why reasonable people may disagree on the correct courses of action. But "getting rid of religion" doesn't magically make the underlying issues go away.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-style: italic;"&gt;dangerous&lt;/span&gt; religions are the ones that create a priestly caste and then say to everyone else "It's complicated, it's a mystery, don't worry your pretty little head about it". By convincing people to shut down their capacity for critical thinking, they are trampling over a number of those principles I value (especially honesty and freedom). Religious traditions that instead encourage their believers to adopt an attitude of constant questioning are &lt;span style="font-style: italic;"&gt;far&lt;/span&gt; more compatible with the humanist point of view.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-3128769168021432160?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.schlockmercenary.com/blog/dawn-treader#comment-110549921' title='An Ethos'/><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/3128769168021432160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2010/12/ethos.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/3128769168021432160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/3128769168021432160'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2010/12/ethos.html' title='An Ethos'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-158067435139252720</id><published>2010-01-29T22:05:00.003+10:00</published><updated>2010-01-29T22:07:55.574+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Status quo wins a stalemate</title><content type='html'>Another old post for reference. This one's a fair bit shorter than the last one and just articulates why "do nothing" needs to be the default option when considering language changes where there are no particularly strong arguments either for or against the proposed change.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-158067435139252720?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://mail.python.org/pipermail/python-3000/2006-May/001936.html' title='Status quo wins a stalemate'/><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/158067435139252720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2010/01/status-quo-wins-stalemate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/158067435139252720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/158067435139252720'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2010/01/status-quo-wins-stalemate.html' title='Status quo wins a stalemate'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-1464395123049389738</id><published>2010-01-29T21:59:00.002+10:00</published><updated>2010-01-29T22:01:51.197+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Justifying Python language changes</title><content type='html'>Link to a mailing list post for my own benefit. Finding this again when I want to refer to it is usually a pain, so hopefully I'll remember it is linked here in the future. Either that or I'll tidy it up and turn it into a blog post in its own right.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-1464395123049389738?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://mail.python.org/pipermail/python-dev/2008-October/082831.html' title='Justifying Python language changes'/><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/1464395123049389738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2010/01/justifying-python-language-changes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/1464395123049389738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/1464395123049389738'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2010/01/justifying-python-language-changes.html' title='Justifying Python language changes'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-3660000444400465049</id><published>2010-01-17T22:46:00.003+10:00</published><updated>2010-01-17T23:14:06.972+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Kubuntu dev packages to build Python</title><content type='html'>List of all the additional packages needed for a full build of the optional Python modules in the 2.x standard library on Kubuntu 9.10:&lt;br /&gt;&lt;br /&gt;libssl-dev (OpenSSL integration)&lt;br /&gt;libreadline-dev (readline module integration)&lt;br /&gt;libgdbm-dev (a DBM backend)&lt;br /&gt;tk-dev (also brings in TCL via dependencies)&lt;br /&gt;tk-tile (extra bit of tk needed for some of the TTK GUI functionality)&lt;br /&gt;libsqlite3-dev (SQLite3 integration)&lt;br /&gt;libdb4.7-dev (BSDDB integration)&lt;br /&gt;&lt;br /&gt;(at least one of those brings in the necessary zlib build dependencies as well - probably SSL dev)&lt;br /&gt;&lt;br /&gt;Mostly for my own reference, but if it proves useful to somebody else via a search engine, cool :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-3660000444400465049?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/3660000444400465049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2010/01/kubuntu-dev-packages-to-build-python.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/3660000444400465049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/3660000444400465049'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2010/01/kubuntu-dev-packages-to-build-python.html' title='Kubuntu dev packages to build Python'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-3303716936699342280</id><published>2007-06-24T10:19:00.000+10:00</published><updated>2010-12-12T22:45:10.886+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><title type='text'>What he said</title><content type='html'>Occasionally you can come across an article which summarises your own thoughts so well, you don't really need to add anything. For me, the author's note on the linked webcomic is such an article.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-3303716936699342280?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.irregularwebcomic.net/1609.html' title='What he said'/><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/3303716936699342280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2007/06/what-he-said.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/3303716936699342280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/3303716936699342280'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2007/06/what-he-said.html' title='What he said'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-114442495473651573</id><published>2006-04-08T01:49:00.000+10:00</published><updated>2010-12-12T22:47:36.604+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='intarwebs'/><title type='text'>Ego Surfing</title><content type='html'>So, one of Techdirt's latest stories led me back to &lt;a href="http://www.canton.elegal.ca/archives/2006/02/internet_privac.html"&gt;this article&lt;/a&gt; about the perils of putting too much personal info on line. Possibly even things like having the words "boredom" and "laziness" as part of a domain name you own, and then not updating the associated website for months on end, so people googling your name can wonder about your follow-through when it comes to keeping up with projects you start*.&lt;br /&gt;&lt;br /&gt;Anyway, as a result I did a bit of googling of my own. It used to be that Google gave me &lt;a href="http://www.boredomandlaziness.org/2004/12/google-footprint.html"&gt; far more prominence&lt;/a&gt; than one might expect, with buckets of references to python-list and python-dev posts. When I noticed those posts weren't on the first list of results anymore, and links for both the actor and the surfer were now included, I thought Google might have done something to give the non-mailing list results more importance, and give a result that better reflected mainstream celebrity.&lt;br /&gt;&lt;br /&gt;A closer look though and I find that while the list of sites has changed, my original opinion still holds: even with a lot more mainstream media moving online, your Google footprint still says far more about your online presence than your fame (or lack thereof) in the offline world. And I still manage to find that fact both obvious and intriguing at the same time :)&lt;br /&gt;&lt;br /&gt;*(FWIW, most of the stuff I write online is Python related, and ends up on the Python mailing lists rather than here)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-114442495473651573?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/114442495473651573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2006/04/ego-surfing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/114442495473651573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/114442495473651573'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2006/04/ego-surfing.html' title='Ego Surfing'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-112186466365782766</id><published>2005-07-20T23:04:00.000+10:00</published><updated>2010-12-12T22:49:04.218+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='travel'/><title type='text'>Lance &amp; Hannah</title><content type='html'>&lt;a href="http://www.flickr.com/photos/ncoghlan/27325255/" title="photo sharing"&gt;&lt;img src="http://photos21.flickr.com/27325255_322a99bc8e_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;&lt;a href="http://www.flickr.com/photos/ncoghlan/27325255/"&gt;Lance &amp;amp; Hannah&lt;/a&gt; &lt;br /&gt;Originally uploaded by &lt;a href="http://www.flickr.com/people/ncoghlan/"&gt;Nick Coghlan&lt;/a&gt;.&lt;/span&gt;&lt;br clear="all" /&gt;&lt;p&gt;Lance &amp; Hannah in Japan&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-112186466365782766?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/112186466365782766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2005/07/lance-hannah.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/112186466365782766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/112186466365782766'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2005/07/lance-hannah.html' title='Lance &amp; Hannah'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-112186192602768737</id><published>2005-07-20T22:18:00.000+10:00</published><updated>2010-12-12T22:46:27.592+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='travel'/><title type='text'>Grand Column</title><content type='html'>&lt;p&gt;This marble column from the Oregon Caves looks pretty impressive.&lt;/p&gt;&lt;a href="http://www.flickr.com/photos/ncoghlan/7085212/" title="photo sharing"&gt;&lt;img src="http://photos5.flickr.com/7085212_910b44b72d_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;&lt;a href="http://www.flickr.com/photos/ncoghlan/7085212/"&gt;Grand Column&lt;/a&gt; &lt;br /&gt;Originally uploaded by &lt;a href="http://www.flickr.com/people/ncoghlan/"&gt;Nick Coghlan&lt;/a&gt;.&lt;/span&gt;&lt;br clear="all" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;That is, until you see it with a person in the picture for scale ;)&lt;/p&gt;&lt;a href="http://www.flickr.com/photos/ncoghlan/7085241/" title="photo sharing"&gt;&lt;img src="http://photos6.flickr.com/7085241_4f3207e4bb_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;&lt;a href="http://www.flickr.com/photos/ncoghlan/7085241/"&gt;Or Maybe Not So Grand Column?&lt;/a&gt; &lt;br /&gt;Originally uploaded by &lt;a href="http://www.flickr.com/people/ncoghlan/"&gt;Nick Coghlan&lt;/a&gt;.&lt;/span&gt;&lt;br clear="all" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-112186192602768737?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/112186192602768737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2005/07/grand-column.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/112186192602768737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/112186192602768737'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2005/07/grand-column.html' title='Grand Column'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-111419014821727991</id><published>2005-04-23T03:15:00.000+10:00</published><updated>2010-12-12T22:47:36.604+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='intarwebs'/><title type='text'>Self-defeating Advertisements</title><content type='html'>My main web browser is Mozilla Firefox. It has this lovely little extension called AdBlock, which let's me eliminate irritating content from the web pages I view. So what does that have to do with the title of the article?&lt;br /&gt;&lt;br /&gt;Simple: A lot of the time, I &lt;i&gt;do not switch AdBlock on&lt;/i&gt;. Normal banner ads, that generally stay out of my way, just plain don't bother me that much. I'm happy to let them appear on the screen (even if I don't click on them). As soon as an ad starts intruding on my web experience, though, out comes AdBlock, so I can say "Leave me the hell alone, you rude, pushy mongrels". Some ads get my attention without triggering that reflex (Absolut and IBM come to mind), because they don't block the main text, and are genuinely entertaining. Other ads (especially ones that interfere with real content) discover that getting too much of my attention can be a bad thing - it raises the irritation level enough to get me to take action. And, thanks to AdBlock's address wildcards, that will mean far more than just the one ad that triggered the block will be eliminated from my web surfing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-111419014821727991?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/111419014821727991/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2005/04/self-defeating-advertisements.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/111419014821727991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/111419014821727991'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2005/04/self-defeating-advertisements.html' title='Self-defeating Advertisements'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-110761198544540995</id><published>2005-02-05T23:59:00.000+10:00</published><updated>2005-02-05T23:59:45.446+10:00</updated><title type='text'>Because James doesn't remember it</title><content type='html'>&lt;a href="http://www.thingsmygirlfriendandihavearguedabout.com/" target="_top"&gt;TMGAIHAA&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-110761198544540995?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/110761198544540995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2005/02/because-james-doesnt-remember-it.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110761198544540995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110761198544540995'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2005/02/because-james-doesnt-remember-it.html' title='Because James doesn&apos;t remember it'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-110388209637610627</id><published>2004-12-24T19:54:00.000+10:00</published><updated>2010-12-12T22:48:16.057+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='metablogging'/><title type='text'>Email Blogging</title><content type='html'>Just checking it works. Nothing to see here. Move along.&lt;br /&gt;&lt;br /&gt;-- &lt;br /&gt;Nick Coghlan   |   ncoghlan@email.com   |   Brisbane, Australia&lt;br /&gt;---------------------------------------------------------------&lt;br /&gt;             http://boredomandlaziness.skystorm.net&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-110388209637610627?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/110388209637610627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2004/12/email-blogging.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110388209637610627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110388209637610627'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2004/12/email-blogging.html' title='Email Blogging'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-110387989393663651</id><published>2004-12-24T19:18:00.000+10:00</published><updated>2010-12-12T22:45:31.162+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Type-checking in Python</title><content type='html'>So, Guido has brought up the idea of &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=85551" title="Optional Static Typing" target="_top"&gt;optional static typing&lt;/a&gt; again, posting his current throughts on the idea, as well as noting what he sees as the problem areas.&lt;br /&gt;&lt;br /&gt;His favoured syntax is:&lt;br /&gt;&lt;font face="'Courier New',Courier,monospace"&gt;&lt;br /&gt;def (a: sometype, b: sometype) -&gt; sometype:&lt;br /&gt;&amp;nbsp;&amp;nbsp;pass&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;Bleh. The main reason I dislike the current version of anonymous functions is because they embed a colon in the middle of an expression so you can probably guess how I feel about Guido's reuse of the colon here. And I've always quite liked VB's approach of using 'as' to indicate the return type of a function. Anyway, syntax aside, there's a question of what the optional type declarations are actually &lt;i&gt;for&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Now one point to make at the start is that optional typing (checked by the VM) and optional &lt;i&gt;static&lt;/i&gt; typing (checked by the compiler) are different things, and it makes some sense to do the former before doing the latter. Once you have a syntax for optional typing, making it static is merely a question of figuring out how to get the compiler to do the type check, instead of the VM. This activity would then blend in with Python's general issue of "how can we move things to the compiler to save run-time activity, without losing too much dynamism?"&lt;br /&gt;&lt;br /&gt;Having dropped the static idea for the moment, there's the fundamental question of what does a type declaration &lt;i&gt;mean&lt;/i&gt;? Python has historically relied on an approach that says "if it defines the right methods, it's OK by me". This is great for flexibility and code reuse, but plays merry hell with type inferencing systems, and can lead to some exceedingly cryptic error messages when you pass a type that doesn't provide the correct methods (or provides methods with the right names, but the wrong signatures, etc, etc).&lt;br /&gt;&lt;br /&gt;Stealing an example I like:&lt;br /&gt;&lt;font face="'Courier New',Courier,monospace"&gt;&lt;br /&gt;def int_divide(x as Integer, y as Integer) as Integer:&lt;br /&gt;&amp;nbsp;&amp;nbsp;return x / y&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;We don't &lt;i&gt;really&lt;/i&gt; want &lt;font face="'Courier New',Courier,monospace"&gt;x as Integer&lt;/font&gt; (or &lt;font face="'Courier New',Courier,monospace"&gt;x : Integer&lt;/font&gt; in Guido's syntax) to mean &lt;font face="'Courier New',Courier,monospace"&gt;isinstance(x, Integer)&lt;/font&gt; do we? After all, we'd like this function to work for builtin types, and Python's builtin types won't know anything about this interface we have created. It would be far nicer if the optional typing was just a way of formalising the 'duck typing' that Python currently relies on.&lt;br /&gt;&lt;br /&gt;So let's consider something like the interfaces from PJE's PEAK, or Eiffel's idea of conformance (&lt;a href="http://www.python.org/peps/pep-0246.html"  target="_top"&gt;PEP 246&lt;/a&gt;, basically). In this case, we have a builtin method &lt;font face="'Courier New',Courier,monospace"&gt;adapt()&lt;/font&gt; to adapt a given object to a given protocol. I'd suggest the meaning of the example should become:&lt;br /&gt;&lt;font face="'Courier New',Courier,monospace"&gt;&lt;br /&gt;def int_divide(x, y):&lt;br /&gt;&amp;nbsp;&amp;nbsp;x = adapt(x, Integer)&lt;br /&gt;&amp;nbsp;&amp;nbsp;y = adapt(y, Integer)&lt;br /&gt;&amp;nbsp;&amp;nbsp;return adapt(x / y, Integer)&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;Objects participate in this scheme as interfaces by definining &lt;font face="'Courier New',Courier,monospace"&gt;__adapt__&lt;/font&gt; special methods, and as adaptable objects by defining &lt;font face="'Courier New',Courier,monospace"&gt;__conform__&lt;/font&gt; special  methods. That way, interfaces and types can be written in any order, and still play well together. For instance, the existing 'adaptation methods' understood by the builtin objects' constructors (i.e. &lt;font face="'Courier New',Courier,monospace"&gt;__int__&lt;/font&gt;, &lt;font face="'Courier New',Courier,monospace"&gt;__str__&lt;/font&gt; and friends) could be incorporated into the system by having the &lt;font face="'Courier New',Courier,monospace"&gt;__adapt__&lt;/font&gt; methods of the relevant interfaces invoke the appropriate constructor - if the constructor throws an exception, then the adaptor method converts it to the appropriate adaptation exception.&lt;br /&gt;&lt;br /&gt;As mentioned in PEP 246, it would also be possible to have an 'adaptation registry' which mapped from (type, interface) tuples to adaptation methods. While this doesn't really matter to the basic idea of adaptation, it's handy for people trying to integrate code which provides the right interface, but doesn't actually provide the relevant adaptation information (e.g. if it provides a &lt;font face="'Courier New',Courier,monospace"&gt;read()&lt;/font&gt; method, and the function uses an interface which expects that method).&lt;br /&gt;&lt;br /&gt;For containers, it would make sense to have the interfaces be parameterisable (e.g. &lt;font face="'Courier New',Courier,monospace"&gt;List(Integer)&lt;/font&gt;, &lt;font face="'Courier New',Courier,monospace"&gt;List(Number)&lt;/font&gt;, &lt;font face="'Courier New',Courier,monospace"&gt;List(int, long)&lt;/font&gt; or &lt;font face="'Courier New',Courier,monospace"&gt;List()&lt;/font&gt; - that last example meaning, "allow a List with any types", since a list which allowed no types wouldn't be very useful). This suggests the concept of interface &lt;i&gt;factories&lt;/i&gt; - classes whose instances are themselves interfaces.&lt;br /&gt;&lt;br /&gt;For example (assume &lt;font face="'Courier New',Courier,monospace"&gt;AdaptationError&lt;/font&gt; is a subclass of &lt;font face="'Courier New',Courier,monospace"&gt;TypeError&lt;/font&gt; that is thrown when an adaptation fails):&lt;br /&gt;&lt;font face="'Courier New',Courier,monospace"&gt;&lt;br /&gt;class AdaptedOk(Exception): pass&lt;br /&gt;&lt;br /&gt;class List(object):&lt;br /&gt;&amp;nbsp;&amp;nbsp;def __init__(self, *args):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._allowed_interfaces = args&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;def __adapt__(self, obj):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lst = list(obj)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except Exception, ex:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise AdaptationError(str(ex))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;interfaces = self._allowed_interfaces&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if interfaces:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for i, x in enumerate(lst):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for interface in interfaces:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lst[i] = adapt(x, interface, None)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise AdaptedOk&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except AdaptationError:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise AdaptationError("List element %s does not "&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"support any allowed interface" % str(x))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except AdaptedOk:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pass&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return lst&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;def __eq__(self, other):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return (isinstance(other, type(self)) and&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(self._allowed_interfaces == other._allowed_interfaces))&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;OK, so PEP 246 combined with syntactic support would give a cleaner mechanism for &lt;i&gt;dynamic&lt;/i&gt; type checking. However, it would still be nice to have some sort of static checking for optimisation purposes (if the compiler &lt;i&gt;knows&lt;/i&gt; the types at compilation time, it can do all the operator lookups and so forth then, instead of waiting to do the lookups at runtime).&lt;br /&gt;&lt;br /&gt;Well, how about a slightly different pair of special methods: &lt;font face="'Courier New',Courier,monospace"&gt;__adapt_strict__&lt;/font&gt; and &lt;font face="'Courier New',Courier,monospace"&gt;__conform_strict__&lt;/font&gt;. The result of strict adaptation &lt;i&gt;guarantees&lt;/i&gt; that the result of adaptation is an actual instance of the interface. If an interface defines &lt;font face="'Courier New',Courier,monospace"&gt;__adapt_strict__&lt;/font&gt; without defining &lt;font face="'Courier New',Courier,monospace"&gt;__adapt__&lt;/font&gt;, then Python can be certain that the results of adaptation to that interface will be an instance of that interface.&lt;br /&gt;&lt;br /&gt;For example, the builtin types might provide &lt;font face="'Courier New',Courier,monospace"&gt;__adapt_strict__&lt;/font&gt; methods, allowing them to be used as interfaces which guaranteed that the result was an instance of the builtin type:&lt;br /&gt;&lt;font face="'Courier New',Courier,monospace"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;isinstance(adapt(x, int), int) # Always true&lt;br /&gt;&amp;nbsp;&amp;nbsp;isinstance(adapt(x, Integer), Integer) # Likely false&lt;br /&gt;&amp;nbsp;&amp;nbsp;isinstance(adapt(x, Integer), int) # Only possibly true&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;This can give us static typing, as long as the compiler can check for the existence of &lt;font face="'Courier New',Courier,monospace"&gt;__adapt__&lt;/font&gt; and &lt;font face="'Courier New',Courier,monospace"&gt;__adapt_strict__&lt;/font&gt; on the supplied interface (e.g. by assuming the names of builtins actually refer to the builtins). Here's some hypothetical implementations of  &lt;font face="'Courier New',Courier,monospace"&gt;__adapt_strict__&lt;/font&gt; for the builtins &lt;font face="'Courier New',Courier,monospace"&gt;object&lt;/font&gt; and &lt;font face="'Courier New',Courier,monospace"&gt;list&lt;/font&gt;:&lt;br /&gt;&lt;font face="'Courier New',Courier,monospace"&gt;&lt;br /&gt;def object:&lt;br /&gt;&amp;nbsp;&amp;nbsp;# The rest of object's definition is as normal&lt;br /&gt;&amp;nbsp;&amp;nbsp;# Naturally this would really be implemented in C. . .&lt;br /&gt;&amp;nbsp;&amp;nbsp;# Use a class method so any new-style class&lt;br /&gt;&amp;nbsp;&amp;nbsp;# can automatically be used for strict adaptation&lt;br /&gt;&amp;nbsp;&amp;nbsp;@classmethod &lt;br /&gt;&amp;nbsp;&amp;nbsp;def __adapt_strict__(cls, obj):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if isinstance(obj, cls):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return obj&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result = cls(obj)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except Exception, ex:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise AdaptationError(str(ex))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return result&lt;br /&gt;&lt;br /&gt;class AdaptedOk(Exception): pass&lt;br /&gt;def list(object):&lt;br /&gt;&amp;nbsp;&amp;nbsp;# The rest of list's definition is as normal&lt;br /&gt;&amp;nbsp;&amp;nbsp;# Naturally this would really be implemented in C. . .&lt;br /&gt;&amp;nbsp;&amp;nbsp;# Uses an instance method, so we use self&lt;br /&gt;&amp;nbsp;&amp;nbsp;# to store the list of allowed interfaces&lt;br /&gt;&amp;nbsp;&amp;nbsp;def __adapt_strict__(self, obj):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lst = list(obj)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except Exception, ex:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise AdaptationError(str(ex))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if self:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for i, x in enumerate(lst):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for interface in self:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lst[i] = adapt(x, interface, None)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise AdaptedOk&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except AdaptationError:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise AdaptationError("List element %s does not "&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"support any allowed interface" % str(x))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except AdaptedOk:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pass&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return lst&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;With strict adaptation available, our earlier example of non-strict list adaptation would change to be:&lt;br /&gt;&lt;font face="'Courier New',Courier,monospace"&gt;&lt;br /&gt;def List(list):&lt;br /&gt;&amp;nbsp;&amp;nbsp;def __adapt__(self, obj):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return self.__adapt_strict__(obj)&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;The rules for adaptation would change slightly from those suggested in the PEP:&lt;ol&gt;&lt;li&gt;If the object is an exact instance of the interface, return it&lt;br /&gt;&lt;li&gt;Try the object's &lt;font face="'Courier New',Courier,monospace"&gt;__conform_strict__&lt;/font&gt; method, if it has one. If that works, return the result.&lt;br /&gt;&lt;li&gt;If the interface allows non-strict adaptation (it defines __adapt__), then try the object's &lt;font face="'Courier New',Courier,monospace"&gt;__conform__&lt;/font&gt; method, if it has one. If that works, return the result.&lt;br /&gt;&lt;li&gt;Try the interface's &lt;font face="'Courier New',Courier,monospace"&gt;__adapt_strict__&lt;/font&gt; method, if it has one. If that works, return the result.&lt;br /&gt;&lt;li&gt;Try the interface's &lt;font face="'Courier New',Courier,monospace"&gt;__adapt__&lt;/font&gt; method, if it has one. If that works, return the result.&lt;/ol&gt;&lt;br /&gt;The new additions are steps 2 &amp; 4, and step 3 has been modified so that it is only tried if the interface implements &lt;font face="'Courier New',Courier,monospace"&gt;__adapt__&lt;/font&gt;. The idea of restricting step 1 to exact instances is taken from the PEP - it allows subclasses to say "I don't implement my parent's interface" by throwing an exception in its conformation method. The check for instances of subclasses has been moved to the implementation of &lt;font face="'Courier New',Courier,monospace"&gt;object.__adapt_strict__&lt;/font&gt;. This allows interfaces to decide how they choose to deal with subclasses.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-110387989393663651?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/110387989393663651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2004/12/type-checking-in-python.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110387989393663651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110387989393663651'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2004/12/type-checking-in-python.html' title='Type-checking in Python'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-110371407812921043</id><published>2004-12-22T21:14:00.000+10:00</published><updated>2010-12-12T22:47:36.604+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='intarwebs'/><title type='text'>Google Footprint</title><content type='html'>OK, so here's the thing. In the real world, most Australians talking about 'Nick Coghlan' are going to be talking about the guy on Secret Life of Us. If not him, then the surfer from somewhere down south. If we went to Canada, well, there's a diplomat by that name, so at least a few people would know who he is, or would have seen an article or two about him.&lt;br /&gt;&lt;br /&gt;Enter the world of Google, though, and an awful lot of it is about me. On the first two pages of a search for "Nick Coghlan", there's just one entry halfway down the second page for the Canadian guy. The other two don't show up until the third page. The results are skewed massively in my favour because of the public mailing list web archives that Google indexes - and every one of my messages to those lists includes my name.&lt;br /&gt;&lt;br /&gt;You can really see the effect of this by searching for "Nicholas Coghlan" instead. I disappear from the results, and the TV actor and the Canadian diplomat take control of the show. I don't show up until page 4, on an old announcement from UQ. As you might guess from that, I don't use my full first name very often.&lt;br /&gt;&lt;br /&gt;Another interesting search is "nick coghlan -python -cygwin -software". The results are then quite similar to the "nicholas coghlan" results.&lt;br /&gt;&lt;br /&gt;Anyway, I guess my only real observation is that, when searching just for names, Google gives extremely high weight to participation in public online communities. Obvious, one might say, but it's an interesting limitation when looking for information on more famous people that happen to share a name with someone like me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-110371407812921043?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/110371407812921043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2004/12/google-footprint.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110371407812921043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110371407812921043'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2004/12/google-footprint.html' title='Google Footprint'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-110232665382312547</id><published>2004-12-06T19:50:00.000+10:00</published><updated>2004-12-06T19:50:53.823+10:00</updated><title type='text'>Brain Dead Software #1: Yast Online Update</title><content type='html'>Suppose a new employee came to work for you. They're asked to collect 20 items from the company warehouse. You come back at the end of the day to find they have retrieved only one of the items. When queried, they say, "Well, the warheouse didn't have the second item on the list, so I came back to see what you wanted to do about it." "OK, fine, where are the other 18 items, then?" "Oh, I didn't try to get those. I needed to ask you about the second item, so I came back here." You'd be justifiably pissed off, and they'd probably be well on their way to getting fired.&lt;br /&gt;&lt;br /&gt;Yast Online Update is that employee. If it encounters a problem with any of the packages you ask it to install, it sits there with a freaking dialog box on the screen doing absolutely &lt;b&gt;nothing&lt;/b&gt; until you come back and tell it, "Look, just get on with the rest of the downloads already".&lt;br /&gt;&lt;br /&gt;To be fair, this problem isn't specific to YOU - YOU just happens to be the most recent example I've encountered. When a computer program is given a list of tasks to do, and encounters a problem with one of them, it should look at the list and continue on with as many of the remaining tasks as it can. At the end, it can present a report detailing any problems encountered, and asking what is to be done about each of them. With Brain Dead Software like YOU, I can't just leave it to run overnight - chances are it will only do useful work for a short while before some glitch causes it to twiddle its thumbs for the rest of the night, waiting for me to wake up and reassure it that everything is fine.&lt;br /&gt;&lt;br /&gt;Anyway, that's Brain Dead Software - programs that do things that would get a human fired. I'm sure there'll be more entries in this category.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-110232665382312547?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/110232665382312547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2004/12/brain-dead-software-1-yast-online.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110232665382312547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110232665382312547'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2004/12/brain-dead-software-1-yast-online.html' title='Brain Dead Software #1: Yast Online Update'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-110148046676963753</id><published>2004-11-27T00:47:00.000+10:00</published><updated>2010-12-12T22:46:27.592+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='travel'/><title type='text'>Mt St Helens</title><content type='html'>When I was in the US, one of the most impressive things I saw was the area around Mt St Helens. It was one of those things that made me glad my digital camera makes it so easy to take panoramic shots (click the panoramics to see slightly larger versions. If you want actual prints of any photos I post, let me know, since the originals have much better resolution than the versions I post).&lt;br /&gt;&lt;br /&gt;The river valley downstream from the mountain:&lt;br /&gt;&lt;a href="http://boredomandlaziness.skystorm.net/images/123-376_381_ST.jpg" target="_top"&gt;&lt;img src="http://members.iinet.net.au/~ncoghlan/boredomandlaziness/images/123-376_381_ST.jpg" width="357" height="63" alt="" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The view from the interpretative centre:&lt;br /&gt;&lt;a href="http://boredomandlaziness.skystorm.net/images/123-384_389_ST.jpg" target="_top"&gt;&lt;img src="http://members.iinet.net.au/~ncoghlan/boredomandlaziness/images/123-384_389_ST.jpg" width="361" height="61" alt="" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Heading around the back of the ridge:&lt;br /&gt;&lt;a href="http://boredomandlaziness.skystorm.net/images/123-392_398_ST.jpg" target="_top"&gt;&lt;img src="http://members.iinet.net.au/~ncoghlan/boredomandlaziness/images/123-392_398_ST.jpg" width="387" height="49" alt="" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Looking back towards the next ridge:&lt;br /&gt;&lt;a href="http://boredomandlaziness.skystorm.net/images/124-401_408_ST.jpg" target="_top"&gt;&lt;img src="http://members.iinet.net.au/~ncoghlan/boredomandlaziness/images/124-401_408_ST.jpg" width="429" height="61" alt="" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And here we have Leung making an appearance (Leung is the mascot I took with me on my trip. He's a little big to make a great photo mascot, so there are long stretches of photos where he doesn't appear). Anyway, the real point of this photo is the effect of the lateral blast from the eruption. Most of the grey stuff on the ridgeline is actually dead trees that were knocked over by the blast. You can see a bunch of trunks still standing where they were sheltered by the ridgeline.&lt;br /&gt;&lt;a href="http://boredomandlaziness.skystorm.net/images/124-414_IMG.jpg" target="_top"&gt;&lt;img src="http://members.iinet.net.au/~ncoghlan/boredomandlaziness/images/124-414_IMG.jpg" width="400" height="300" alt="" border="0"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-110148046676963753?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/110148046676963753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2004/11/mt-st-helens.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110148046676963753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110148046676963753'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2004/11/mt-st-helens.html' title='Mt St Helens'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-110147955310745741</id><published>2004-11-27T00:32:00.000+10:00</published><updated>2010-12-12T22:50:52.561+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python Quirk</title><content type='html'>Python's a very nice language to program in, but it does have a few quirks. Normally, if you put multiple strings in your code, Python will automatically combine them into a single string.&lt;br /&gt;&lt;br /&gt;However, it *doesn't* do this if your string literals are positioned in the "docstring" location for a class or function. If they are then only the first string will be used as the docstring - the remainder will be ignored.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update:&lt;/b&gt; A quick discussion on python-dev showed that the behaviour was fairly easily explained. The string literal concatenation magic only works inside a single expression (e.g. an assignment statement). Two string literals on separate lines look like two distinct statements to the interpreter. Escaping the newline after the first literal causes the string concatenation behaviour to be applied.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-110147955310745741?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/110147955310745741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2004/11/python-quirk.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110147955310745741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110147955310745741'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2004/11/python-quirk.html' title='Python Quirk'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9320223.post-110138452072615065</id><published>2004-11-25T22:03:00.000+10:00</published><updated>2010-12-12T22:48:16.057+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='metablogging'/><title type='text'>Firing it up</title><content type='html'>So, I occasionally post stuff over at &lt;a href="http://www.talkinboutstuff.net" target="_top"&gt;Talkinboutstuff&lt;/a&gt;. However, that's mostly for random crap I expect the rest of the guys to find interesting/annoying/whatever.&lt;br /&gt;&lt;br /&gt;So, I created this extra blog for myself - somewhere to pontificate about things I &lt;i&gt;don't&lt;/i&gt; expect them to find interesting, like software and Python and open source and what have you. And, anything of interest to them can be cross-linked quite happily :)&lt;br /&gt;&lt;br /&gt;Maybe I'll even get around to attaching this thing to a real domain name!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9320223-110138452072615065?l=www.boredomandlaziness.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.boredomandlaziness.org/feeds/110138452072615065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.boredomandlaziness.org/2004/11/firing-it-up.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110138452072615065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9320223/posts/default/110138452072615065'/><link rel='alternate' type='text/html' href='http://www.boredomandlaziness.org/2004/11/firing-it-up.html' title='Firing it up'/><author><name>Nick Coghlan</name><uri>https://profiles.google.com/105644937960330777422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh5.googleusercontent.com/-rt2hgESCIwY/AAAAAAAAAAI/AAAAAAAAt7s/cyiXrav5tqg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
