<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CkUFRXg9fSp7ImA9WhdUFkg.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935</id><updated>2011-10-03T06:56:54.665-07:00</updated><category term="ruby" /><category term="generators" /><category term="_getframe" /><category term="podcast" /><category term="design patterns" /><category term="&quot;with statement&quot;" /><category term="books" /><category term="highlight" /><category term="tutorial" /><category term="mock" /><category term="PEPs" /><category term="api" /><category term="django" /><category term="Google" /><category term="iteration" /><category term="pycon" /><category term="coroutines" /><category term="presentation" /><category term="baypiggies" /><category term="properties" /><category term="&quot;Google Developer Podcast&quot;" /><category term="&quot;Google App Engine&quot;" /><category term="&quot;unit tests&quot;" /><category term="pdb" /><category term="&quot;string interpolation&quot;" /><category term="&quot;newbie nugget&quot;" /><category term="metapost" /><category term="TDD" /><category term="pronunciation" /><category term="&quot;test-driven development&quot;" /><category term="&quot;Secrets of the Framework Creators&quot;" /><category term="book review" /><category term="&quot;dependency injection&quot;" /><category term="metaclasses" /><category term="&quot;Python 3.0&quot;" /><category term="Pygments" /><category term="&quot;book review&quot;" /><category term="testing" /><category term="why" /><category term="pbcopy" /><category term="TODO" /><category term="patch" /><title>PyPap</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://pypap.blogspot.com/" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/PyPap" /><feedburner:info uri="pypap" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>PyPap</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry gd:etag="W/&quot;DkICQns4eyp7ImA9WxBTEk0.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-8453485458361823242</id><published>2009-12-07T08:10:00.001-08:00</published><updated>2009-12-07T08:49:23.533-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-07T08:49:23.533-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="book review" /><category scheme="http://www.blogger.com/atom/ns#" term="design patterns" /><title>A Ruby book worth reading for Pythonistas</title><content type="html">It's been a while since I've ready an entire technical book over the weekend. But I enjoyed &lt;a href="http://www.amazon.com/gp/product/0321490452?ie=UTF8&amp;amp;tag=pythpracandpa-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0321490452"&gt;Design Patterns in Ruby&lt;/a&gt; so much that I kept picking it up for "one more chapter".&lt;br /&gt;&lt;div&gt;&lt;br /&gt;I played with Ruby a little several years ago, but I've never used it seriously. I need to use it at work though. Specifically, I wanted to learn about creating Domain-Specific Languages (DSLs) in Ruby, which is what led me to this book (since it has a chapter on DSLs).&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;When the book arrived late Thursday I skipped straight to the DSL chapter, which was interesting. But then I started reading it from the beginning. Chapter 1 talks about design patterns, the book &lt;a href="http://www.amazon.com/gp/product/0201633612?ie=UTF8&amp;amp;tag=pythpracandpa-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0201633612"&gt;Design Patterns&lt;/a&gt;, and the general principles that begin the Gang of Four book:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style="clear: both"&gt;&lt;li&gt;Separate out the things that change from those that stay the same.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Program to an interface, not an implementation.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Prefer composition over inheritance.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Delegate, delegate, delegate.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Russ Olsen adds "You ain't gonna need it."&lt;br /&gt;&lt;br /&gt;Chapter 2 is a concise introduction to Ruby: just 37 pages. It's not thorough, but it's enough to be able to read the Ruby code in the subsequent chapters.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Chapters 3 through 15 explain many of the patterns covered in the Gang of Four book. I enjoyed brushing up on my patterns, but what kept me wanting to read "one more chapter" over the weekend was how after explaining the pattern, Olsen explains how it does or does not apply in Ruby. And he takes the opportunity to introduce Ruby features (like procs &amp;amp; blocks, modules and mixins, modifying classes and objects on the fly, message passing, etc.) as he does this.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;He also write about how each pattern can be abused, and describes real-world uses of the patterns in the Ruby libraries.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Chapters 16 through 18 describe three "patterns that have emerged with the introduction and expanded use of Ruby": DSLs, meta-programming and convention over configuration. And there are two appendices: A on installing Ruby on different platforms, and B contains a carefully annotated bibliography.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;I suspect I'll find myself referring back to this book often, even when I'm writing Python code. I suspect reading it will help make me a better Python programmer (and a better programmer in general). So I recommend it.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;If I had loads of time, it would be a worthwhile exercise to go through each pattern in the book and convert the examples to Python, and look for examples of the pattern in the Python libraries. I wonder if anyone else with more time has already had this idea.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-8453485458361823242?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/KE00lIEka08" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/8453485458361823242/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=8453485458361823242" title="43 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/8453485458361823242?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/8453485458361823242?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/KE00lIEka08/ruby-book-worth-reading-for-pythonistas.html" title="A Ruby book worth reading for Pythonistas" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>43</thr:total><feedburner:origLink>http://pypap.blogspot.com/2009/12/ruby-book-worth-reading-for-pythonistas.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MGQn07cSp7ImA9WxJXEU4.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-2999622525081292611</id><published>2009-06-04T08:54:00.001-07:00</published><updated>2009-06-04T09:03:43.309-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-04T09:03:43.309-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="TODO" /><category scheme="http://www.blogger.com/atom/ns#" term="pycon" /><title>PyCon 2009 Notes - March 28th</title><content type="html">&lt;p style="clear: both;"&gt;Day Two of the "core" of PyCon 2009...&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;h3 id="morning_lightning_talks"&gt;Morning Lightning Talks&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;You’ll find the video at&lt;a href="http://us.pycon.org/2009/conference/schedule/event/41/" style=""&gt; &lt;/a&gt;&lt;a href="http://us.pycon.org/2009/conference/schedule/event/41/"&gt;http://us.pycon.org/2009/conference/schedule/event/41/&lt;/a&gt;.&lt;/p&gt;&lt;p style="clear: both;"&gt;Jesse Noller’s “Python License V3” is pretty funny (&lt;a href="http://blip.tv/file/1931026"&gt;http://blip.tv/file/1931026 &lt;/a&gt;contains only that talk).&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;a href="http://blip.tv/file/1999383"&gt;http://blip.tv/file/1999383 &lt;/a&gt;contains all the Saturday morning lightning talks.&lt;/p&gt;&lt;p style="clear: both;"&gt;Katie Cunningham talks on Python at NASA at 19:15.&lt;/p&gt;&lt;p style="clear: both;"&gt;PlayerPiano (&lt;a href="http://playerpiano.googlecode.com/"&gt;http://playerpiano.googlecode.com&lt;/a&gt;) pretend typing of doctests for demos at 35:15.&lt;/p&gt;&lt;p style="clear: both;"&gt;James Bennett had a good presentation on DVCSs at 40:10:&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;&lt;a href="http://www.b-list.org/weblog/2008/jul/28/lets-talk-about-dvcs/"&gt;Let’s talk about DVCS&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Two advantages of DVCSs:&lt;br /&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;better merging&lt;br /&gt;&lt;/li&gt;&lt;li&gt;local/offline commits&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;why can’t Subversion be improved with these?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;since then:&lt;br /&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;Good news:&lt;br /&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;Mercurial is easy to use&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Bitbucket is better than Google Code hosting&lt;br /&gt;&lt;/li&gt;&lt;li&gt;easier repository creation (at least with Mercurial)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Bad news:&lt;br /&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;still doesn’t know if DVCSs are better&lt;br /&gt;&lt;/li&gt;&lt;li&gt;know some ways that it’s worse&lt;br /&gt;&lt;/li&gt;&lt;li&gt;“Where is the code?”&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Also recommend’s &lt;a href="http://www.pointy-stick.com/blog/2009/03/16/dark-side-distributed-version-control/"&gt;Malcolm Tredinnick’s “The Dark Side Of Distributed Version Control”&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;PyMite - a subset of Python for microcontrollers (at 45:15)&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;&lt;a href="http://pymite.python-hosting.com/"&gt;http://pymite.python-hosting.com&lt;/a&gt;&lt;br /&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;I see there it says “The PyMite VM is growing into the Python-on-a-chip project and its repository has moved to Google Code.” - &lt;a href="http://code.google.com/p/python-on-a-chip/"&gt;http://code.google.com/p/python-on-a-chip/&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;will run in as little as 64 KB flash and 4 KB RAM&lt;br /&gt;&lt;/li&gt;&lt;li&gt;easy porting: one file with six functions&lt;br /&gt;&lt;/li&gt;&lt;li&gt;interactive interface&lt;br /&gt;&lt;/li&gt;&lt;li&gt;easy to write native functions: embed C code in docstrings&lt;br /&gt;&lt;/li&gt;&lt;li&gt;to try it out:&lt;br /&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;svn co http://svn.pymite.python-hosting.com/trunk&lt;br /&gt;&lt;/li&gt;&lt;li&gt;cd trunk; make ipm&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;TODO - would be interesting to port it to &lt;a href="http://www.altera.com/nios2"&gt;Nios II&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;web2py (at 49:50)&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;admin interface not just for database, but for design &amp;amp; debug&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;h3 id="keynote_guido_van_rossum"&gt;Keynote: Guido van Rossum&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;You’ll find the video at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/42/"&gt;http://us.pycon.org/2009/conference/schedule/event/42/&lt;/a&gt;.&lt;/p&gt;&lt;p style="clear: both;"&gt;The R-word&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;“I’m not retiring, but I’m tiring.”&lt;br /&gt;&lt;/li&gt;&lt;li&gt;doesn’t enjoy traveling like he used to&lt;br /&gt;&lt;/li&gt;&lt;li&gt;“I’m sort of thinking over the next five or ten years to gradually fade away.”&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Hopes in 5 years that the BDFL is not actually leading the community anymore, more of a figurehead.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;“Don’t look to me for guidance for everything.”&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;Mentioned a new PEP that he supports on “yield from” which is useful for building “coroutine libraries” [I think]&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;A Google search revealed &lt;a href="http://www.python.org/dev/peps/pep-0380/"&gt;PEP 380&lt;/a&gt;. I didn’t read it in detail, but at a quick glance it looks like it would eliminate the need for the &lt;a href="http://www.blogger.com/dspitzer/notes/PyCon2009/coroutines"&gt;“trampolining” David Beazley created to work around this in Part 8 of his A Curious Course on Coroutines and Concurrency tutorial&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;MAY be a dependency &amp;amp; packaging API in 2.7 &amp;amp; 3.1—he mentioned this problem several times, it’s certainly on his mind as a big unsolved problem&lt;/p&gt;&lt;p style="clear: both;"&gt;“Remember, once you put an API in the core, it may not be dead but it evolves at a glacial pace.” “Third-party packages can evolve much faster.”&lt;/p&gt;&lt;p style="clear: both;"&gt;“The standard library may be just the right size.”&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;Can’t shrink it without killing apps.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Don’t want to add things until they’re stable. “Biologists call things that are stable ‘dead’.”&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;Answering a question about code blocks: “Let’s stop tinkering with the languages and [focus on] solv[ing] the problems around the language.”&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;FOR FUTURE INVESTIGATION: Guido said you could put a decorator around a nested function that “says execute here” (@apply?) - would this be the equivalent of Ruby code blocks? What are the advantages of Ruby code blocks? How are they used? Would this apply to nested, apply-decorated functions like this?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;h3 id="jacob_kaplan_moss_the_state_of_django"&gt;Jacob Kaplan-Moss - The State of Django&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;You’ll find the slides (in PDF format) and video at&lt;a href="http://us.pycon.org/2009/conference/schedule/event/45/" style=""&gt; &lt;/a&gt;&lt;a href="http://us.pycon.org/2009/conference/schedule/event/45/"&gt;http://us.pycon.org/2009/conference/schedule/event/45/&lt;/a&gt;. I didn’t take any notes. (And the slides aren’t meant to be read by themselves.)&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;h3 id="joe_gregorio_the_lack_of_design_patterns_in_python"&gt;Joe Gregorio - The (lack of) design patterns in Python&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;You’ll find the slides (in PDF format) at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/51/"&gt;http://us.pycon.org/2009/conference/schedule/event/51/&lt;/a&gt;, but there’s no video yet. (I’ll update this when it appears.)&lt;/p&gt;&lt;p style="clear: both;"&gt;BTW, Joe Gregorio’s PyCon 2009 blog post is at &lt;a href="http://bitworking.org/news/420/pycon-2009-notes"&gt;http://bitworking.org/news/420/pycon-2009-notes&lt;/a&gt;. You’ll find links to his “An Introduction to Google App Engine” tutorial materials there (as well as mention of this talk).&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;em&gt;This was one of my favorite talks from PyCon 2009.&lt;/em&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;Mythology - languages are all turing complete&lt;/p&gt;&lt;p style="clear: both;"&gt;Python isn’t Java without the compile&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;see &lt;a href="http://bitworking.org/news/Python_isnt_Java_without_the_compile"&gt;his blog post&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Beyond-Java-Bruce-Tate/dp/0596100949"&gt;Bruce Tate’s Beyond Java book&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;“Yes, design patterns are good, but they’re also a sign of weakness in a language.”&lt;/p&gt;&lt;p style="clear: both;"&gt;The patterns are built in [to Python].&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;“No one talks about the ‘structured programming’ pattern, or the ‘object-oriented’ pattern, or the ‘function’ pattern anymore.”&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;“When most of your code does nothing in a pompous way that is a sure sign that you are heading in the wrong direction. Here’s a translation into Python.”&lt;br /&gt;- Peter Otten&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Strategy_pattern"&gt;Wikipedia Strategy Pattern page&lt;/a&gt; - “invisible in languages with first-class functions”.&lt;/p&gt;&lt;p style="clear: both;"&gt;no need for iterator pattern in Python&lt;/p&gt;&lt;p style="clear: both;"&gt;also talked about Abstract Factory pattern, and others&lt;/p&gt;&lt;p style="clear: both;"&gt;TODO - I need to think about his using a decorator for the observer pattern. (Slides 27 through 29.)&lt;/p&gt;&lt;p style="clear: both;"&gt;Conclusions:&lt;/p&gt;&lt;ol style="clear: both;"&gt;&lt;li&gt;look to features before patterns&lt;/li&gt;&lt;li&gt;reduce patterns -&gt; shorter code&lt;/li&gt;&lt;li&gt;needed patterns -&gt; language feature&lt;/li&gt;&lt;/ol&gt;&lt;p style="clear: both;"&gt;Concurrency Patterns listed on Wikipedia:&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;Thread pool, etc.&lt;/li&gt;&lt;li&gt;“do these point to language features we should be talking about adding?”&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;See the Google Video: “Advanced Topics in Programming Languages: Concurrency and Message Passing in Newsqueak” by Rob Pike&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;h3 id="jack_diederich_class_decorators_radically_simple"&gt;Jack Diederich - Class Decorators: Radically Simple&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;You find the slides (in PDF &amp;amp; PPT formats) and video at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/55/"&gt;http://us.pycon.org/2009/conference/schedule/event/55/&lt;/a&gt;.&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;em&gt;This was also one of my favorite talks from PyCon. I recommend you watch the video.&lt;/em&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;Practical definitions of a decorator:&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;takes one argument&lt;/li&gt;&lt;li&gt;returns something useful&lt;/li&gt;&lt;/ul&gt;Example:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;cron&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(170, 34, 255);"&gt;@cron&lt;/span&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;schedule(cron&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;NIGHTLY)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;class&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;SalesReport&lt;/span&gt;(Report):&lt;br /&gt;  &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;run&lt;/span&gt;(&lt;span style="color: rgb(0, 128, 0);"&gt;self&lt;/span&gt;):&lt;br /&gt;  &lt;span style="color: rgb(64, 128, 128); font-style: italic;"&gt;# do stuff&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;“Can do everything in class decorators that you can do in metaclasses” [I may have paraphrased.]&lt;ul style="clear: both;"&gt;&lt;li&gt;class decorators are explicit&lt;/li&gt;&lt;li&gt;class decorators are easily stackable (unlike metaclasses—while possible, it’s difficult to remember how)&lt;/li&gt;&lt;li&gt;nice alternative to mixins&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;Popular patterns:&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;register - like cron scheduler above&lt;/li&gt;&lt;li&gt;augment - like mixins&lt;/li&gt;&lt;li&gt;fixup&lt;/li&gt;&lt;li&gt;verify&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;&lt;em&gt;very simple (and slick) registration class decorator - see slide 25&lt;/em&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;Best Practices&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;return the original class&lt;/li&gt;&lt;li&gt;don't assume you are the only decorator&lt;/li&gt;&lt;li&gt;maybe you want a metaclass [he still uses them sometimes]&lt;/li&gt;&lt;li&gt;don't add slots&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;&lt;h3&gt;Ed Leafe - Dabo: Rich Client Web Applications in 100% Python&lt;/h3&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;Slides (in ODP format) and video at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/58/"&gt;http://us.pycon.org/2009/conference/schedule/event/58/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;advantages of web application:&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;zero deployment&lt;/li&gt;&lt;li&gt;cross platform&lt;/li&gt;&lt;li&gt;centralized control (of databases)&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;disadvantages:&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;limited UI&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;Manifest Class&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;client and server diff each other, ala rsync&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;Dabo Springboard is a launch app (to allow you to run apps without have to install, so you get the same advantage as a browser-based app)&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;h3&gt;Bob Ippolito - Drop ACID and think about data&lt;br /&gt;&lt;/h3&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;Video at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/64/"&gt;http://us.pycon.org/2009/conference/schedule/event/64/&lt;/a&gt;. I found the slides at &lt;a href="http://bitbucket.org/etrepum/drop_acid_pycon_2009/"&gt;http://bitbucket.org/etrepum/drop_acid_pycon_2009/&lt;/a&gt; (linked to from his "PyCon 2009, Drop ACID and think about data") blog post.&lt;/p&gt;&lt;p style="clear: both;"&gt;This was a "ﬁrehose-style" presentation, so I recommend you ﬁrst have a look at the slides, then try the video if interested.&lt;/p&gt;&lt;p style="clear: both;"&gt;ACID&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;Atomicity - all or nothing&lt;/li&gt;&lt;li&gt;Consistency - no explosions&lt;/li&gt;&lt;li&gt;Isolation - no ﬁghts (when used concurrently)&lt;/li&gt;&lt;li&gt;Durability - no lying&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;networks make ACID difﬁcult in a distributed environment (which is necessary for reliability and scalability)&lt;/p&gt;&lt;p style="clear: both;"&gt;BASE&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;basically available&lt;/li&gt;&lt;li&gt;soft state&lt;/li&gt;&lt;li&gt;eventually consistent&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;Then reviews the pros &amp;amp; cons of:&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;BigTable&lt;/li&gt;&lt;li&gt;Dynamo&lt;/li&gt;&lt;li&gt;Cassandra&lt;/li&gt;&lt;li&gt;Tokyo Cabinet &amp;amp; Tokyo Tyrant&lt;/li&gt;&lt;li&gt;Redis&lt;/li&gt;&lt;li&gt;CouchDB&lt;/li&gt;&lt;li&gt;MongoDB&lt;/li&gt;&lt;li&gt;Column Databases&lt;/li&gt;&lt;li&gt;MonetDB&lt;/li&gt;&lt;li&gt;LucidDB&lt;/li&gt;&lt;li&gt;Vertica&lt;br /&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;this is the one his company (MochiMedia) decided to pay for; “it works”&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;“Bloom Filters are Neat”&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;probabilistic data structure&lt;/li&gt;&lt;li&gt;false positives at a known error&lt;/li&gt;&lt;li&gt;constant space&lt;/li&gt;&lt;li&gt;uses:&lt;br /&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;approximate counting of a large set (eg. unique IPs from logs)&lt;/li&gt;&lt;li&gt;knowing that data is definitely NOT stored somewhere (eg. remote chache)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;h3 id="ian_bicking_topics_of_interest"&gt;Ian Bicking - Topics of Interest&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;Video, slides, and IRC logs available at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/76/"&gt;http://us.pycon.org/2009/conference/schedule/event/76/&lt;/a&gt;.&lt;/p&gt;&lt;p style="clear: both;"&gt;I went to this talk because I had heard Ian Bicking is a great speaker and is “not to be missed”. I’m afraid I wish I had missed it. Ian kept a live IRC display on the screen as he spoke. While it was good for some laughs, it was a distraction to both the speaker and the audience.&lt;/p&gt;&lt;p style="clear: both;"&gt;TODO - he mentioned a lot of names of what I presume are projects he’s started (he assumed—incorrectly in my case—that we all knew what they are), I should learn about them:&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;Paste&lt;/li&gt;&lt;li&gt;Deliverance&lt;/li&gt;&lt;li&gt;WebOb&lt;/li&gt;&lt;li&gt;PoachEggs&lt;/li&gt;&lt;li&gt;pip&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;h3 id="alex_martelli_abstraction_as_leverage"&gt;Alex Martelli - Abstraction as Leverage&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;I chose the Ian Bicking talk over this one. The video and slides (PDF) are at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/75/"&gt;http://us.pycon.org/2009/conference/schedule/event/75/&lt;/a&gt;.&lt;/p&gt;&lt;p style="clear: both;"&gt;TODO: I intend to review them. I’ve never regretted attending an Alex Martelli lecture.&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;h3 id="lennart_regebro_python_26_and_30_compatibility"&gt;Lennart Regebro - Python 2.6 and 3.0 compatibility&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;I chose the Ian Bicking talk over this one also. But this looks interesting: “This talks takes a look at the various options of migrating to Python 3, and takes up examples of some tricks you can do to make you code run unmodified under both 2.6 and 3.0.” The video and slides (PDF) are at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/74/"&gt;http://us.pycon.org/2009/conference/schedule/event/74/&lt;/a&gt;.&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;h3 id="evening_lightning_talks"&gt;Evening Lightning Talks&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="clear: both;"&gt;You’ll find the video at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/78/"&gt;http://us.pycon.org/2009/conference/schedule/event/78/&lt;/a&gt;.&lt;/p&gt;&lt;p style="clear: both;"&gt;snakebite - &lt;a href="http://www.snakebite.org/"&gt;http://www.snakebite.org/&lt;/a&gt; (right at the start of the video)&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;“Snakebite is a network that strives to provide developers of open source projects complete and unrestricted access to as many different platforms, operating systems, architectures, compilers, devices, databases, tools and applications that they may need in order to optimally develop their software.”&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;reading and writing Excel files from Python (5:40)&lt;/p&gt;&lt;p style="clear: both;"&gt;melkjug.org (8:35)&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;for filtering RSS feeds&lt;/li&gt;&lt;li&gt;open source&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;funny numbers rant (15:55)&lt;/p&gt;&lt;p style="clear: both;"&gt;Martin v. Löwis talks about porting Django and pyscopg to Python 3.0 (32:30)&lt;/p&gt;&lt;p style="clear: both;"&gt;Leonard Reder from JPL spoke about “Mars Science Laboratory - Flight Software Automatic Code Generation Tools” (37:35)&lt;/p&gt;&lt;ul style="clear: both;"&gt;&lt;li&gt;MSL animations: &lt;a href="http://mars.jpl.nasa.gov/msl/gallery/videos.html#MSL_EDL"&gt;http://mars.jpl.nasa.gov/msl/gallery/videos.html#MSLEDL&lt;/a&gt;&lt;/li&gt;&lt;li&gt;MSL general info: &lt;a href="http://mars.jpl.nasa.gov/msl/"&gt;http://mars.jpl.nasa.gov/msl/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="clear: both;"&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-2999622525081292611?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/qZPEQcmE1p4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/2999622525081292611/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=2999622525081292611" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/2999622525081292611?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/2999622525081292611?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/qZPEQcmE1p4/pycon-2009-notes-march-28th.html" title="PyCon 2009 Notes - March 28th" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://pypap.blogspot.com/2009/06/pycon-2009-notes-march-28th.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIHQnk5eSp7ImA9WxJTGU4.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-2738994524773762784</id><published>2009-04-22T20:49:00.000-07:00</published><updated>2009-04-28T08:28:53.721-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-28T08:28:53.721-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="TODO" /><category scheme="http://www.blogger.com/atom/ns#" term="pycon" /><title>PyCon 2009 Notes - March 27th</title><content type="html">&lt;p&gt;Friday, March 27th through Sunday, March 29th were the “core” conference days.  These are the days with regular scheduled talks, keynote talks, lightning talks and open spaces.  You can see an overview of the schedule for these three days at &lt;a href="http://us.pycon.org/2009/conference/schedule/"&gt;http://us.pycon.org/2009/conference/schedule/&lt;/a&gt;.&lt;/p&gt;I’ll present my notes from PyCon in chronological order.&lt;br /&gt;&lt;br /&gt;Last year there were lightning talk sessions after the scheduled talks on all three days.  Perhaps the scheduling committee got plenty of “more lightning talks” feedback, because this year each day also started with lightning talks, so except for a brief introduction from &lt;a href="http://us.pycon.org/2009/about/staff/"&gt;the PyCon 2009 Chair David Googer&lt;/a&gt; on Friday morning, the conference kicked off with lightning talks.  I found this quite fitting and in keeping with PyCon being a &lt;a href="http://us.pycon.org/2009/helping/"&gt;community conference&lt;/a&gt;.&lt;br /&gt;&lt;h3 id="morning_lightning_talks"&gt;&lt;span style="font-size:130%;"&gt;Morning Lightning Talks&lt;/span&gt;&lt;/h3&gt;You’ll find the video at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/2/"&gt;http://us.pycon.org/2009/conference/schedule/event/2/&lt;/a&gt;.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://us.pycon.org/2009/profile/04c5/"&gt;Brett Cannon&lt;/a&gt; (~3:45 in the video) presented on python.org’s switching to a DVCS (from Subversion).  See &lt;a href="http://www.python.org/dev/peps/pep-0374/"&gt;http://www.python.org/dev/peps/pep-0374/&lt;/a&gt;, particularly &lt;a href="http://www.python.org/dev/peps/pep-0374/#chosen-dvcs"&gt;http://www.python.org/dev/peps/pep-0374/#chosen-dvcs&lt;/a&gt; which makes the decision to go with Mercurial official.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.blogger.com/profile/11003648392946638242"&gt;Jonathan Ellis&lt;/a&gt; (about 12:30 in the video) spoke about the &lt;a href="http://en.wikipedia.org/wiki/Cassandra_%28database"&gt;Cassandra distributed database&lt;/a&gt;), opened sourced by Facebook in the summer of 2008.  He made it sound like it’s the only (open source?) “distributed database” with a Python API.&lt;/li&gt;&lt;/ul&gt;&lt;h3 id="jeff_rush_about_python_namespaces_and_code_objects"&gt;&lt;span style="font-size:130%;"&gt;Jeff Rush - About Python Namespaces (and Code Objects)&lt;/span&gt;&lt;/h3&gt;See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/7/"&gt;http://us.pycon.org/2009/conference/schedule/event/7/&lt;/a&gt; for the video, slides and other files.&lt;br /&gt;&lt;br /&gt;I didn’t know compiling and disassembling Python code is as simple as:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;s &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'x = 5'&lt;/span&gt;&lt;br /&gt;co &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;compile&lt;/span&gt;(s, &lt;span style="color: rgb(186, 33, 33);"&gt;'&amp;lt;stdin&amp;gt;'&lt;/span&gt;, &lt;span style="color: rgb(186, 33, 33);"&gt;'exec'&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;from&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;dis&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; dis&lt;br /&gt;dis(co)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;His slides and/or the video are worth reviewing.&lt;br /&gt;&lt;br /&gt;His “thunk” example—which he defines as “like a proxy but it gets out of the way when you need it”—is interesting. See page 38 of the PDF or about 11:30 of the video.&lt;br /&gt;&lt;br /&gt;I also noted that he said “we spend a lot of time going over source code in Dallas [at the Dallas Python Interest Group]”.  That would be a worthwhile thing to try at &lt;a href="http://www.baypiggies.net/"&gt;BayPIGgies&lt;/a&gt;—I’ll propose it [TODO].&lt;br /&gt;&lt;h3 id="adam_d_christian_using_windmill"&gt;&lt;span style="font-size:130%;"&gt;Adam D Christian - Using Windmill&lt;/span&gt;&lt;/h3&gt;See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/9/"&gt;http://us.pycon.org/2009/conference/schedule/event/9/&lt;/a&gt; for the video and PowerPoint slides.&lt;br /&gt;&lt;br /&gt;“Windmill is the best-integrated solution for Web test development and its flexibility is largely due to its development in Python.”&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Open source&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Looks pretty slick&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.getwindmill.com/"&gt;http://www.getwindmill.com&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Selenium does SSL, Windmill doesn’t…yet.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Selenium has strong Java integration (and Windmill does not)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Question: “Why did you create Windmill?”&lt;br /&gt;Answer: “At the time it took us longer to debug a Selenium test than to write it over again.”&lt;/p&gt;&lt;h3 id="mike_fletcher_introduction_to_python_profiling"&gt;&lt;span style="font-size:130%;"&gt;Mike Fletcher - Introduction to Python Profiling&lt;/span&gt;&lt;/h3&gt;See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/15/"&gt;http://us.pycon.org/2009/conference/schedule/event/15/&lt;/a&gt; for the video and slides in OOo &amp;amp; PDF formats.&lt;br /&gt;&lt;br /&gt;Asked 12 programmers “If I had a million dollars to spend on Python…”.  The top three answers were about improving performance.&lt;br /&gt;&lt;br /&gt;Good introduction.  You may want to check out the slides first and then turn to the video for more detail.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Visualization Tools:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;KCacheGrind - “some assembly required for use with Python”[and non-trivial to get it working on Mac OS X]&lt;/li&gt;&lt;li&gt;RunSnakeRun: (&lt;a href="http://www.vrplumber.com/programming/runsnakerun/"&gt;http://www.vrplumber.com/programming/runsnakerun/&lt;/a&gt;) - “doesn’t provide all the bells-and-whistles of a program like KCacheGrind, it’s intended to allow for profiling your Python programs, and just your Python programs”&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id="kumar_mcmillan_strategies_for_testing_ajax_web_applications"&gt;&lt;span style="font-size:130%;"&gt;Kumar McMillan - Strategies For Testing Ajax Web Applications&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/18/"&gt;http://us.pycon.org/2009/conference/schedule/event/18/&lt;/a&gt; for the video and a ZIP containing the slides in HTML (or go to &lt;a href="http://farmdev.com/talks/test-ajax/"&gt;http://farmdev.com/talks/test-ajax/&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;5 strategies:&lt;br /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt; Test Data Handlers&lt;/li&gt;&lt;li&gt;Test JavaScript&lt;/li&gt;&lt;li&gt;Isolate UI for Testing&lt;/li&gt;&lt;li&gt;Automate UI Tests&lt;/li&gt;&lt;li&gt;Gridify Your Test Suite&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;/p&gt;Some resources on his wrap-up slide.&lt;br /&gt;&lt;h3 id="aaron_maxwell_building_an_automated_qa_infrastructure_using_open_source_python_tools"&gt;&lt;span style="font-size:130%;"&gt;Aaron Maxwell - Building an Automated QA Infrastructure using Open-Source Python Tools&lt;/span&gt;&lt;/h3&gt;See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/22/"&gt;http://us.pycon.org/2009/conference/schedule/event/22/&lt;/a&gt; for the video and the slides (in OOo &amp;amp; PPT formats).  Or see &lt;a href="http://redsymbol.net/talks/auto-qa-python/"&gt;http://redsymbol.net/talks/auto-qa-python/&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;“This demonstrates the value of an automated QA system. If you need to manually execute the code coverage tool, then in practice you just won’t do it as often as if it is run for you. If your QA system automatically runs code coverage each night (for example), you and your team are freed up from bothering to do it manually - or even remembering to do so. It’s just done silently, and a fresh coverage report is available when you are ready to see it.&lt;br /&gt;&lt;br /&gt;“This talk referenced the The Buildbot QA/CI Framework. There are many such frameworks with different plusses and minuses. BuildBot’s weakness is its brief but steep learning curve, which makes it harder than anyone would like to set up for simple projects. Its plusses are its generality, range, and extensibility: it can be made to do almost anything you need your QA system to do, even for tremendously large projects with complex test metrics. Overall, I recommend BuildBot be used for building your QA framework, unless you have some particular reason to use one of the others that are out there.”&lt;br /&gt;&lt;br /&gt;From slide 5: “Your QA System is ONLY as good as its reporting of results.  If you don’t get this done well… none of the rest matters.  Under appreciated…And critically, critically important.”&lt;br /&gt;&lt;br /&gt;From slide 9: “BuildBot is probably the best general purpose Python-based, open-source framework available now.”&lt;p&gt;Slide 11 gives quick definitions of some BuildBot architectural terms.&lt;/p&gt;&lt;p&gt;Slides 12-19 walk through examples of a simple and a more complex BuildBot configuration.&lt;/p&gt;Slides 20 &amp;amp; 21 show examples of extending BuildBot.&lt;br /&gt;&lt;h3 id="owen_taylor_reinteract_a_better_way_to_interact_with_python"&gt;&lt;span style="font-size:130%;"&gt;Owen Taylor - Reinteract: a better way to interact with Python&lt;/span&gt;&lt;/h3&gt;I didn’t attend this talk, but several people remarked on it later.  I’ve since played with Reinteract and I recommend you check it out: &lt;a href="http://www.reinteract.org/"&gt;http://www.reinteract.org/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/23/"&gt;http://us.pycon.org/2009/conference/schedule/event/23/&lt;/a&gt; for the video and the slides (in PDF format).  The slides are not at all useful by themselves.  But I definitely recommend you watch the video.  Reinteract could well be a tool you’ll want to use regularly.&lt;br /&gt;&lt;br /&gt;“Traditionally Python has worked one of two ways: either a program with an edit-run cycle or a command prompt where the user types commands. Reinteract introduces a new way of working where the user creates a worksheet that interleaves Python code with the results of that code. Previously entered code can be changed and corrected. The ability to insert graphs and plots in the worksheet makes Reinteract very suitable for data analysis, but it also is a good for basic experimentation with the Python language. This talk introduces Reinteract and gives a high-level peek at the magic behind the scenes.”&lt;br /&gt;&lt;h3 id="ned_batchelder_coverage_testing_the_good_and_the_bad"&gt;&lt;span style="font-size:130%;"&gt;Ned Batchelder - Coverage testing, the good and the bad.&lt;/span&gt;&lt;/h3&gt;See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/26/"&gt;http://us.pycon.org/2009/conference/schedule/event/26/&lt;/a&gt; for the video and the slides (in PDF format).&lt;br /&gt;&lt;br /&gt;“Coverage testing tests your tests”&lt;br /&gt;&lt;p&gt;The slides are easy to read without the video if you prefer, so I won’t duplicate them here.&lt;/p&gt;Writing more tests is the “only way to truly increase code coverage”.  Excluding code to boost coverage is tempting, but you’ll never come back, so you’re only hurting yourself.&lt;br /&gt;&lt;br /&gt;What is currently “100% broken”:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;branch coverage&lt;br /&gt;&lt;/li&gt;&lt;li&gt;path coverage&lt;br /&gt;&lt;/li&gt;&lt;li&gt;loop path coverage&lt;br /&gt;&lt;/li&gt;&lt;li&gt;data-driven code - can’t measure data used&lt;br /&gt;&lt;/li&gt;&lt;li&gt;complex conditionals&lt;br /&gt;&lt;/li&gt;&lt;li&gt;hidden branches&lt;br /&gt;&lt;/li&gt;&lt;li&gt;broken tests&lt;/li&gt;&lt;/ul&gt;&lt;h3 id="dr_c_titus_brown_building_tests_for_large_untested_codebases"&gt;&lt;span style="font-size:130%;"&gt;Dr. C. Titus Brown - Building tests for large, untested codebases&lt;/span&gt;&lt;/h3&gt;See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/30/"&gt;http://us.pycon.org/2009/conference/schedule/event/30/&lt;/a&gt; for the video and the slides (in PDF format).&lt;br /&gt;&lt;br /&gt;Presented on his experiences creating tests for pygr, a Python graph database (for use in bioinformatics).  (slide 11)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;~8K of Python, ~2K of Pyrex (-&gt; C, for speed)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;almost all library and framework (complex)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;lots of technical debt&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Code coverage invaluable when aimed at (slide 16)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;new tests efforts on legacy code&lt;br /&gt;&lt;/li&gt;&lt;li&gt;understanding code bases&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Grokking code through coverage (slide 19)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;start with minimum useful statement&lt;br /&gt;&lt;/li&gt;&lt;li&gt;examine code that’s actually executed&lt;br /&gt;&lt;/li&gt;&lt;li&gt;add additional statement&lt;br /&gt;&lt;/li&gt;&lt;li&gt;examine executed code&lt;br /&gt;&lt;/li&gt;&lt;li&gt;repeat&lt;/li&gt;&lt;/ul&gt;(At some point—I can’t find it in the slides—he showed a —coverage-diff command-line option, to figleaf?)&lt;br /&gt;&lt;br /&gt;Coverage driven testing (slide 29)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;each new test should “attack” an uncovered line of code&lt;br /&gt;&lt;/li&gt;&lt;li&gt;immediate gratification of new code coverage&lt;br /&gt;&lt;/li&gt;&lt;li&gt;finds simple bugs with ease&lt;br /&gt;&lt;/li&gt;&lt;li&gt;you now understand that code&lt;/li&gt;&lt;/ul&gt;&lt;h3 id="jesse_noller_introduction_to_multiprocessing_in_python"&gt;&lt;span style="font-size:130%;"&gt;Jesse Noller - Introduction to Multiprocessing in Python&lt;/span&gt;&lt;/h3&gt;I didn’t attend this (as it was at the same time as the above talk), but I heard it was good.  See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/31/"&gt;http://us.pycon.org/2009/conference/schedule/event/31/&lt;/a&gt; for the video and the slides (in PDF format).&lt;br /&gt;&lt;h3 id="michael_foord_functional_testing_of_desktop_applications"&gt;&lt;span style="font-size:130%;"&gt;Michael Foord - Functional Testing of Desktop Applications&lt;/span&gt;&lt;/h3&gt;See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/34/"&gt;http://us.pycon.org/2009/conference/schedule/event/34/&lt;/a&gt; for the video.  See &lt;a href="http://www.voidspace.org.uk/python/articles/testing/index.shtml"&gt;http://www.voidspace.org.uk/python/articles/testing/index.shtml&lt;/a&gt; for “online slides”.&lt;br /&gt;&lt;br /&gt;If you write applications without tests then you are a bad person, incapable of love. — Wilson Bilkovich (The Rails Way)&lt;br /&gt;&lt;br /&gt;Why Test Functionally? (&lt;a href="http://www.voidspace.org.uk/python/articles/testing/processes.shtml"&gt;http://www.voidspace.org.uk/python/articles/testing/processes.shtml&lt;/a&gt;)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Unit tests test components - not the application as a whole&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Check new features don’t break existing functionality&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Massively helpful when refactoring&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Individual tests act as specification for a feature&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Test suites are a specification for the application&lt;br /&gt;&lt;/li&gt;&lt;li&gt;When the test passes you know the feature is done&lt;br /&gt;&lt;/li&gt;&lt;li&gt;They can drive development&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Good advice in dealing with problems (&lt;a href="http://www.voidspace.org.uk/python/articles/testing/problems.shtml"&gt;http://www.voidspace.org.uk/python/articles/testing/problems.shtml&lt;/a&gt;)&lt;/p&gt;Fragility due to layout changes&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Timing problems (beware the lure of the voodoo sleep)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Some UI elements are very hard to test&lt;/li&gt;&lt;li&gt;System dialogs (that are hard to interact with programmatically)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;How do you test printing?&lt;/li&gt;&lt;li&gt;Bugs in the GUI toolkit&lt;/li&gt;&lt;li&gt;Spurious, random and impossible failures&lt;/li&gt;&lt;/ul&gt;&lt;h3 id="raymond_hettinger_easy_ai_with_python"&gt;&lt;span style="font-size:130%;"&gt;Raymond Hettinger - Easy AI with Python&lt;/span&gt;&lt;/h3&gt;I didn’t attend this (as it was at the same time as the above talk), but I heard it was good.  See &lt;a href="http://us.pycon.org/2009/conference/schedule/event/71/"&gt;http://us.pycon.org/2009/conference/schedule/event/71/&lt;/a&gt; for the video and slides (in PPT &amp;amp; PDF formats).&lt;br /&gt;&lt;h3 id="evening_lightning_talks"&gt;&lt;span style="font-size:130%;"&gt;Evening Lightning Talks&lt;/span&gt;&lt;/h3&gt;You’ll find the video at &lt;a href="http://us.pycon.org/2009/conference/schedule/event/39/"&gt;http://us.pycon.org/2009/conference/schedule/event/39/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;RANT: “import *” is evil (right at 0:05 in the video)&lt;br /&gt;&lt;br /&gt;some call Brazil “Belindia” because it’s like “islands of Belgium in a sea of India” (6:18)&lt;br /&gt;&lt;br /&gt;Michael Foord - Metaclasses in Five Minutes (12:00)&lt;br /&gt;&lt;a href="http://www.voidspace.org.uk/python/articles/five-minutes.shtml"&gt;http://www.voidspace.org.uk/python/articles/five-minutes.shtml&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-2738994524773762784?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/tZMwdGHBgMw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/2738994524773762784/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=2738994524773762784" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/2738994524773762784?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/2738994524773762784?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/tZMwdGHBgMw/pycon-2009-notes-march-27th.html" title="PyCon 2009 Notes - March 27th" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://pypap.blogspot.com/2009/04/pycon-2009-notes-march-27th.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08ESHY4eCp7ImA9WxVaGUk.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-6319985291940305084</id><published>2009-04-16T23:18:00.000-07:00</published><updated>2009-04-16T23:30:09.830-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-16T23:30:09.830-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="generators" /><category scheme="http://www.blogger.com/atom/ns#" term="metaclasses" /><category scheme="http://www.blogger.com/atom/ns#" term="TODO" /><category scheme="http://www.blogger.com/atom/ns#" term="properties" /><category scheme="http://www.blogger.com/atom/ns#" term="iteration" /><category scheme="http://www.blogger.com/atom/ns#" term="tutorial" /><category scheme="http://www.blogger.com/atom/ns#" term="pronunciation" /><category scheme="http://www.blogger.com/atom/ns#" term="pycon" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;string interpolation&quot;" /><title>Python 401: Some Advanced Topics</title><content type="html">&lt;p&gt;On Thursday, March 26th, I attended &lt;a href="http://holdenweb.com/about/"&gt;Steve Holden&lt;/a&gt;’s &lt;a href="http://us.pycon.org/2009/tutorials/schedule/2AM1/"&gt;Python 401: Some Advanced Topics&lt;/a&gt; tutorial.  This one wasn’t as mind-expanding as the previous tutorial (or the &lt;a href="http://pypap.blogspot.com/2008/04/pycon-2008-notes.html"&gt;three I took at PyCon 2008&lt;/a&gt;), and none of the material was new to me.  But I’ve found re-learning material will often fill in the gaps in my knowledge, and that certainly was the case here.&lt;/p&gt;You’ll find the slides at &lt;a href="http://holdenweb.com/files/Python401.pdf"&gt;http://holdenweb.com/files/Python401.pdf&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The material was divided into six “lessons”, and three appendices.&lt;br /&gt;&lt;br /&gt;Lesson 1 (slides 4 though 15) was on string interpolation, which I thought I had mastered.  (Especially after the &lt;a href="http://pypap.blogspot.com/2008/04/pycon-2008-notes.html"&gt;Secrets of the Framework Creators tutorial at PyCon 2008&lt;/a&gt; and after writing &lt;a href="http://pypap.blogspot.com/2008/03/string-interpolation.html"&gt;http://pypap.blogspot.com/2008/03/string-interpolation.html&lt;/a&gt;).  But I did learn a few new things.  For example, I didn’t realize that the ‘%s’ conversion uses the value’s str() method.  So one can quite safely do:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;print&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(187, 102, 136); font-weight: bold;"&gt;%s&lt;/span&gt;&lt;span style="color: rgb(186, 33, 33);"&gt;'&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102);"&gt;%&lt;/span&gt; foo&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;…regardless of the type of foo.&lt;br /&gt;&lt;br /&gt;I also didn’t know that one can use an asterisk to make width and precision “data dependent”.  (Steve notes this only works with tuple data—of course it won’t work with a dictionary because the values are not ordered.)  So you can do the following:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&gt;&gt;&gt; &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;foo_wide&lt;/span&gt;(width):&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;...&lt;/span&gt;   &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;print&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(187, 102, 136); font-weight: bold;"&gt;%*s&lt;/span&gt;&lt;span style="color: rgb(186, 33, 33);"&gt;'&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102);"&gt;%&lt;/span&gt; (width, &lt;span style="color: rgb(186, 33, 33);"&gt;'foo'&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;&gt;&gt;&gt;&lt;/span&gt; foo_wide(&lt;span style="color: rgb(102, 102, 102);"&gt;4&lt;/span&gt;)&lt;br /&gt;foo&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;&gt;&gt;&gt;&lt;/span&gt; foo_wide(&lt;span style="color: rgb(102, 102, 102);"&gt;10&lt;/span&gt;)&lt;br /&gt;     foo&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;…or…&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;&gt;&gt;&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;math&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;&gt;&gt;&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;pi_wide&lt;/span&gt;(width, precision):&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;...&lt;/span&gt;   &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;print&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'&lt;/span&gt;&lt;span style="color: rgb(187, 102, 136); font-weight: bold;"&gt;%*.*f&lt;/span&gt;&lt;span style="color: rgb(186, 33, 33);"&gt;'&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102);"&gt;%&lt;/span&gt; (width, precision, math&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;pi)&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;&gt;&gt;&gt;&lt;/span&gt; pi_wide(&lt;span style="color: rgb(102, 102, 102);"&gt;8&lt;/span&gt;,&lt;span style="color: rgb(102, 102, 102);"&gt;2&lt;/span&gt;)&lt;br /&gt;   &lt;span style="color: rgb(102, 102, 102);"&gt;3.14&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;&gt;&gt;&gt;&lt;/span&gt; pi_wide(&lt;span style="color: rgb(102, 102, 102);"&gt;10&lt;/span&gt;,&lt;span style="color: rgb(102, 102, 102);"&gt;5&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: rgb(102, 102, 102);"&gt;3.14159&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;Lesson 2 (slides 17 through 27) was on iteration.  Steve explained the ”iteration protocol”:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;iterables must have an &lt;code&gt;__iter__()&lt;/code&gt; method which returns and iterator&lt;/li&gt;&lt;li&gt;iterators must be iterable, and must also have a next() method&lt;/li&gt;&lt;/ul&gt;Steve (and I later observed Michael Foord also) pronounced &lt;code&gt;__iter__&lt;/code&gt; as “dunder-iter”.  It sounded a little strange at first, but it’s certainly easier than saying “under-under-iter” or “under-under-iter-under-under”.&lt;br /&gt;&lt;br /&gt;Steve mentioned the itertools standard library, but didn’t allocate time in the tutorial to cover it.  (For that I recommend &lt;a href="http://blog.doughellmann.com/2007/10/pymotw-itertools.html"&gt;Doug Hellmann’s PyMOTW blog post&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;He concludes lesson 2 with a slide (#27) explaining how to use the enumerate() built-in function (which I have found useful many times).&lt;br /&gt;&lt;br /&gt;Lesson 3 (slides 29 though 35) was on generators and generator expressions.  I like Steve’s explanation that generators are for creating sequences where computation is needed to create each element.  And in conclusion, he writes that generators can “express producer-consumer algorithms more naturally” since the “generation of values is cleaning separated from their processing”.  But aside from these insights, I didn’t learn anything new about generators.  (That may be difficult after David Beazley’s excellent &lt;a href="http://pypap.blogspot.com/2008/04/pycon-2008-notes.html"&gt;“Generator Tricks for Systems Programmers” tutorial at PyCon 2008&lt;/a&gt;.)  And in spite of the lesson’s title, Steve didn’t cover generator expressions.&lt;br /&gt;&lt;br /&gt;Lesson 4—covering Descriptors and Properties—was the most useful to me.  I’d heard of descriptors and properties, but never really studied them or read code that used them.  First, Steve explains in detail how attribute lookup works in new-style classes.  This leads (after an aside which I’ll mention later) this his definition of properties: “a way of interposing code between client and server of a namespace”.  One can define—using the &lt;code&gt;property()&lt;/code&gt; built-in—a getter, setter and deleter, plus a doc string.  And since the first argument to &lt;code&gt;property()&lt;/code&gt; is the getter function, one can use property as a decorator (with no arguments) around a method.  (See slide 41.)  David Beazley (who was also taking this tutorial) spoke up and pointed out that in Python 2.6 a property object (returned from the property built-in) has setter and deleter methods that can be used as decorators.  See &lt;a href="http://docs.python.org/library/functions.html#property"&gt;the property built-in documentation&lt;/a&gt; for an example.  On slide 45, Steve shows how to define properties without namespace pollution.  Finally (slides 47 though 50) he goes into detail on the difference between old-style and new-style attribute lookup.  I realized as Steve wrapped up this lesson that I still didn’t understand what a descriptor is, so I asked.  Steve’s answer (I think) that the “descriptor protocol” is what enables properties to work.  I gave myself a to-do to read the &lt;a href="http://docs.python.org/reference/datamodel.html#descriptors"&gt;Python documentation on descriptors&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Back to the aside (on slide 39) I mentioned above.  Steve notes that when you look up a callable on an instance, the interpreter creates a “bound method”, therefore (presumably because these are objects like everything else in Python) “a method call carries object creation overhead”.  There’s a good illustration of this on the slide.  This would be good to keep in mind if I ever find myself trying to squeeze as much performance as possible out of some Python code.&lt;br /&gt;&lt;br /&gt;Lesson 5 (slides 52 though 73) is on metaclasses.  I’d seen these before in the &lt;a href="http://pypap.blogspot.com/2008/04/pycon-2008-notes.html"&gt;“Secrets of the Framework Creators” tutorial at !PyCon 2008&lt;/a&gt;.  (And during the time I spent &lt;a href="http://pypap.blogspot.com/2008/06/django-multiple-database-api-proposal.html"&gt;digging around inside the Django sources&lt;/a&gt;).  If you’re still trying to wrap your head around metaclasses, this may be a quick way to get there.  I won’t attempt to summarize, but the insight I gained from this lesson is that the &lt;a href="http://docs.python.org/library/functions.html#type"&gt;type() built-in&lt;/a&gt;, when called with three arguments returns a new type object.  In other words it’s a dynamic form of the class statement.  (This is the mechanism for implementing metaclasses.)  You may also want to read &lt;a href="http://www.voidspace.org.uk/python/articles/five-minutes.shtml"&gt;Michael Foord’s “Metaclasses in Five Minutes” notes&lt;/a&gt; or watch the &lt;a href="http://pycon.blip.tv/file/1949796"&gt;video of his lightning talk at PyCon 2009&lt;/a&gt; (which is supposed to start 11 minutes in).  Though I would conclude that if you’re considering using metaclasses, you should seriously consider using class decorators first.  (See my notes on the &lt;a href="http://us.pycon.org/2009/conference/schedule/event/55/"&gt;“Class Decorators: Radically Simple” PyCon 2009 talk&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;Lesson 6 (slides 75 &amp;amp; 76) was not really a lesson but a very quick wrap-up.&lt;br /&gt;&lt;br /&gt;Finally there are three appendices.  We did find the time to cover Appendix A (slides 78 through 84).  It’s on decorators, but only on the simpler form of decorators that don’t take arguments.  Slides 83 and 84 cover functools.wraps and functools.partial, and are interesting reading.&lt;br /&gt;&lt;br /&gt;We did not cover the other two appendices.  Appendix B (slides 86 through 89) is on context managers, which I myself covered back in July 2008 to present a &lt;a href="http://pypap.blogspot.com/2008/07/newbie-nugget-introduction-to-with.html"&gt;“Newbie Nugget” to BayPIGgies on the with statement&lt;/a&gt;.  Appendix C (slides 92 through 107) is on unit testing.  If you’re new to unit testing or new to the Python unittest module, then this is worth a read.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-6319985291940305084?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/s3tONiq_6Aw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/6319985291940305084/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=6319985291940305084" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/6319985291940305084?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/6319985291940305084?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/s3tONiq_6Aw/python-401-some-advanced-topics.html" title="Python 401: Some Advanced Topics" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://pypap.blogspot.com/2009/04/python-401-some-advanced-topics.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEBRngzeSp7ImA9WxVaE0k.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-2312191362628267106</id><published>2009-04-09T22:55:00.000-07:00</published><updated>2009-04-09T23:07:37.681-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-09T23:07:37.681-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tutorial" /><category scheme="http://www.blogger.com/atom/ns#" term="pycon" /><category scheme="http://www.blogger.com/atom/ns#" term="coroutines" /><title>A Curious Course on Coroutines and Concurrency</title><content type="html">On Wednesday, March 25th, I attended &lt;a href="http://www.dabeaz.com/"&gt;David Beazley&lt;/a&gt;'s &lt;a href="http://us.pycon.org/2009/tutorials/schedule/1PM6/"&gt;A Curious Course on Coroutines and Concurrency&lt;/a&gt; tutorial at &lt;a href="http://us.pycon.org/2009/about/"&gt;PyCon 2009&lt;/a&gt;.  This was an excellent tutorial that continued from where David's &lt;a href="http://us.pycon.org/2008/tutorials/Generators/"&gt;Generator Tricks for Systems Programmers&lt;/a&gt; tutorial from PyCon 2008 left off.  (See my notes on that tutorial in my &lt;a href="http://pypap.blogspot.com/2008/04/pycon-2008-notes.html"&gt;PyCon 2008 Notes blog post&lt;/a&gt;; I see I never did write a summary.)&lt;br /&gt;&lt;br /&gt;David again has made his tutorial materials (including excellent slides and plenty of code samples) publicly available: &lt;a href="http://www.dabeaz.com/coroutines/"&gt;http://www.dabeaz.com/coroutines/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;At the start of the tutorial I had written generators and had some  recollection of the "Generator Tricks for Systems Programmers" tutorial.  But I had only vague sense of what a coroutine is.  After the tutorial I feel like my understanding of coroutines is much deeper.  I'm ready to use them when called for.  I might even understand them well enough to avoid looking for all kinds of inappropriate nails to hit with this new hammer.&lt;br /&gt;&lt;br /&gt;After an entertaining overview—David's sense of humor provided some sugar to help the medicine of the sometimes challenging material go down—he introduces coroutines.  As he writes (on slide 8), in Python 2.5 generators "picked up some new features to allow 'coroutines'" (see &lt;a href="http://www.python.org/dev/peps/pep-0342/"&gt;PEP-342 "Coroutines via Enhanced Generators"&lt;/a&gt;), "most notably: a new send() method".  He adds "If Python books are any guide, this is the most poorly documented, obscure, and apparently useless feature of Python."&lt;br /&gt;&lt;br /&gt;I digress, but as the author of the &lt;a href="http://www.amazon.com/gp/product/0672328623?tag=pythpracandpa-20"&gt;Python Essential Reference&lt;/a&gt;, David has raised the bar for himself.  I happened to pick up a copy of a draft manuscript of a fragment of chapter 6—"Functions and Functional Programming"—from the upcoming &lt;a href="http://www.amazon.com/gp/product/0672329786?tag=pythpracandpa-20"&gt;4th Edition&lt;/a&gt; at the Addison-Wesley booth at PyCon.  Following a section in that chapter explaining what coroutines are is a section entitled "Using Generators and Coroutines".  David explains that "generator functions are useful if you want to set up a processing pipeline, similar in nature to using a pipe in the UNIX shell."  After an example of this he writes "Coroutines can be used to write programs based on data-flow processing.  Programs organized in this way look like inverted pipelines."  The example that follows explains that "the coroutine pipeline remains active indefinitely or until close() is explicitly called on it."  So "a program can continue to feed data into a coroutine for as long as necessary", and his example shows two consecutive calls to send different data into the pipeline.&lt;br /&gt;&lt;br /&gt;I've never owned a copy of Python Essential Reference, but after reading this draft manuscript and seeing first-hand David's ability to simplify sometimes complex material, I've pre-ordered a copy of the 4th Edition.&lt;br /&gt;&lt;br /&gt;Anyway, I need to remember that this is meant to be a summary of the tutorial.  If you want the details you can read the slides and look at the code samples.&lt;br /&gt;&lt;br /&gt;The tutorial was divided into 9 parts.  Part 1 (slides 15 through 33) is a very clear introduction to generators and coroutines.  He summarizes (in slide 33) that generators produce data for iteration, whereas coroutines are consumers are data and are not related to iteration.  He warns us not to mix the two concepts together.&lt;br /&gt;&lt;br /&gt;In Part 2 ("Coroutines, Pipelines, and Dataflow", slides 34 through 52) David explains that coroutines can be used to set up pipes.  Each pipeline needs an initial source (a producer) and and end-point (a sink).  Because (unlike generators which pull data through the pipe with iteration) coroutines push data into the pipeline with send(), they allow you to send data to multiple destinations.  That is, you can have branches in the pipeline.  He shows broadcasting to multiple targets as an example.  (See slides 44 through 46.)  He concludes by showing how coroutines are "somewhat similar to OO design patterns involving simple handler objects".  (I think he's talking about the Chain of Responsibility pattern.)  He notes that just like a generator is an iterator "stripped down to the bare essentials", so is a coroutine very simple compared to the multiple classes required to implement this pattern.  (This is an example of the claim made by &lt;a href="http://us.pycon.org/2009/profile/0765cc/"&gt;Joe Gregorio&lt;/a&gt; in his &lt;a href="http://us.pycon.org/2009/conference/schedule/event/51/"&gt;The (lack of) design patterns in Python&lt;/a&gt; PyCon 2009 talk.)  David also shows that coroutines are faster than objects (because of the lack of self lookups).&lt;br /&gt;&lt;br /&gt;Part 3 ("Coroutines and Event Dispatching", slides 53 through 74) shows that "coroutines can be used to write various components that process event streams".  His example shows parsing the XML data that is available with the real-time GPS tracking data of most Chicago Transit Authority buses.  He has a coroutine that implements a simple state machine to convert the "events" from an XML parser into dictionaries of bus data, another coroutine to filter on dictionary fields, and a coroutine to print the dictionaries as a table.  ''What's quite slick about this is that he hooks them together into a pipeline that works without modification'' with &lt;a href="http://docs.python.org/library/xml.sax.html"&gt;SAX&lt;/a&gt;, &lt;a href="http://docs.python.org/library/pyexpat.html"&gt;expat&lt;/a&gt;, and a custom C extension written on top of the expat C library.  (Each is faster than its predecessor, and the latter is slightly faster than using &lt;a href="http://docs.python.org/library/xml.etree.elementtree.html"&gt;ElementTree&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;Part 4 ("From Data Processing to Concurrent Programming", slides 75 through 91) shows how coroutines "naturally tie into problems involving threads and distributed systems", since you send data to coroutines just as you do to threads (via queues) or processes (via messages).  He creates a coroutine call threaded and hooks it up (slide 84) to the example coroutines from Part 3 so the filters and printing coroutines run in a separate thread.  (And he notes this makes it run about 50% slower!)  He then shows how coroutines could also be used to bridge two processes over a pipe or socket.  So he notes that coroutines allow us to separate the implementation of a task (the coroutines) from the execution environment (threads, subprocesses, network).  But he cautions us that huge collections of coroutines, threads and processes may be difficult to maintain and without careful study may make your program run slower.  He also warns that the send() method on a coroutine must be synchronized, and if you call send() on an already-executing coroutine your program will crash (so no loops or cycles in the pipeline or multiple threads sending data into the same coroutine).&lt;br /&gt;&lt;br /&gt;From here, the tutorial gets much more "mondo".  In Part 5 (slides 92 through 98) he explains that coroutines look like tasks, the building blocks of concurrent programming.  In Part 6 (slides 99 through 109), he gives a crash course in operating systems (and shows the yield statement can be though of like a trap) in order to prepare us for Part 7 (slides 110 through 168), where he builds an operating system using coroutines.  I'm not going to go into detail on this, because this summary is already too long and you're better off reading his slides and looking at the code sample than reading my description of this.  I'll note though that I enjoyed the humor in slide 152, where having written the a Task class to wrap a coroutine, support for system calls and a Scheduler class with basic task management, he states "The next step is obvious; we must implement a web framework".  But he settles for an echo server.  In Part 8 (slides 169 through 188) he explains that coroutines can't call subroutine functions that yield, and explains the solution using "trampolining".  Slide 187 is worth noting, where he shows that application code has "normal looking control flow", just like traditional socket code (and unlike any code using a module that uses event callbacks).&lt;br /&gt;&lt;br /&gt;He wraps it all up in Part 9 (slides 189 through 198).  Here's my summary of his summary:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;generators (and coroutines) are "far more powerful than most people realize"&lt;/li&gt;&lt;li&gt;they have decent performance&lt;/li&gt;&lt;li&gt;but he's not convinced that it's worth using coroutines for general multitasking&lt;/li&gt;&lt;li&gt;it is "critically important" not to mix the three main uses of yield toegether:&lt;/li&gt;&lt;li&gt;iteration&lt;/li&gt;&lt;li&gt;receiving messages&lt;/li&gt;&lt;li&gt;a trap&lt;/li&gt;&lt;/ul&gt;If you find this at all interesting, I urge you to read David's slides and code.  And join me in urging him to present another tutorial at PyCon 2010.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-2312191362628267106?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/s8bb8YzkmWM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/2312191362628267106/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=2312191362628267106" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/2312191362628267106?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/2312191362628267106?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/s8bb8YzkmWM/curious-course-on-coroutines-and.html" title="A Curious Course on Coroutines and Concurrency" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://pypap.blogspot.com/2009/04/curious-course-on-coroutines-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQNRns_fyp7ImA9WxVbEE4.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-8923645428683331301</id><published>2009-03-25T18:14:00.000-07:00</published><updated>2009-03-25T18:19:57.547-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-25T18:19:57.547-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="why" /><category scheme="http://www.blogger.com/atom/ns#" term="TODO" /><category scheme="http://www.blogger.com/atom/ns#" term="books" /><title>Why Python?</title><content type="html">&lt;p&gt;I started reading &lt;a href="http://www.amazon.com/gp/product/0596529325?ie=UTF8&amp;amp;tag=pythpracandpa-20"&gt;Programming Collective Intelligence&lt;/a&gt; again on my flight to Chicago for &lt;a href="http://us.pycon.org/2009/about/"&gt;PyCon 2009&lt;/a&gt;.  I started reading it months ago but never found the time to finish it.  So now I’m starting again at the beginning, but hopefully this time I’ll read the parts I've already read faster (and with better recollection), and hopefully get through more—if not all—of it.  (Not that I find it difficult or dull reading; on the contrary it’s very interesting and well written.)&lt;/p&gt;I read something in the preface I don’t recall noticing last time.  (Though I wish I had noticed it earlier.)  Toby Segaran (the author) explains why he chose Python for all the example code in the book.  He lists six reasons.  Python is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;em&gt;Consise&lt;/em&gt; - Python code tends to be shorter than other “mainstream languages”.  So there’s less typing, but also it’s “easier to fit the algorithm in your head and really understand what it’s doing”.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;em&gt;Easy to read&lt;/em&gt; - If I recall correctly, I’ve heard &lt;a href="http://en.wikipedia.org/wiki/Guido_van_rossum"&gt;Guido&lt;/a&gt; himself describe Python as “executable pseudocode”.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;em&gt;Easily extensible&lt;/em&gt; - In addition to the &lt;a href="http://www.python.org/about/"&gt;“batteries included”&lt;/a&gt;, there are many other modules that free and easy to download, install and use.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;em&gt;Interactive&lt;/em&gt; - If you program in Python and you never use it interactively, you may be a figment of my imagination.  (Though others may be shocked to learn I don’t use &lt;a href="http://ipython.scipy.org/moin/"&gt;IPython&lt;/a&gt;.  When I finish reading Programming Collective Intelligence, next on my list is another book I started and didn’t make time to finish: &lt;a href="http://www.amazon.com/gp/product/0596515820?ie=UTF8&amp;amp;tag=pythpracandpa-20"&gt;Python for Unix and Linux System Administration&lt;/a&gt;.  Chapter 2 is on IPython.)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;em&gt;Multiparadigm&lt;/em&gt; - “Python supports object-oriented, procedural, and functional styles of programming…Sometimes it’s useful to pass around functions as parameters and other times to capture state in an object.”  As I become more proficient with Python I’m surprised that I use all three styles.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;em&gt;Multiplatform and free&lt;/em&gt; - “The code described in this book will work on Windows, Linux, and Macintosh.”&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;I wanted to blog about this because I’m sure I’ll want to refer to this in the future the next time someone asks “Why Python?”  (Though I find I hear that question less and less.  The word is spreading.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-8923645428683331301?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/zSKjycOGqVE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/8923645428683331301/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=8923645428683331301" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/8923645428683331301?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/8923645428683331301?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/zSKjycOGqVE/why-python.html" title="Why Python?" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://pypap.blogspot.com/2009/03/why-python.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMDRXo8eSp7ImA9WxVSGUQ.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-3874815845690667074</id><published>2009-01-08T09:19:00.000-08:00</published><updated>2009-01-14T20:24:34.471-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-14T20:24:34.471-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="django" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;book review&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="baypiggies" /><title>Book Review: Python Web Development with Django</title><content type="html">&lt;a href="http://www.amazon.com/gp/product/0132356139?ie=UTF8&amp;tag=pythpracandpa-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0132356139"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 127px; height: 162px;" src="http://3.bp.blogspot.com/_GBuM4RB_ljE/SW31xNyXMUI/AAAAAAAAAFQ/UM51Z95W2gI/s400/51y3VtGapML._SL160_.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5291155363093492034" /&gt;&lt;/a&gt;&lt;br /&gt;Back in April 2008 I eagerly volunteered to review a “rough cut” of &lt;a href="ttp://www.amazon.com/gp/product/0132356139?ie=UTF8&amp;amp;tag=pythpracandpa-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0132356139"&gt;Python Web Development with Django&lt;/a&gt; by Jeff Forcier, Paul Bissex, and Wesley Chun when I read of the opportunity on the &lt;a href="http://baypiggies.net/"&gt;BayPIGgies&lt;/a&gt; &lt;a href="http://mail.python.org/mailman/listinfo/baypiggies"&gt;mailing list&lt;/a&gt;.  I first completed a first version of this review in April (based on a version of the rough cut updated March 11, 2008).  But I was asked to hold my review until it was updated again—I updated the review using the next two updates, but didn’t complete it.  (I’ll post the whole sordid story is on &lt;a href="http://yacitus.com/"&gt;yacitus.com&lt;/a&gt;.)  I’m ashamed to say the book was published before I finished my review.  (But I did post several comments on the rough cut—under the name “yacitus”—so I’m happy that I contributed to the final outcome in a small way.)  I’m pleased to finally finish my review, about 10 months after I first read the “rough cut”.  It’s fairly long, so you may want to skip to my recommendation in the third-to-last paragraph (before the footnotes).&lt;p&gt;&lt;/p&gt;You’ll find that my coverage of some chapters is extremely detailed, while I only quickly mention others.  The deeper coverage was written back when I was reviewing the rough cut, and I just don’t have time right now to go that deep on the material added to the book since then.  I plan to (someday) use this book to help me convert &lt;a href="http://www.spitzer.us/"&gt;www.spitzer.us&lt;/a&gt; to a “real” blog, and I will update this review as I read other chapters more carefully then.&lt;br /&gt;&lt;p&gt;While I’ve been using Python for about 4 years (full-time for about half that), I’m quite new to Django.  I’ve read &lt;a href="http://www.djangobook.com/"&gt;The Definitive Guide to Django&lt;/a&gt; (which I’ll refer to as TheDjangoBook below) and I won’t be able to resist comparing it to Python Web Development with Django (which I’ll refer to as PyWDwD below).&lt;/p&gt;The first thing I want to do before I start reading (or before I buy) a book is to get a sense of the intended audience.  If I’m in a bookstore, I’ll start by reading the back.  When browsing online (which for me almost always means Amazon.com), I’ll look at the “Editorial Reviews”.  It doesn’t really contain a description of the intended audience (and neither does the back of the book).  But back in April there was a clue in the overview on the book’s public Safari page: “This book is designed to help you learn and use Django (and Python, if necessary)…” (though that text is no longer there).  So I assumed that the book would contain an optional introduction to Python, but would mostly concentrate on Django.&lt;br /&gt;&lt;br /&gt;The second thing I look at is the table of contents.  (Which you’ll find the the Amazon.com Editorial Reviews section.)  The book is divided into five parts:  “Getting Started”, “Django in Depth”, “Django Applications by Example”, “Advanced Django Techniques and Features”, and the appendices.&lt;br /&gt;&lt;p&gt;I’m not going to spend too much time reviewing Chapter 1: “Practical Python for Django”.  I have limited experience with Django (which is why I was so eager to read even this incomplete version of this book), but I am quite comfortable with Python.  But I did skim through the chapter and tried to keep an eye out for any Python features that are used in Django that they don’t cover.  I didn’t find any.  I was surprised to find concise introductions to some of the more complex Python features like generators and decorators.  After reading the chapter over, I would guess that it would be useful for people with a fair bit of programming experience who are new to Python, but I think it would be confusing for anyone completely new to programming.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The beginning of the chapter states that they intend for it to be more than just a high-level introduction.  They explain Python’s “object model, memory management, and philosophies as well as giving a good number of samples and sidebars which directly relate to Django development”.  So I also made note of any content that I found valuable. (1)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The next chapter is “Django for the Impatient”.  As an introduction to Django, they walk the reader through creating a simple blog project.  I’m familiar enough with Django that I skimmed this very quickly, but I expect it would be quite useful to a Django newbie.  It was worth the skim: defining ordering in a model (using the ordering attribute of the Meta inner class) was new to me.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In the next chapter (#3), titled “Starting Out”, they take a step back and provide a “tool-agnostic” view of the Web, provide high-level explanations of Django models, views and templates and explain the general philosophy of the creators of Django.  They warn the reader not to skip ahead (saying “…even intermediate and experienced Web developers can benefit from taking a step back and reviewing the fundamentals…”), but I found I could have completely skipped the “Dynamic website basics” section.  I also could have skipped the “Understanding Models, Views and Templates” section and the explanation of Django’s spin on MVC (2), but I do feel that both would be useful to a Django newbie.  The “Core philosophies of Django” section was interesting, but I didn’t learn anything new.  (It may have reinforced what I already know, however.)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Part II “Django in Depth” starts with Chapter 4: “Defining and Using Models”.  There are (of course) two sections.  The “Defining Models” section starts with an explanation of why to use an ORM.  Then they describe the different types of fields, and explain primary keys (and they describe the “unique=True” argument, which is new to me).  Then they go into detail on foreign keys (many-to-one relationships), many-to-many relationships (both “simple” and “complex”) and a brief explanation of composition with one-to-one relationships (but no examples).  That’s followed a brief description of constraining relationships with a “limit_choices_to” argument.  That’s new to me, and I don’t see a use case for it, so I’d like to see a real example (rather than their contrived example of a Book model class that will only relate to authors whose name ends in Smith).  Next is a detailed explanation of (the new Django feature) model inheritance, where they explain the two different approaches: abstract base classes and multi-table inheritance.  They then describe the Meta inner class with a reasonable amount of detail and conclude with admin registration.  They avoid a detailed explanation of the admin options, which is in keeping with this book’s intention to be more of a tutorial than a reference.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The “Using Models” section starts with an explanation of syncdb.  They’re careful to explain right away that in spite of its name, syncdb will only create database tables to match models—it doesn’t do any sort of synchronization.  I don’t recall TheDjangoBook explicitly stating this so clearly, but I also didn’t learn this the hard way.  I think it became clear as I read through the examples.  They provide a table of the manage.py functions, which I don’t recall seeing in TheDjangoBook, and if I read about the “sql*” functions and “loaddata” and “dumpdata” (in The DjangoBook) then I’ve forgotten.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The meat of the section is in the section on query syntax.  I also don’t recall TheDjangoBook explaining so clearly what a Manager is.  I’ve heard the term, but until I read it in PyWDwD I didn’t realize a Manager object is returned from a model class’s objects attribute, and its methods (all, filter, exclude and get) always return QuerySets.  The explanation in the (next) “QuerySet as a building block” section is also new (to me) and quite lucid.  They explain how QuerySet “…is &lt;em&gt;lazy&lt;/em&gt;: it will only execute a database query when it absolutely has to…” and explain how this allows them to be composed into complex queries.  There’s a lot of detail here, including tweaking the SQL with the QuerySet method extra.  Then the chapter concludes with an explanation of how to use SQL features that Django doesn’t provide.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Chapter 5 is entitled “URLs, HTTP Mechanisms and Views”.  The URLs section contains a very detailed explanation of URLconfs.  Then follows the “Modeling HTTP: Requests, Responses and Middleware” section, which starts a description of request objects, within which their explanation of GET and POST is helpful.  And then the section gets even meatier.  Their explanation of cookies and sessions is (IIRC) not covered in TheDjangoBook.  The section concludes with a brief description of response objects and middleware.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Finally the “Views / Logic” section explains that views are just Python functions, that must take an HttpRequest object and return an HttpResponse object (both of which were explained previously in the “Client/Server - HTTP” section).  And then they jump right in to explaining generic views. (3)  Unfortunately they don’t (yet?) provide any examples, so I imagine their descriptions of the most common generic views will go over the head of Django newbies.  They state that the most common use of “semi-generic” views (calling a generic view from a custom view) is “…to work around an inherent limitation in the URLconf itself: you can’t perform logic with the captured URL parameters until the regular expression has been parsed.”  But they only provide one short example with no explanation of what it does.  Finally they very briefly explain custom views, and describe render&lt;em&gt;to&lt;/em&gt;response() as replacing “…the two- or three-step process of creating a Context object, rendering a Template with it, and then returning an HttpResponse containing the result.”, but I don’t believe they have yet explained what a context object is and only very briefly described templates.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The final chapter in Part II (#6) is “Templates and Form Processing”, containing (of course) two sections.  The “Templates” section is more of an overview of Django templates than an in-depth description.  But I did find it clear and easy to follow.  I didn’t learn anything new, but I already have a reasonable amount of experience using Django templates.  There is plenty of detail in the “Forms” section, and more examples than many of the previous chapters.  I enjoyed reading this chapter—it’s a big improvement over the limited coverage of forms in TheDjangoBook.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Part III, “Django Applications by Example” contains four chapters, each dedicated to a different example application.  Chapter 7—“Photo Gallery”—presents an example application using Django’s image upload field and a custom ImageField subclass that automatically generates thumbnails.  Chapter 8—“Content Management System”—defines “CMS” and describes the “Un-CMS” Flatpages App and presents a simple custom CMS.  Chapter 9—“Liveblog”—walks through the creation of a blog application, including Ajax integration.  The introduction to the chapter states it “goes over everything you need to know to integrate Ajax with a Django Web application without going too deep into the specifics of complex client-server interaction or animation.”  (I’m particularly looking forward to reading this chapter carefully.)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Chapter 10—“Pastebin”—is (I think) last in Part III because it is a lesson in using generic views.  They write: “…the essence of this example is seeing how much work we can hand off to the framework. Some might call this approach lazy, but every line of code you don’t write is one you don’t have to debug.”  They show and explain the model, and the templates are self-explanatory.  The explanation for the URLs is detailed.  And then we’re ready to try it out—they walk us through the “add one” form, the newly created paste, the list of submitted items and the admin screen.  Then they show us how to limit the number of recent pastes displayed, how to add syntax highlighting using the &lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt;SyntaxHighlighter&lt;/a&gt; JavaScript library, and how to write a cron job that periodically deletes old items.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Part IV—“Advanced Django Techniques and Features” contains two chapters.  Chapter 11—“Advanced Django Programming”—has plenty of meat.  There are sections on customizing the admin, generating RSS or Atom feeds, generating downloadable files (including examples of a vCard, CSV, and a chart using PyCha), enhancing the Django ORM with custom managers, and plenty of detail on extending the template system (by creating custom template tags, inclusion tags and custom filters) and using other template engines (Mako in this case).  Their explanation of inclusion tags is detailed and walks through a useful example of how to create a template tag to display a calendar grid.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Chapter 12—“Advanced Django Development”—also has plenty of satisfying detail.  There’s a section on writing utility scripts using Django, with a couple examples: one that can be run using cron to delete old records, and a script to import email from an mbox file to a database using a Django model.  They provide plenty of good advice and background on caching.  I’m sure it’s just a sign of how little I know about Apache, but I had never heard of “ab”, the Apache Bench tool.  I applaud the authors for taking the time to describe its use at the beginning of their caching session, and using it to show measured performance improvements.  A section on testing covers doctest &amp;amp; unittest, testing models, testing your entire web app, and testing the Django codebase itself.  And there’s a couple paragraphs on customizing the Django sources, where they (rightly) discourage the reader from doing so unless it’s worth contributing the changes back to the Django project.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;There are 6 appendices.  Appendix A is titled “Command Line Basics”.  It is a very simple introduction to using a command-line environment on Linux or Unix.  They cover common commands, options and arguments, pipes and redirection, environment variables, and the PATH.  I think this would be quite useful to someone with no command-line experience (perhaps with a strictly Windows background).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Appendix B covers “Installing and Running Django”.  Including installing Python (and brief mentions of Easy Install and IPython), installing Django itself, choosing and configuring a web server (they cover Apache &amp;amp; mod_python, WSGI, and FastCGI with flup), and choosing and configuring an SQL database (they covert SQLite, PostgreSQL, and MySQL, with a quick mention of Oracle and Microsoft SQL Server and IBM DB2).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Appendix C is titled “Tools for Practical Django Development”.  The first section is on version control.  They discuss the fundamentals of branches and merging, describe subversion and the Mercurial and Git DVCSs, and then walk through using version control on a Django project (using Mercurial).  There’s a brief section on project management software, with a description of Trac.  And a brief section on text editors with descriptions of Emacs, Vim, TextMate and Eclipse.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Appendix D is a quick 3 pages on “Finding, Evaluating, and Using Django Applications”, with brief sections on where to look for applications, how to evaluate them, how to use them, and sharing your own applications.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Appendix E covers “Django on the Google App Engine”.  They focus on porting an existing Django app to App Engine, and creating a new Django app written specifically for App Engine.  While not exhaustive, the detail on porting looks useful.  (I hope to come back to this in more detail later.)  But the intention of the appendix is to give an overview; they conclude with a list of online resources for more detail.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The final appendix F (and conclusion of the book) is two pages on “Getting Involved in the Django Project”.  They describe ways to contribute that don’t require any programming, ways to contribute involving code that “still don’t require Herculean effort”, and offer ideas for contributions that would “have a significant impact on the Django community”.  The conclude by pointing the reader to the two Django mailing lists, IRC and some Django community web sites.  It feels like an appropriate ending to the book.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In conclusion, I recommend Python Web Development with Django to anyone considering (or just starting) using Django to build a web site.  I recommend it over TheDjangoBook, not just because PyWDwD is more up-to-date, but also because I think it does a better job at explaining all the new concepts required when using a web framework.  My main concern when reading the rough cut version was that there were not enough examples.  But that’s been almost entirely rectified in the published book.  (And the book should empower the reader to go out an find more open source examples as needed.)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The only other thing I noticed that was missing was examples of writing Django applications (Django terminology for modules built to be reusable, if possible).  But a book can’t be everything to everyone, and that’s a niche that James Bennett’s book &lt;a href="http://www.amazon.com/gp/product/1590599969?ie=UTF8&amp;amp;tag=pythpracandpa-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1590599969"&gt;Practical Django Projects&lt;/a&gt; looks like it will fill nicely.  (I hope to review it eventually.)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;One other Django book I hope to find time to read is Marty Alchin’s &lt;a href="http://www.amazon.com/gp/product/1430210478?ie=UTF8&amp;amp;tag=pythpracandpa-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1430210478"&gt;Pro Django&lt;/a&gt;.  It looks like it will pick up where these other two leave off.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Footnotes:&lt;br /&gt;&lt;/p&gt;(1) I made note of the following tidbits along the way:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I didn’t know about the enumerate() built-in function.  I’m sure there have been times where I could have used that to simplify my code.  They have an explanation of a handy way to use enumerate in Django models that you’ll also find used in &lt;a href="http://news.e-scribe.com/230"&gt;this Paul Bissex blog post&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;I also wasn’t aware of the sorted() built-in function, which would also simplify my code at times in place of the list sort() method (which doesn’t have a return value).&lt;/li&gt;&lt;li&gt;Their explanation of “tuple-related gotchas” will be quite helpful to Python newbies.&lt;/li&gt;&lt;li&gt;I wasn’t aware of “from . import X” and “from .. import Y”.  I can think of one specific place in my code where “from ..” will help.&lt;/li&gt;&lt;li&gt;Their entire “Common Gotchas” section is excellent reading.&lt;/li&gt;&lt;/ul&gt;(2) See &lt;a href="http://docs.djangoproject.com/en/dev/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names"&gt;http://docs.djangoproject.com/en/dev/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(3) This is the opposite approach to TheDjangoBook, which (IIRC) gives many examples of views and saves generic views for a separate chapter.  I don’t think one approach is demonstrably better than the other, but I found it easier to understand generic views this time.  But that could be because I read PyWDwD after already reading about generic views in TheDjangoBook.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-3874815845690667074?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/B4h4axbLC7c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/3874815845690667074/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=3874815845690667074" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/3874815845690667074?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/3874815845690667074?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/B4h4axbLC7c/book-review-python-web-development-with.html" title="Book Review: Python Web Development with Django" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_GBuM4RB_ljE/SW31xNyXMUI/AAAAAAAAAFQ/UM51Z95W2gI/s72-c/51y3VtGapML._SL160_.jpg" height="72" width="72" /><thr:total>9</thr:total><feedburner:origLink>http://pypap.blogspot.com/2009/01/book-review-python-web-development-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QEQnszcSp7ImA9WxRXE0Q.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-2121070860717474568</id><published>2008-10-18T08:10:00.000-07:00</published><updated>2008-10-18T21:41:43.589-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-18T21:41:43.589-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="&quot;test-driven development&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="mock" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;newbie nugget&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="TODO" /><category scheme="http://www.blogger.com/atom/ns#" term="baypiggies" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;dependency injection&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;unit tests&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="presentation" /><category scheme="http://www.blogger.com/atom/ns#" term="TDD" /><title>Newbie Nugget: Unit Testing with Mock</title><content type="html">I presented my second &lt;a href="http://mail.python.org/pipermail/baypiggies/2008-June/003611.html"&gt;“Newbie Nugget”&lt;/a&gt; at the October &lt;a href="http://baypiggies.net/new/plone"&gt;BayPIGgies&lt;/a&gt; meeting.  Since I’ve been working with &lt;a href="http://www.voidspace.org.uk/python/mock.html"&gt;Mock&lt;/a&gt; quite a bit lately, I chose to present on that.  (I also thought I could present on decorators, but I decided Mock would be easier since I’d have to do the least to prepare.  I remember feeling confident on my knowledge of Mock itself, but I suspected there was still a lot I had to learn on unit testing.  My suspicions proved correct.)&lt;br /&gt;&lt;p&gt;I didn’t make as much time to prepare as I would have liked.  I ended up with 18 slides, and didn’t have time to trim them down.  So I had to breeze through them very quickly.  (In theory I only had 5 minutes.  I don’t know how long I actually took—probably more like 10—it turned out there wasn’t any pressure this time to keep it brief.)  I also would have liked to have time to come up with some real-world examples, but in my rush to finish the slides I ended up taking the code examples from &lt;a href="http://www.voidspace.org.uk/python/mock.html"&gt;Michael Foord’s documentation&lt;/a&gt;, except for the last two examples which I pulled out of my own code.  I’ve uploaded the Keynote slides exported to &lt;a href="http://www.spitzer.us/daryl/baypiggies/2008-10-09/Mock.pdf"&gt;PDF&lt;/a&gt; and to &lt;a href="http://spitzer.us/daryl/baypiggies/2008-10-09/"&gt;HTML&lt;/a&gt;.  To save some of you some time, the references I had in my final slide are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.voidspace.org.uk/python/mock.html"&gt;The Mock documentation&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.voidspace.org.uk/python/articles/mocking.shtml"&gt;Michael Foord’s “Mocking, Patching, Stubbing: all that Stuff” blog post&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Mock_Object"&gt;The Wikipedia article on mock objects&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;Martin Fowler’s “Mocks Aren’t Stubs” essay&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Note that I prepared this presentation based upon Mock version 0.3.1.  Michael has since released version 0.4.0.  &lt;strong&gt;TODO&lt;/strong&gt;: I’d like to describe the details on what’s new in 0.4.0—but in the meantime, see the &lt;a href="http://www.voidspace.org.uk/python/mock.html#version-0-4-0"&gt;notes in the documentation&lt;/a&gt; or &lt;a href="http://www.voidspace.org.uk/python/weblog/arch_d7_2008_10_11.shtml#e1019"&gt;Michael’s blog post&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;After the &lt;a href="http://baypiggies.net/new/plone/eventfolder/baypiggies-october-9-2008-meeting/"&gt;main presentation on PyGameSF&lt;/a&gt;, there was some extra time left and &lt;a href="http://mail.python.org/pipermail/baypiggies/2008-October/004000.html"&gt;Jim Stockford&lt;/a&gt; asked if I’d be willing to take questions.  I’m glad he asked, and I’m glad I did so.  (How could I not?)  I probably will not recall all the questions.  Feel free to ask them again here, or on the &lt;a href="http://mail.python.org/mailman/listinfo/baypiggies"&gt;BayPIGgies mailing list&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The first question I remember was whether I’ve found any bugs in Mock.  I replied no, and elaborated that Mock was written using test-driven development and the tests themselves use Mock (and are included with Mock).  So if you do find a bug, you can easily fix it yourself.  (But looking at the &lt;a href="http://www.voidspace.org.uk/python/mock.html#changelog"&gt;changelog&lt;/a&gt;, it appears there have been few bugs fixes.  Most changes have been new features.  BTW, I’ve submitted a couple patches with new features myself, but I believe Michael decided he wasn’t ready for them or decided to implement them in a different way.  &lt;strong&gt;TODO&lt;/strong&gt;: I have a couple ideas for other new features to add.)  And &lt;a href="http://www.voidspace.org.uk/python/mock.html#examples"&gt;Mock’s unit tests are good examples of how to use Mock&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Then &lt;a href="http://en.wikipedia.org/wiki/Alex_Martelli"&gt;Alex Martelli&lt;/a&gt; commented (I probably won’t get this right) that my use of the @patch decorator in my tests is dangerous and won’t scale.  (It’s not clear to me whether he meant it won’t scale to projects with large amounts of code, or large numbers of programmers, or large numbers of processes and/or threads, or something else entirely different.)  He suggested we have a look at the video of him talking about this.  &lt;span style="font-weight: bold;"&gt;Update&lt;/span&gt;: I thought that may be &lt;a href="http://www.youtube.com/watch?v=0vJJlVBVTFg"&gt;this YouTube video from Google Developer Day 2008 on “Python Design Patterns”&lt;/a&gt; (added June 4, 2007?), but Alex comments (below) that the video is not currently available, but we can find the slides at &lt;a href="http://www.aleax.it/yt_pydi.pdf"&gt;http://www.aleax.it/yt_pydi.pdf&lt;/a&gt;. And Alex described how the code would use “self” to refer to any dependency, which would allow that dependency to be changed by tests, or by other code that might use it.&lt;/p&gt;&lt;p&gt;I then asked a question (which I can no longer recall) and Alex stood up and came up to the microphone to elaborate.  After sitting down, I (and others) asked further questions (which I also can’t recall) and Alex got some exercise sitting down and getting back up a few times until the two of us stayed at the podium and Alex gave me (and the audience) an impromptu (but very meaty) lesson on dependency injection.  (I hope Google makes the video of this available—I’d like to watch it again myself.  I haven’t found the video of &lt;a href="http://pypap.blogspot.com/2008/07/newbie-nugget-introduction-to-with.html"&gt;my previous newbie nugget presentation&lt;/a&gt; yet though.)  I do remember one (rather foolish) question I asked: I described how I had tried dependency injection using keyword arguments to functions with defaults, and how that gets complicated to test when testing a function which calls a function which calls a function with such an argument.  Alex kindly repeated that dependency injection should be implemented using “self”, which I took to mean that one would use an object’s attributes to hold the dependencies.  (This would certainly make the scenario I described much simpler to test.)&lt;/p&gt;&lt;p&gt;In a discussion after the meeting, I explained to one of several people I had very interesting follow-up conversations with (I didn’t get his name) on a white-board how this would work.  The Google engineer who had graciously agreed at the last minute to host our meeting (I didn’t get is name either—but learned later that he was visiting from Australia) was watching (probably because we were over-staying our welcome) and as we were walking how he explained how the accepted technique is actually to use class attributes for the dependencies, since it’s less work to inject new dependencies into multiple objects, but one can still override dependencies for a particular object (since an object attribute will “replace” a class attribute with the same name).&lt;/p&gt;&lt;p&gt;One other question I recall (it may have been the last) was &lt;a href="http://www.blogger.com/profile/03270879497119114175"&gt;-jj’s&lt;/a&gt;.  He asked (shrewdly) asked me to explain why one would want to use mocks.  I decided to (figuratively) take a step back and first describe why one would want to test and use test-driven development (and what that is).  I described the benefits those practices and then explained (or tried to) how mocks are used in testing to replace dependencies and allow unit tests to be truly “unit” tests and run fast to keep the test-implement-refactor cycle quick.  &lt;strong&gt;TODO&lt;/strong&gt;: Write this up in detail.&lt;/p&gt;&lt;p&gt;I concluded by thanking everyone for their questions and comments (especially Alex)—I stated I felt like I had learned more from everyone else than they probably did from me.  When I sat down afterward, Alex turned to me and quoted &lt;a href="http://en.wikipedia.org/wiki/Richard_Bach"&gt;Richard Bach&lt;/a&gt;: &lt;a href="http://en.wikiquote.org/wiki/Richard_Bach"&gt;“You teach best what you most need to learn.”&lt;/a&gt;.  Absolutely.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Next&lt;/strong&gt;: Write up my experiences modifying my code and tests to use dependency injection, and contrast the new versions of the two examples from my slides.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-2121070860717474568?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/ElNHzS2Z7EE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/2121070860717474568/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=2121070860717474568" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/2121070860717474568?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/2121070860717474568?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/ElNHzS2Z7EE/newbie-nugget-unit-testing-with-mock.html" title="Newbie Nugget: Unit Testing with Mock" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://pypap.blogspot.com/2008/10/newbie-nugget-unit-testing-with-mock.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYNRXg9cCp7ImA9WxRQGU8.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-3236504485090764887</id><published>2008-07-10T09:36:00.000-07:00</published><updated>2008-10-13T12:29:54.668-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-13T12:29:54.668-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="&quot;newbie nugget&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="baypiggies" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;with statement&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="presentation" /><title>Newbie Nugget: Introduction to the with statement</title><content type="html">&lt;p&gt;I’ve signed up to present the first &lt;a href="http://baypiggies.net/new/plone"&gt;BayPIGgies&lt;/a&gt; &lt;a href="http://mail.python.org/pipermail/baypiggies/2008-June/003611.html"&gt;“Newbie Nugget”&lt;/a&gt; at tonight’s meeting, on the &lt;strong&gt;with&lt;/strong&gt; statement.  I know from past experience that the best way to learn something is to explain it—and one has to learn it very well to explain it to a large group of smart people.&lt;/p&gt;&lt;p&gt;What follows are the notes I compiled as I taught myself about the &lt;strong&gt;with&lt;/strong&gt; statement.  I’ll turn these into slides for tonight.  Since I only have 10 minutes for the presentation, I’ll keep these notes brief.  (Think of this as an introduction to the with statement.)  You’ll find links to further reading below.&lt;/p&gt;&lt;p&gt;We’re all used to (or should be used to) writing code that looks like this:&lt;/p&gt;&lt;div class="highlight"&gt;&lt;pre&gt;f &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;open&lt;/span&gt;(filename)&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;try&lt;/span&gt;:&lt;br /&gt;   &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;print&lt;/span&gt; f&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;read()&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;finally&lt;/span&gt;:&lt;br /&gt;   f&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;close()&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;strong&gt;with&lt;/strong&gt; statement (introduced in Python 2.5) simplifies that to:&lt;/p&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;from&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 0, 255);"&gt;__future__&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;import&lt;/span&gt; with_statement&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;with&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;open&lt;/span&gt;(filename) &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;as&lt;/span&gt; f:&lt;br /&gt;   &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;print&lt;/span&gt; f&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;read()&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(“with” and “as” are keywords in Python 2.6, and “from __future__ import…” is not needed.)&lt;/p&gt;&lt;p&gt;The specified syntax for the &lt;strong&gt;with&lt;/strong&gt; statement is:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;with EXPR as VAR:&lt;br /&gt;BLOCK&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The “as VAR” part is optional.&lt;/p&gt;&lt;p&gt;The EXPR must result in a &lt;em&gt;context manager&lt;/em&gt;.  Briefly, a context manager is an object with a &lt;code&gt;__context__()&lt;/code&gt; method, which returns a &lt;em&gt;context object&lt;/em&gt;.  A context object has an &lt;code&gt;__enter__()&lt;/code&gt; method, which is invoked as soon as a context object is returned.  Its return value is assigned to VAR (if there is one).  When the with statement terminates, the context object’s &lt;code&gt;__exit__()&lt;/code&gt; method is called.  (I won’t take the time to go into the arguments to &lt;code&gt;__exit__()&lt;/code&gt;.)&lt;/p&gt;&lt;p&gt;The &lt;a href="http://docs.python.org/lib/module-contextlib.html"&gt;&lt;code&gt;contextlib&lt;/code&gt; module&lt;/a&gt; provides “utilities for common tasks involving the &lt;strong&gt;with&lt;/strong&gt; statement.”&lt;/p&gt;&lt;p&gt;The &lt;code&gt;contextlib.closing&lt;/code&gt; function returns a context manager that closes its argument.  For example:&lt;/p&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;from&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 0, 255);"&gt;__future__&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;import&lt;/span&gt; with_statement&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;from&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 0, 255);"&gt;contextlib&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;import&lt;/span&gt; closing&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;import&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 0, 255);"&gt;urllib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;with&lt;/span&gt; closing(urllib&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;urlopen(&lt;span style="color: rgb(186, 33, 33);"&gt;'http://www.python.org'&lt;/span&gt;)) &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;as&lt;/span&gt; page:&lt;br /&gt;   &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;for&lt;/span&gt; line &lt;span style="font-weight: bold; color: rgb(170, 34, 255);"&gt;in&lt;/span&gt; page:&lt;br /&gt;       &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;print&lt;/span&gt; line&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the &lt;code&gt;contextlib.contextmanager&lt;/code&gt; function “is a decorator that can be used to define a factory function for &lt;strong&gt;with&lt;/strong&gt; statement context managers, without needing to create a class or separate &lt;strong&gt;enter&lt;/strong&gt;() and &lt;strong&gt;exit&lt;/strong&gt;() methods.”  For example:&lt;/p&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;from&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 0, 255);"&gt;__future__&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;import&lt;/span&gt; with_statement&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;from&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 0, 255);"&gt;contextlib&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;import&lt;/span&gt; contextmanager&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(170, 34, 255);"&gt;@contextmanager&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;opened&lt;/span&gt;(filename):&lt;br /&gt;   f &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;open&lt;/span&gt;(filename)&lt;br /&gt;   &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;try&lt;/span&gt;:&lt;br /&gt;       &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;yield&lt;/span&gt; f&lt;br /&gt;   &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;finally&lt;/span&gt;:&lt;br /&gt;       f&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;close()&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;with&lt;/span&gt; opened(filename) &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;as&lt;/span&gt; f:&lt;br /&gt;   &lt;span style="font-weight: bold; color: rgb(0, 128, 0);"&gt;print&lt;/span&gt; f&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;read()&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is plenty more detail in &lt;a href="http://www.python.org/dev/peps/pep-0343/"&gt;PEP 343&lt;/a&gt;, including plenty of fun examples.  My favorites are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;(2) The &lt;code&gt;opened()&lt;/code&gt; context manager used above&lt;/li&gt;&lt;li&gt;(3) &lt;code&gt;transaction()&lt;/code&gt; context manager for committing or rolling back a database transaction&lt;/li&gt;&lt;li&gt;(5) &lt;code&gt;stdout_redirected()&lt;/code&gt; context manager for temporarily redirecting stdout&lt;/li&gt;&lt;li&gt;(7) A context manager for blocking signals.  (This one is actually left as an exercise to the reader.)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;To learn about the &lt;strong&gt;with&lt;/strong&gt; statement (before reading &lt;a href="http://www.python.org/dev/peps/pep-0343/"&gt;PEP 343&lt;/a&gt; and the &lt;a href="http://docs.python.org/lib/module-contextlib.html"&gt;&lt;code&gt;contextlib&lt;/code&gt; module&lt;/a&gt; documentation), I first turned to section 10.4 (Context Management) of &lt;a href="http://www.amazon.com/gp/product/0132269937?ie=UTF8&amp;amp;tag=pythpracandpa-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0132269937"&gt;Core Python Programming (2nd Edition)&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=pythpracandpa-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0132269937" alt="" style="border: medium none  ! important; margin: 0px ! important;" border="0" height="1" width="1" /&gt; by Wesley J. Chun.  It provided an excellent introduction.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-3236504485090764887?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/JRBhyCyrC3o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/3236504485090764887/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=3236504485090764887" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/3236504485090764887?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/3236504485090764887?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/JRBhyCyrC3o/newbie-nugget-introduction-to-with.html" title="Newbie Nugget: Introduction to the with statement" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://pypap.blogspot.com/2008/07/newbie-nugget-introduction-to-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYFQ3c8fCp7ImA9WxdRFUQ.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-7956718172281960600</id><published>2008-06-04T08:03:00.000-07:00</published><updated>2008-06-04T08:08:32.974-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-04T08:08:32.974-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="api" /><category scheme="http://www.blogger.com/atom/ns#" term="django" /><category scheme="http://www.blogger.com/atom/ns#" term="patch" /><title>Django multiple database API proposal</title><content type="html">I finally wrote up the multiple database API I proposed at the Django sprint at PyCon 2008,  in &lt;a href="http://groups.google.com/group/django-developers/msg/7b20663b5bac003a"&gt;a post to the django-developers mailing list&lt;/a&gt;.  Hopefully I'll soon be able to finish the coding I began then and finally create a working patch so the community can play with it and test it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-7956718172281960600?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/AferI6Z4iJg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/7956718172281960600/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=7956718172281960600" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/7956718172281960600?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/7956718172281960600?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/AferI6Z4iJg/django-multiple-database-api-proposal.html" title="Django multiple database API proposal" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://pypap.blogspot.com/2008/06/django-multiple-database-api-proposal.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYGRXw5eCp7ImA9WxZaF0U.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-3876526056311023611</id><published>2008-05-01T22:14:00.000-07:00</published><updated>2008-05-02T19:35:24.220-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-02T19:35:24.220-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="podcast" /><category scheme="http://www.blogger.com/atom/ns#" term="Google" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;Google App Engine&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;Google Developer Podcast&quot;" /><title>Google Developer Podcast: Google App Engine</title><content type="html">If you have any interest in &lt;a href="http://code.google.com/appengine/"&gt;Google App Engine&lt;/a&gt;, I recommend listening to &lt;a href="http://google-code-updates.blogspot.com/2008/04/google-developer-podcast-episode-15.html"&gt;episode 15 of the Google Developer Podcast&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I haven't made time to play with App Engine yet, but I'm looking forward to it.  I registered for the &lt;a href="http://googleappengine.blogspot.com/2008/04/google-app-engine-hack-thons.html"&gt;Google App Engine "Hack-a-thon"&lt;/a&gt; (in San Francisco on May 16th), so if I can't make time to play with it before then, at least I'll have the day to hack away. Hopefully they'll give out accounts to attendees (I wasn't one of the first 10,000 to sign up so I didn't get an account)--but if not, I can still &lt;a href="http://code.google.com/p/googleappengine/"&gt;download the SDK&lt;/a&gt; and &lt;a href="http://code.google.com/appengine/kb/general.html#dev"&gt;start developing&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-3876526056311023611?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/HGen-Zx9KRw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/3876526056311023611/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=3876526056311023611" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/3876526056311023611?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/3876526056311023611?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/HGen-Zx9KRw/google-developer-podcast-google-app.html" title="Google Developer Podcast: Google App Engine" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://pypap.blogspot.com/2008/05/google-developer-podcast-google-app.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYHRnk5cSp7ImA9WxdWF00.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-826684573761588695</id><published>2008-04-01T07:14:00.000-07:00</published><updated>2008-07-10T09:42:17.729-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-10T09:42:17.729-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="TODO" /><category scheme="http://www.blogger.com/atom/ns#" term="baypiggies" /><category scheme="http://www.blogger.com/atom/ns#" term="pycon" /><category scheme="http://www.blogger.com/atom/ns#" term="presentation" /><title>PyCon 2008 Notes</title><content type="html">I just completed writing up my notes on &lt;a href="http://us.pycon.org/2008/about/"&gt;PyCon 2008&lt;/a&gt; for my employer (who paid my way), and thought I should also share them here.  I apologize for using one long blog post;  I decided the ability to refer to a single post outweighed the advantages of &lt;span style="font-size:100%;"&gt;several&lt;/span&gt; smaller ones.  (And you'll have to ignore the "TODOs" I've sprinkled in the text.)&lt;br /&gt;&lt;br /&gt;I &lt;a href="http://yacitus.blogspot.com/2008/02/im-going-to-pycon.html"&gt;attended&lt;/a&gt; PyCon from March 13 through 20, 2008.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Tutorials&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Thursday April 13 was a day of &lt;a href="http://us.pycon.org/2008/tutorials/"&gt;tutorials&lt;/a&gt;.  I attended three (of a maximum of three).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Secrets of the Framework Creators Tutorial&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The first tutorial I attended was &lt;a href="http://us.pycon.org/2008/tutorials/FrameworksHsu/"&gt;"Secrets of the Framework Creators"&lt;/a&gt;, presented by &lt;a href="http://feihonghsu.blogspot.com/"&gt;Feihong Hsu&lt;/a&gt; and &lt;a href="http://farmdev.com/"&gt;Kumar McMillan&lt;/a&gt;.  This was an excellent tutorial that opened my my to some much more sophisticated ways of using Python.  (See the three previous posts I've written on this tutorial so far.)&lt;br /&gt;&lt;br /&gt;You'll find the materials they prepared for the tutorial in the &lt;a href="http://groups.google.com/group/secrets-of-the-framework-creators/files"&gt;Google Group&lt;/a&gt; they created.  They covered four topics:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Frame Hacks&lt;/li&gt;&lt;li&gt;Decorators&lt;/li&gt;&lt;li&gt;Metaclasses&lt;/li&gt;&lt;li&gt;Magic Methods&lt;/li&gt;&lt;/ul&gt;(Of these four, frame hacks and metaclasses were completely new to me.  I already had some experience with decorators and magic methods.)&lt;br /&gt;&lt;br /&gt;It would be a waste of my time to summarize any of the material presented, since the &lt;a href="http://groups.google.com/group/secrets-of-the-framework-creators/files"&gt;tutorial materials&lt;/a&gt; do such an excellent job introducing these subjects.  If you want a quick overview, you can probably read through them in an hour or less.  And if you really want to learn to use these techniques, you can spend a few hours on the exercises they've provided.&lt;br /&gt;&lt;br /&gt;Here are the few brief notes I took during the tutorial:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;TODO - Learn about &lt;a href="http://users.rcn.com/python/download/Descriptor.htm"&gt;properties and descriptors&lt;/a&gt;&lt;/li&gt;&lt;li&gt;TODO - Look into &lt;a href="http://peak.telecommunity.com/DevCenter/Trellis"&gt;Trellis&lt;/a&gt;&lt;/li&gt;&lt;li&gt;TODO - Look at &lt;a href="http://docs.python.org/lib/module-functools.html"&gt;functools&lt;/a&gt;&lt;/li&gt;&lt;li&gt;TODO - Look at the &lt;a href="http://docs.python.org/lib/module-inspect.html"&gt;inspect module&lt;/a&gt;&lt;/li&gt;&lt;li&gt;The "automatic debugger methods" recipe in the metaclasses section is way cool&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;Generator Tricks for Systems Programmers&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The second tutorial I attended was &lt;a href="http://us.pycon.org/2008/tutorials/Generators/"&gt;"Generator Tricks for Systems Programmers"&lt;/a&gt;, presented by &lt;a href="http://www.dabeaz.com/"&gt;David Beazley&lt;/a&gt;.  David has also made his tutorial materials (including excellent slides and plenty of code samples) publicly available: &lt;a href="http://www.dabeaz.com/generators/"&gt;http://www.dabeaz.com/generators/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;At the start of the tutorial I had written iterators, and had a vague understanding of generators.  After the tutorial, I now feel like my understanding of generators is much deeper.  I very highly recommend you take the time to read through the slides (probably one to two hours) and look through his code samples.&lt;br /&gt;&lt;br /&gt;TODO  - add a summary here&lt;br /&gt;&lt;br /&gt;My notes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I didn't know that "Conditional Expressions" (aka "the Ternary Operator") was added to Python in 2.5.  See an example at the bottom of slide 64.&lt;/li&gt;&lt;li&gt;There's a nifty trick in using the max function under the first bullet of slide 71.  TODO - explain.&lt;/li&gt;&lt;li&gt;I wrote on slide 135 that the find_404() function could be modified to take a receiver arg and call it instead of the print (and the print could be wrapped in a consumer function).  TODO - explain&lt;/li&gt;&lt;li&gt;TODO - I also gave myself a TODO on slide 135 to compare this to the previous use(s) of broadcast&lt;/li&gt;&lt;li&gt;TODO - Someone mentioned the "etree" (I think they meant &lt;a href="http://effbot.org/zone/element-index.htm"&gt;ElementTree&lt;/a&gt;), which either uses generators for parsing XML or can be used with generators.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;Django Code Lab&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The last tutorial I attended was the &lt;a href="http://us.pycon.org/2008/tutorials/DjangoLab/"&gt;Django Code Lab&lt;/a&gt;.  The presenters, Adrian Holovaty (one of the creators and core developers of Django), Jacob Kaplan-Moss (a core developer of Django) and James Bennett (release manager for Django) asked people to send in questions and code samples, and then reviewed them in the lab.  (I did submit some code developed at the last minute--my main question was how best to integrate models that don't use the database with others that do--but mine was not chosen.)&lt;br /&gt;&lt;br /&gt;The slides are posted at &lt;a href="http://toys.jacobian.org/presentations/2008/pycon/codelab/"&gt;http://toys.jacobian.org/presentations/2008/pycon/codelab/&lt;/a&gt;.  They may not be too useful out of context.  But I refer to them in my notes (below):&lt;br /&gt;&lt;br /&gt;The first up was Pim Van Heuven:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;he had a huge urls.py file - see the slides&lt;/li&gt;&lt;li&gt;they also presented "Forms with extra parameters"&lt;/li&gt;&lt;/ul&gt;Next was Justin Lilly:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Jacob ranted about TDD&lt;/li&gt;&lt;li&gt;then he presented some useful information about testing Django&lt;ul&gt;&lt;li&gt;look at the model examples in the Django documentation, they're all working unit tests&lt;/li&gt;&lt;li&gt;see slides for example of using django.test.TestCase&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;Next was Richard House:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;he had a long list of BooleanFields in his model&lt;ul&gt;&lt;li&gt;they pointed out that one should use NullBooleanField rather than BooleanField(null=True)&lt;/li&gt;&lt;li&gt;the slides present a pattern for using "two pairs of models"&lt;/li&gt;&lt;li&gt;Adrian pointed out this is called &lt;a href="http://en.wikipedia.org/wiki/Entity-Attribute-Value_model"&gt;EAV (Entity-Attribute-Value)&lt;/a&gt; and noted this has problems with searching and queries&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;Next, Peter Herndon:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;he suffered from slow queries (see the slides)&lt;/li&gt;&lt;li&gt;someone recommended a Malcolm Tredinnick blog post (I think &lt;a href="http://www.pointy-stick.com/blog/2008/03/26/more-django-queryset-notes/"&gt;this one&lt;/a&gt;); though his blog is definitely recommended reading for anyone using Django&lt;/li&gt;&lt;li&gt;see the optimization notes for your database - Jacob says the PostgreSQL optimization notes are especially good&lt;/li&gt;&lt;li&gt;James recommends especially django-sphinx for searching (David Cramer used it for a very busy site with a single database server)&lt;/li&gt;&lt;li&gt;Jacob mentioned &lt;a href="http://www.google.com/coop/"&gt;Google Co-op&lt;/a&gt; several times&lt;/li&gt;&lt;/ul&gt;Next, J. Clifford (Cliff) Dyer:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;  Handling previous/next links&lt;/li&gt;&lt;li&gt;  I didn't fully understand the discussion, and there were no code examples provided unfortunately (and no slides)&lt;/li&gt;&lt;/ul&gt;Next, Dave Lowe:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the subject was when not to use the admin&lt;ul&gt;&lt;li&gt;the advice was that the admin should only be used by someone trusted with access to the entire database (even after the newforms-admin branch is merged back into the trunk)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Adrian said that the key to mastering Django as a tool is to learn (through experience) when to use different parts of Django and when not to&lt;/li&gt;&lt;/ul&gt;Next, Bob Haugen:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;prepping for deployment&lt;/li&gt;&lt;ul&gt;&lt;li&gt;make sure that django.views.static.serve is blocked out inside settings.DEBUG&lt;/li&gt;&lt;li&gt;see the HOME trick with os.path.join() for TEMPLATES_DIR&lt;/li&gt;&lt;li&gt;see the urlresolvers.reverse slide&lt;/li&gt;&lt;li&gt;worth looking at mod_wsgi first (before mod_python)&lt;/li&gt;&lt;li&gt;Jacob admitted (reluctantly) that MySQL is easier to setup than PostgreSQL&lt;/li&gt;&lt;li&gt;see the slide 97, which summarizes "Develop" vs. "Deploy"&lt;ul&gt;&lt;li&gt;Jacob forgot to include creating 500.html &amp;amp; 404.html pages&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;Next, Wiley Kestner:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;see the slides for details on the Django dispatcher&lt;/li&gt;&lt;/ul&gt;Then they ran out of time, but the slides also contain some details on REST APIs,&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Slides for other tutorials&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I got the URL for the slides from the Introduction to SQLAlchemy tutorial from IRC: &lt;a href="http://utahpython.org/jellis/"&gt;http://utahpython.org/jellis/&lt;/a&gt;.  The slides are in "sa-intro.pdf".  (But it looks like there's some other interesting stuff there too.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Conference Sessions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Friday, April 14 through Sunday, April 16 were the &lt;a href="http://us.pycon.org/2008/conference/"&gt;Conference Days&lt;/a&gt;.  Each day contained keynote talks, scheduled talks, lightning talks, and "open space".  (See the previous link for details.)&lt;br /&gt;&lt;br /&gt;I'll go into detail on the scheduled talks (from all three days) first, and then dump all my notes from the lightning talks.&lt;br /&gt;&lt;br /&gt;The A/V team as begun posting recordings from PyCon 2008 to their YouTube channel: see this &lt;a href="http://pycon.blogspot.com/2008/03/pycon-videos-on-youtube.html"&gt;blog post&lt;/a&gt;.  As of 2008-03-28 they've got 12 up, some from regular sessions and some from lightning talks.  None are from tutorials--I don't know if they intend to post tutorial videos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Guido van Rossum - "Python 3000 and You"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The first technical talk of the conference was fittingly &lt;a href="http://en.wikipedia.org/wiki/Guido_van_Rossum"&gt;Guido&lt;/a&gt;'s talk on Python 3000.  Guido has posted the slides and some advice when porting to Python 3.0 on his &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=227041"&gt;blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I didn't take any notes, but if you're interested in Python 3000, &lt;a href="http://www.python.org/dev/peps/pep-3000/"&gt;PEP 3000&lt;/a&gt; is work reading.  (In addition to the slides.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Brett Cannon - How Import Works&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This was useful information.  You'll find the slides in &lt;a href="http://us.pycon.org/2008/conference/schedule/event/12/"&gt;http://us.pycon.org/2008/conference/schedule/event/12/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;See also &lt;a href="http://www.python.org/dev/peps/pep-0328/"&gt;http://www.python.org/dev/peps/pep-0328/&lt;/a&gt; and &lt;a href="http://www.python.org/dev/peps/pep-0302/"&gt;http://www.python.org/dev/peps/pep-0302/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Dr. Tim Couper - Python references and practical solutions to reference-related problems&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This was an excellent talk.  The video isn't up yet, but I hope it is soon.  (Unfortunately no slides are attached to &lt;a href="http://us.pycon.org/2008/conference/schedule/event/16/"&gt;http://us.pycon.org/2008/conference/schedule/event/16/&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;Here are my (sketchy) notes: &lt;ul&gt;&lt;li&gt; see the getrefcount() function&lt;/li&gt; &lt;li&gt; weakref.ref() &lt;ul&gt;&lt;li&gt; can get the actual reference from a week reference, with "()"&lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; getweakrefcount()&lt;/li&gt; &lt;li&gt; getweakref()&lt;/li&gt; &lt;li&gt; garbage collector will clean up objects not deleted because of a circular reference&lt;/li&gt; &lt;li&gt; can turn off GC if you're sure you'll have no circular references&lt;/li&gt; &lt;li&gt; GC will not clean up objects with a __del__ magic method &lt;ul&gt;&lt;li&gt; but you can get a list of these objects&lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; then I got distracted and got lost when he talked about pickling and weak references as a solution for this? &lt;ul&gt;&lt;li&gt; something interesting about a pattern using __getstate__ and __setstate__ methods&lt;/li&gt; &lt;li&gt; also talked about finalizers&lt;/li&gt;&lt;/ul&gt; &lt;/li&gt;&lt;/ul&gt; &lt;span style="font-size:130%;"&gt;Noah Gift - Using Optparse, Subprocess, and Doctest To Make Agile Unix Utilities&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The presentation and code samples are at &lt;a href="http://code.noahgift.com/pycon2008/"&gt;http://code.noahgift.com/pycon2008/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;TODO - I need to take a look at the &lt;a href="http://blog.doughellmann.com/2007/07/pymotw-subprocess.html"&gt;subprocess module&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Kevin Dangoor - Rich UI Webapps with TurboGears 2 and Dojo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This was a very slick, fast-moving presentation with excellent examples on how to use Dojo.  There was also an example of (bleeding edge, I think) use of Comet to push data from the server to the client.&lt;br /&gt;&lt;br /&gt;I'll want to see this one again when it's available on video.  I haven't been able to find the slides, but Kevin promises to post a screencast version in &lt;a href="http://www.sitepen.com/blog/2008/03/20/pycon-2008-report/"&gt;this blog post&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Adrian Holovaty - The State of Django&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I haven't been able to find the slides, and the video isn't up yet.  But I recommend it (if you're interested in Django).&lt;br /&gt;&lt;br /&gt;Here are my notes: &lt;ul&gt; &lt;li&gt; What's new in the last year: &lt;ul&gt;&lt;li&gt; 0.96 - released March 23, 2007! &lt;/li&gt; &lt;li&gt; Unicode branch - is it still in a separate branch? (I think it was merged to trunk) &lt;/li&gt; &lt;li&gt; auto-escaping in templates &lt;/li&gt; &lt;li&gt; GeoDjango - still a branch &lt;ul&gt; &lt;li&gt; "hope to get it integrated into the trunk soon" &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; Sprints in Sept. &amp;amp; Nov.&lt;/li&gt; &lt;li&gt; 2432 checkins &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; Community stuff: &lt;ul&gt; &lt;li&gt; &lt;a href="http://www.djangosites.org/"&gt;http://www.djangosites.org/&lt;/a&gt; &lt;/li&gt; &lt;li&gt; &lt;a href="http://www.djangosnippets.org/"&gt;http://www.djangosnippets.org/&lt;/a&gt; &lt;/li&gt; &lt;li&gt; &lt;a href="http://djangogigs.com/"&gt;http://djangogigs.com/&lt;/a&gt;&lt;/li&gt; &lt;li&gt; &lt;a href="http://djangopeople.net/"&gt;http://djangopeople.net/&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; What's coming &lt;ul&gt; &lt;li&gt; mostly mature/stable &lt;/li&gt; &lt;li&gt; queryset-refactor to be merged to trunk &lt;ul&gt; &lt;li&gt; includes support for model subclassing&lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; select_related - can now specify args &lt;/li&gt; &lt;li&gt; newforms-admin &lt;ul&gt; &lt;li&gt; admin options defined in separate class; register &lt;/li&gt; &lt;li&gt; has_change_position() method in ModelAdmin classes &lt;/li&gt; &lt;li&gt; can regulate which objects show up in the admin &lt;/li&gt; &lt;li&gt; can have multiple admin sites on the same website&lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; want to add more sophisticated INSTALLED_APPS (using classes) &lt;ul&gt; &lt;li&gt; can define database prefixes &amp;amp; labels (?) &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; model validation &lt;/li&gt; &lt;li&gt; 1.0! &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;Marty Alchin - Django: Under the Hood&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Plenty of useful information that I plan to review again (more slowly).  His slides are at &lt;a href="http://www.slideshare.net/Gulopine/django-under-the-hood/"&gt;http://www.slideshare.net/Gulopine/django-under-the-hood/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Some notes: &lt;ul&gt; &lt;li&gt; the quick review of how metaclasses are used was useful as used a metaclass in the code I wrote during the Django sprint &lt;/li&gt; &lt;li&gt; the signals discussion may be useful to users of Django too&lt;/li&gt; &lt;li&gt; Utilities &lt;ul&gt; &lt;li&gt; functional utilties &lt;ul&gt; &lt;li&gt; several, including turn middleware into per-view decorators &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; text utilities &lt;ul&gt; &lt;li&gt; various &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; "remember, Django is Python, just read the source" &lt;ul&gt; &lt;li&gt; but beware of query.py and related.py &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt;&lt;/ul&gt;See &lt;a href="http://adam.gomaa.us/blog/friday-at-pycon2008/"&gt;this Adam Gomaa blog post&lt;/a&gt; for links to the source files to look at for model metaclasses, the "signalling stuff" and "some neat functional utilities".&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Chris McDonough &amp;amp; Mike Naberezny - Supervisor as a Platform&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This looks like a very useful tool.  I plan on using it very soon.  The slides are in &lt;a href="http://supervisord.org/wp-content/uploads/2008/03/"&gt;http://supervisord.org/wp-content/uploads/2008/03/&lt;/a&gt; and are very good--I don't have anything to add.  (Except I read a rumour somewhere that Guido wrote the original version of this--details are in &lt;a href="http://supervisord.org/contributors/"&gt;http://supervisord.org/contributors/&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Mike Bayer - SQLAlchemy 0.4 and Beyond&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I missed this because it was at the same time as the Supervisor session.  But I heard this was very good.  You'll find the slides at &lt;a href="http://techspot.zzzeek.org/?p=22"&gt;http://techspot.zzzeek.org/?p=22&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Rodney Drenth - Decorated State Machines&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I missed this one too (it was at the same time as the above two sessions).  But I see the slides are at &lt;a href="http://us.pycon.org/2008/conference/schedule/event/43/"&gt;http://us.pycon.org/2008/conference/schedule/event/43/&lt;/a&gt;.  TODO - I haven't looked at them yet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Maciej Fijalkowski - The State of PyPy&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This was interesting.  I learned a bit about PyPy (a subject I know very little about).  I can't find the slides, and the video isn't up yet.&lt;br /&gt;&lt;br /&gt;My notes are very brief: &lt;ul&gt; &lt;li&gt; Currently: &lt;ul&gt;&lt;li&gt; quite compliant 2.4/2.5 &lt;/li&gt; &lt;li&gt; still missing some standard libs &lt;/li&gt; &lt;li&gt; new: ctypes! &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt;&lt;/ul&gt;I vaguely recall an interesting demo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt; James Bennett - Developing Reusable Django Applications &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This was a very good talk that would be worth reviewing by anyone using Django.  The slides are in &lt;a href="http://us.pycon.org/2008/conference/schedule/event/50/"&gt;http://us.pycon.org/2008/conference/schedule/event/50/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'll repeat some of the slides that I noted: &lt;ul&gt; &lt;li&gt; Four big ideas: &lt;ul&gt; &lt;li&gt; do one thing, and do it well (the UNIX philosophy) &lt;/li&gt; &lt;li&gt; don't be afraid of multiple apps &lt;/li&gt; &lt;li&gt; write for flexibility&lt;/li&gt; &lt;li&gt; build to distribute &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; He wrote django-registration &lt;ul&gt; &lt;li&gt; people asked for profiles (in django-registration)--he said no &lt;/li&gt; &lt;li&gt; but then he wrote django-profiles (as a separate app) &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; The Django mindset &lt;ul&gt;&lt;li&gt; application == some bit of functionality &lt;/li&gt; &lt;li&gt; site == several applications &lt;/li&gt; &lt;li&gt; tend to spin off new applications liberally &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; What reusable apps look like &lt;ul&gt; &lt;li&gt; single module directly on Python path &lt;/li&gt; &lt;li&gt; related modules under a package&lt;/li&gt; &lt;li&gt; no project cruft whatsoever &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; Good examples: &lt;ul&gt; &lt;li&gt; django-tagging (Jonathan Buchanan, &lt;a href="http://code.google.com/p/django-tagging/"&gt;http://code.google.com/p/django-tagging/&lt;/a&gt;) &lt;/li&gt; &lt;li&gt; django-atompub (James Tauber, &lt;a href="http://code.google.com/p/django-atompub/"&gt;http://code.google.com/p/django-atompub/&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; More information: &lt;ul&gt; &lt;li&gt; django-hotclub (&lt;a href="http://groups.google.com/group/django-hotclub/"&gt;http://groups.google.com/group/django-hotclub/&lt;/a&gt;) &lt;/li&gt; &lt;li&gt; Jannis Leidel’s django-packages (&lt;a href="http://code.google.com/p/django-reusableapps/"&gt;http://code.google.com/p/django-reusableapps/&lt;/a&gt;) &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;Alex Martelli - Don't call us, we'll call you: callback patterns and idioms in Python&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;This was at the same time as the Developing Reusable Django Applications talk, so I missed it.  But the slides are in &lt;a href="http://www.aleax.it/pyc08_cback.pdf"&gt;http://www.aleax.it/pyc08_cback.pdf&lt;/a&gt;.   TODO - I haven't looked at them yet, but I've read good things about this talk.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt; Brandon Rhodes - Using Grok to Walk Like a Duck&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;You'll find the slides and example source code at &lt;a href="http://rhodesmill.org/brandon/adapters/"&gt;http://rhodesmill.org/brandon/adapters/&lt;/a&gt;.  (And this one is on &lt;a href="http://www.youtube.com/watch?v=UF77e2TeeQo"&gt;YouTube&lt;/a&gt;.  The title is misleading--this was really primarily about the Adapter pattern and the Zope Interface class.  I left wishing he provided some examples of using Grok.&lt;br /&gt;&lt;br /&gt;I got a little lost when he gets into zope.interface.Interface.  TODO - The best way to understand this would be a play around with it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt; Steven Wilcox - The Power of Django Admin (Even For Non-Django Projects)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;The "slides" (actually a paper) are at &lt;a href="http://devpicayune.com/pycon2008/django_admin.html"&gt;http://devpicayune.com/pycon2008/django_admin.html&lt;/a&gt;.  This doesn't look familiar, so I must have been busy with something else at the time--though I can't recall what.  Perhaps that presentation wasn't as compelling as the material deserved.  TODO - This does appear to be worth reading.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Brian Dorsey, Maciej Fijalkowski - py.test: Towards Interactive, Distributed and Rapid Testing&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;This was a very good presentation that I would recommend watching when it's available on YouTube.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://codespeak.net/py/dist/test.html"&gt;http://codespeak.net/py/dist/test.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here are my notes: &lt;ul&gt; &lt;li&gt; tests for py.test are almost identical to nose &lt;/li&gt; &lt;li&gt; tab completion in bash after -k flag &lt;strong&gt;slick&lt;/strong&gt;&lt;/li&gt; &lt;li&gt; I missed the test reporting page thing, but heard it was slick - and I believe that's one thing that distinguishes py.test from nose &lt;/li&gt; &lt;li&gt; 1.0 soon &lt;ul&gt; &lt;li&gt; more plug-in architecture &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; yes, there is a tool for converting unittest tests to py.test tests &lt;ul&gt; &lt;li&gt; you can convert tests, or just run them without (permanently) converting them &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt; &lt;li&gt; what does py.test do that nose doesn't? &lt;ul&gt; &lt;li&gt; the introspection magic &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; py.test.raises(Exception, stuff, arg1, arg2) &lt;/li&gt; &lt;li&gt; TODO check out py.execnet (&lt;a href="http://codespeak.net/py/dist/execnet.html"&gt;http://codespeak.net/py/dist/execnet.html&lt;/a&gt; - "A new view on distributed execution")&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;Jim Baker - More Iterators in Action&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;My notes say the slides are at &lt;a href="http://zyasoft.com/"&gt;http://zyasoft.com/&lt;/a&gt;, but that page strangely describes Zyasoft consulting services and software development but provides no links or contact information.  The slides are attached to &lt;a href="http://us.pycon.org/2008/conference/schedule/event/75/"&gt;http://us.pycon.org/2008/conference/schedule/event/75/&lt;/a&gt; though.&lt;br /&gt;&lt;br /&gt;Here are my notes: &lt;ul&gt; &lt;li&gt; LINQ - Language INtegrated Query - &lt;a href="http://en.wikipedia.org/wiki/Language_Integrated_Query"&gt;http://en.wikipedia.org/wiki/Language_Integrated_Query&lt;/a&gt;&lt;/li&gt; &lt;li&gt; "The solution to integration in Python is naming (more or less)."  [I may have got that wrong.] &lt;/li&gt; &lt;li&gt; collections.namedtuple - new in 2.6 &lt;/li&gt; &lt;li&gt; see also cookbook recipe &lt;span class="twikiNewLink"&gt;NamedTuple&lt;a href="http://www.blogger.com/twiki/bin/edit/Software/NamedTuple?topicparent=Software.DarylSpitzersPyCon2008Notes;nowysiwyg=1" rel="nofollow" title="Create this topic"&gt;?&lt;/a&gt;&lt;/span&gt;  - &lt;a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/303439"&gt;http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/303439&lt;/a&gt; &lt;/li&gt; &lt;li&gt; TODO look up tee() - &lt;a href="http://docs.python.org/lib/itertools-functions.html"&gt;http://docs.python.org/lib/itertools-functions.html&lt;/a&gt;&lt;/li&gt; &lt;li&gt; operator.itemgetter() - &lt;a href="http://docs.python.org/lib/module-operator.html"&gt;http://docs.python.org/lib/module-operator.html&lt;/a&gt; &lt;/li&gt; &lt;li&gt; defaultdict - &lt;a href="http://docs.python.org/lib/defaultdict-objects.html"&gt;http://docs.python.org/lib/defaultdict-objects.html&lt;/a&gt; &lt;/li&gt; &lt;li&gt; Recursive Generators &lt;ul&gt; &lt;li&gt; are they practical?  sometimes, but they're fun &lt;/li&gt; &lt;li&gt; see cookbook recipe 190465 - &lt;a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/190465"&gt;http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/190465&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt; Raymond Hettinger - Core Python Containers - Under the Hood&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;An excellent presentation that I will most definitely watch again when it's available on YouTube.  I haven't been able to find the slides.&lt;br /&gt;&lt;br /&gt;I didn't take very good notes: &lt;ul&gt; &lt;li&gt; &lt;a href="http://svn.python.org/view/python/trunk/Include/listobject.h?rev=59564&amp;amp;view=markup"&gt;python/trunk/Include/listobject.h&lt;/a&gt;&lt;/li&gt; &lt;li&gt; &lt;a href="http://svn.python.org/view/python/trunk/Objects/listobject.c?rev=61049&amp;amp;view=markup"&gt;python/trunk/Objects/listobject.c&lt;/a&gt; &lt;/li&gt; &lt;li&gt; collections.deque() is optimized for appends and pops at both ends, but it is slower for indexed access &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;Collin Winter - 2to3: Translating Python 2 to Python 3&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;I haven't been able to find the slides.&lt;br /&gt;&lt;br /&gt;My notes are very brief: &lt;ul&gt;&lt;li&gt; &lt;a href="mailto:collinw@gmail.com"&gt;collinw@gmail.com&lt;/a&gt; &lt;/li&gt; &lt;li&gt; workflow: &lt;ul&gt; &lt;li&gt; maintain in 2.x &lt;/li&gt; &lt;li&gt; fix 2.6 -3 warnings &lt;/li&gt; &lt;li&gt; run 2to3 &lt;/li&gt; &lt;li&gt; test suite!&lt;/li&gt; &lt;li&gt; release 3.x version &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:180%;"&gt;Lightning Talks&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There were three &lt;a href="http://us.pycon.org/2008/conference/lightning/" target="_top"&gt;Lightning Talk&lt;/a&gt; sessions, after the scheduled talks on Friday, Saturday, and Sunday.  Here are my notes.  (I marked my favorites with *.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;a name="Friday_April_14_"&gt;&lt;/a&gt; Friday (April 14) &lt;/span&gt; &lt;ul&gt; &lt;li&gt; *&lt;a href="http://daemonize.sourceforge.net/"&gt;How to write a daemon in Python&lt;/a&gt; &lt;/li&gt; &lt;li&gt; &lt;a href="http://code.google.com/p/nose-trestle/"&gt;Trestle&lt;/a&gt; - a nose plugin for writing testable documentation for web apps (or shell commands) &lt;/li&gt; &lt;li&gt; *&lt;a href="http://www.noonhat.com/lunch/"&gt;Noonhat&lt;/a&gt; - "Changing the world through lunch"&lt;/li&gt; &lt;li&gt; *&lt;a href="http://www.saturdayhouse.org/"&gt;Seattle Saturday House&lt;/a&gt; &lt;/li&gt; &lt;li&gt; &lt;a href="http://developer.facebook.com/thrift/"&gt;Thrift lightweight RPC mechanism&lt;/a&gt; &lt;/li&gt; &lt;li&gt; *&lt;a href="http://tinypy.org/"&gt;tinypy&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;&lt;a name="Saturday_April_15_"&gt;&lt;/a&gt; Saturday (April 15) &lt;/span&gt; &lt;ul&gt; &lt;li&gt; &lt;a href="http://bazaar-vcs.org/"&gt;Bazaar&lt;/a&gt; - "if you can run Python 2.4, then you can run Bazaar" &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;&lt;a name="Sunday_April_16_"&gt;&lt;/a&gt; Sunday (April 16) &lt;/span&gt; &lt;ul&gt; &lt;li&gt; Wesley Chun - &lt;a href="http://www.nearbynow.com/"&gt;http://www.nearbynow.com/&lt;/a&gt; &lt;ul&gt;&lt;li&gt; Text a &lt;a href="http://www.nearbynow.com/sms#mallcodes"&gt;"mall code"&lt;/a&gt; to 632729 (NEARBY) to search products, brands and sales &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; &lt;a href="http://www.zedshaw.com/blog/"&gt;Zed Shaw&lt;/a&gt; &lt;/li&gt; &lt;li&gt; *&lt;a href="http://www.snpedia.com/"&gt;SNPedia&lt;/a&gt; - &lt;a href="http://www.snpedia.com/index.php?title=SNP"&gt;"SNP"&lt;/a&gt; is pronounced "SNIP"&lt;/li&gt; &lt;li&gt; *&lt;a href="http://www.dalkescientific.com/Python/python4ply.html"&gt;python4ply&lt;/a&gt; - a Python parser for the Python language &lt;/li&gt; &lt;li&gt; Jython - 2 use cases: &lt;ul&gt; &lt;li&gt; script Java libraries from Python &lt;/li&gt; &lt;li&gt; "maintain huge collapsing J2EE  app"&lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; &lt;a href="http://bug.gd/"&gt;bug.gd&lt;/a&gt; - "...submit an error message you've seen and we'll try to find other people who've seen the same error..." &lt;ul&gt; &lt;li&gt; see also &lt;a href="http://blog.bug.gd/2008/03/29/error_help-for-python-hackers/"&gt;error_help() for Python hackers&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; *&lt;a href="http://exogen.case.edu/projects/geopy/"&gt;geopy&lt;/a&gt; - a geocoding toolbox for Python&lt;/li&gt; &lt;li&gt; from LJWorld.com: &lt;ul&gt; &lt;li&gt; &lt;a href="http://www2.ljworld.com/data/crime/ku/"&gt;Crimes reported in KU residences&lt;/a&gt; &lt;/li&gt; &lt;li&gt; &lt;a href="http://www2.ljworld.com/foreclosures/sheriffs_sale/"&gt;Foreclosures: Sheriff's Sales&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt; &lt;li&gt; &lt;a href="http://elixir.ematia.de/trac/wiki"&gt;Elixir&lt;/a&gt; - a declarative layer on top of the SQLAlchemy library&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;UPDATE&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt; (2008-04-03)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As I read through blog posts on PyCon, I'll add links here.&lt;br /&gt;&lt;br /&gt;To start, I recommend &lt;a href="http://jjinux.blogspot.com/"&gt;-JJ&lt;/a&gt;'s posts on:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://jjinux.blogspot.com/2008/03/pycon-sqlalchemy-04-and-beyond.html"&gt;SQLAlchemy 0.4 and Beyond&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://jjinux.blogspot.com/2008/03/pycon-managing-complexity-and-testing.html"&gt;Managing Complexity (and Testing)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://jjinux.blogspot.com/2008/03/pycon-consuming-html.html"&gt;Consuming HTML&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://jjinux.blogspot.com/2008/03/pycon-core-python-containers-under-hood.html"&gt;Core Python Containers--Under the Hood&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Did I miss any?  (You just may want to scan &lt;a href="http://jjinux.blogspot.com/search/label/pycon2008"&gt;all his PyCon 2008 posts&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;UPDATE&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt; (2008-04-11)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Yesterday evening I presented my "PyCon 2008 Notes" to &lt;a href="http://baypiggies.net/"&gt;BayPIGgies&lt;/a&gt;, in slide form.  The slides don't have any of the links above, and I stripped out much of my notes, but if you really want them you'll find them at &lt;a href="http://www.spitzer.us/daryl/baypiggies/pycon_2008_notes/"&gt;http://www.spitzer.us/daryl/baypiggies/pycon_2008_notes/&lt;/a&gt; (exported to HTML from Keynote) or &lt;a href="http://www.spitzer.us/daryl/baypiggies/pycon_2008_notes/pycon_2008_notes.pdf"&gt;http://www.spitzer.us/daryl/baypiggies/pycon_2008_notes/pycon_2008_notes.pdf&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-826684573761588695?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/j-cPNmeT8kg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/826684573761588695/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=826684573761588695" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/826684573761588695?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/826684573761588695?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/j-cPNmeT8kg/pycon-2008-notes.html" title="PyCon 2008 Notes" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://pypap.blogspot.com/2008/04/pycon-2008-notes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4ARH46fip7ImA9WxZVFUk.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-2696607398493632000</id><published>2008-03-26T09:15:00.000-07:00</published><updated>2008-03-26T09:29:05.016-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-26T09:29:05.016-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="_getframe" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;Python 3.0&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="PEPs" /><category scheme="http://www.blogger.com/atom/ns#" term="TODO" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;Secrets of the Framework Creators&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;string interpolation&quot;" /><title>String Interpolation</title><content type="html">One of the prerequisites for recipe #1 ("Ruby-style string interpolation") from the &lt;a href="http://pypap.blogspot.com/2008/03/frame-hacks.html"&gt;Frame Hacks&lt;/a&gt; section of the &lt;a href="http://pypap.blogspot.com/2008/03/secrets-of-secrets-of-framework.html"&gt;"Secrets of the Framework Creators"&lt;/a&gt; PyCon tutorial is the &lt;a href="http://docs.python.org/lib/node40.html"&gt;string.Template&lt;/a&gt; class.  Before I took the tutorial I was vaguely aware of the string.Template class, but I don't think I've ever used it.&lt;br /&gt;&lt;br /&gt;I'm going to consider using it though.  There are probably plenty of cases where it would be more readable than using the &lt;a href="http://docs.python.org/lib/typesseq-strings.html"&gt;% operator&lt;/a&gt;--I can recall a couple times in code I wrote very recently.&lt;br /&gt;&lt;br /&gt;In step 1 of Frame Hacks recipe #1, Feihong and Kumar how how one can write a function that wraps string.Template and the substitute method so the mapping argument (and optional keyword arguments) don't need to be provided.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SPOILER WARNING&lt;/span&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;interpolate&lt;/span&gt;(templateStr):&lt;br /&gt;  &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;sys&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;from&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;string&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; Template&lt;br /&gt;  t &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; Template(templateStr)&lt;br /&gt;  frame &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; sys&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;_getframe(&lt;span style="color: rgb(102, 102, 102);"&gt;1&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;return&lt;/span&gt; t&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;substitute(&lt;span style="color: rgb(102, 102, 102);"&gt;**&lt;/span&gt;frame&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;f_locals)&lt;br /&gt;&lt;br /&gt;name &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'Feihong'&lt;/span&gt;&lt;br /&gt;place &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'Chicago'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;print&lt;/span&gt; interpolate(&lt;span style="color: rgb(186, 33, 33);"&gt;"My name is ${name}. I work in ${place}."&lt;/span&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;Here's what it could look like without the sys._getframe() call:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;interpolate&lt;/span&gt;(templateStr, &lt;span style="color: #666666"&gt;**&lt;/span&gt;kws):&lt;br /&gt;    &lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;string&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; Template&lt;br /&gt;    &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; Template(templateStr)&lt;span style="color: #666666"&gt;.&lt;/span&gt;substitute(kws)&lt;br /&gt;&lt;br /&gt;name &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;Feihong&amp;#39;&lt;/span&gt;&lt;br /&gt;place &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;Chicago&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; interpolate(&lt;span style="color: #BA2121"&gt;&amp;quot;My name is ${name}. I work in ${place}.&amp;quot;&lt;/span&gt;,&lt;br /&gt;                  name&lt;span style="color: #666666"&gt;=&lt;/span&gt;name, place&lt;span style="color: #666666"&gt;=&lt;/span&gt;place)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;I guess I could argue that the latter is more &lt;a href="http://www.python.org/dev/peps/pep-0020/"&gt;explicit&lt;/a&gt;, but perhaps the former is explicit enough.  I guess I'll be the judge of that (for myself) the next time I write (or am ready to refactor) an ugly string using the % operator.  I'll let you know if I decide to add the interpolate function to my utilities module.&lt;br /&gt;&lt;br /&gt;The solution for step 2 of recipe #1 (which I showed a partial solution for when I wrote about Frame Hacks) allows for expressions in the template strings.  I don't think I've run across a use case for that, but I'll write about it if I do.&lt;br /&gt;&lt;br /&gt;I should also mention that Python 3.0 will include a new (third) method of string interpolation, the format method to be added to the built-in string class.  (There's more to it than just that.  You can read all about it in &lt;a href="http://www.python.org/dev/peps/pep-3101/"&gt;PEP 3101&lt;/a&gt;.  And if--like me--you don't know just what a PEP is, I recommend reading the "PEPs" section hear the top of the description of &lt;a href="http://www.python.org/dev/process/"&gt;Python's Development Process&lt;/a&gt;.  And you'll find plenty more detail in &lt;a href="http://www.python.org/dev/peps/pep-0001/"&gt;PEP 1&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;The above example would look like this using the new format method:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;name = 'Feihong'&lt;br /&gt;place = 'Chicago'&lt;br /&gt;print "My name is {name}. I work in {place}.".format(name=name, place=place)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;There doesn't seem to be a spec for the format method yet, so it's not clear whether one could wrap it and use sys._getframe().  I don't know if that's an argument for avoiding using it now though.  (I don't see any reason why the interpolate() function above wouldn't work in Python 3.0.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;TODO&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I haven't installed the latest Python 3.0 alpha yet.  I should make time to do so and play with the above.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-2696607398493632000?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/JbcqjLSwoGw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/2696607398493632000/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=2696607398493632000" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/2696607398493632000?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/2696607398493632000?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/JbcqjLSwoGw/string-interpolation.html" title="String Interpolation" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://pypap.blogspot.com/2008/03/string-interpolation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4NRns8fCp7ImA9WxJTGU4.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-4937389978837997171</id><published>2008-03-16T09:43:00.000-07:00</published><updated>2009-04-28T09:43:17.574-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-28T09:43:17.574-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Pygments" /><category scheme="http://www.blogger.com/atom/ns#" term="highlight" /><category scheme="http://www.blogger.com/atom/ns#" term="pbcopy" /><title>Pygments</title><content type="html">I thought I'd write a quick post on how I highlighted the Python code in my &lt;a href="http://pypap.blogspot.com/2008/03/frame-hacks.html"&gt;previous post&lt;/a&gt;.  I used &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt;, which (though I've only had limited experience with it) appears to truly be a "top quality product".  It was &lt;a href="http://pygments.org/docs/installation/"&gt;easy to install&lt;/a&gt; with easy_install.&lt;br /&gt;&lt;br /&gt;Because I'm pasting the highlighted code into Blogger, I can't use the CSS it generates by default, so I use the &lt;a href="http://pygments.org/docs/formatters/"&gt;"noclasses" option&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ pygmentize -f html -O noclasses -o file.html file.py&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And then I can paste the contents of the html file into my Blogger post's HTML.&lt;br /&gt;&lt;br /&gt;Actually, on Mac OS X I can save a step using:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ pygmentize -f html -O noclasses file.py | pbcopy&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And then paste directly into Blogger.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update&lt;/span&gt;: the following command-line allows me to pygmentize the Python code in the clipboard (without having to create a file for it):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ pbpaste |  pygmentize -f html -O noclasses -l python | pbcopy&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;span style="font-weight: bold;"&gt;Another Update&lt;/span&gt;: it occurred to me I could use the above (updated) command-line in TextExpander (see &lt;a href="http://yacitus.com/2009/03/textexpander-snippet-to-paste-quoted.html"&gt;A TextExpander snippet to paste quoted text&lt;/a&gt; and &lt;a href="http://yacitus.com/2009/03/trim-textexpander-snippet-that-works.html"&gt;A tr.im TextExpander snippet that works for me&lt;/a&gt;) to create a snippet that pastes a "Pygmentized"  version of the Python code in the clipboard:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GBuM4RB_ljE/Sfcx9CeapCI/AAAAAAAAAHY/fjOIFrcavuU/s1600-h/Picture+1.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 400px; height: 288px;" src="http://4.bp.blogspot.com/_GBuM4RB_ljE/Sfcx9CeapCI/AAAAAAAAAHY/fjOIFrcavuU/s400/Picture+1.png" alt="" id="BLOGGER_PHOTO_ID_5329783608722498594" 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/6716655737319338935-4937389978837997171?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/yXZyhRxjpqM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/4937389978837997171/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=4937389978837997171" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/4937389978837997171?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/4937389978837997171?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/yXZyhRxjpqM/pygments.html" title="Pygments" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_GBuM4RB_ljE/Sfcx9CeapCI/AAAAAAAAAHY/fjOIFrcavuU/s72-c/Picture+1.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://pypap.blogspot.com/2008/03/pygments.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0EASX87fip7ImA9WxZVFUk.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-3029311903019496636</id><published>2008-03-16T08:21:00.000-07:00</published><updated>2008-03-26T07:27:28.106-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-26T07:27:28.106-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="_getframe" /><category scheme="http://www.blogger.com/atom/ns#" term="TODO" /><category scheme="http://www.blogger.com/atom/ns#" term="&quot;Secrets of the Framework Creators&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="pycon" /><title>Frame Hacks</title><content type="html">Someone (I forget who--I've listened to so many smart people here at &lt;a href="http://us.pycon.org/2008/about/"&gt;PyCon&lt;/a&gt;) said yesterday that Python treats us like adults--if we want go "off-road" we can.  (Other languages try to protect programmers from themselves and others.  With Python we need to write tests to get that protection.  Not that statically-typed languages with protected attributes and methods make testing unnecessary.  But that's a subject for another time.)  But until I took the &lt;a href="http://us.pycon.org/2008/tutorials/FrameworksHsu/"&gt;"Secrets of the Framework Creators"&lt;/a&gt; tutorial at PyCon, I had no idea just how far into the wilderness one could go.&lt;br /&gt;&lt;br /&gt;As Leihong and Kumar explain in the getting started chapter of the frame hacks section, one can call &lt;a href="http://docs.python.org/lib/module-sys.html"&gt;sys._getframe()&lt;/a&gt; to get the "frame" of the calling functions, all the way to the bottom of the call stack.  This made immediate sense to me, since one of the first bits of real code I wrote when I started at Altera did a stack trace on the Nios (Classic) processor.  (That was tricky, since the original Nios used register windows--but I'd better stop before I go down a rat hole.)&lt;br /&gt;&lt;br /&gt;As I wrote previously, I'm working my way through the tutorial again on my own to give myself a chance to get to the point where I can use the techniques (rather than just understand them when I see them used).&lt;br /&gt;&lt;br /&gt;I worked my way through the three steps of the first frame hacks recipe without a problem, though (to be honest), I've never used the string.Template class and the re.finditer function before (though they did seem familiar, so I guess I've read about them).  I don't think I've used the yield statement either, though I'm eager to now that I've been immersed in generators and co-routines in the &lt;a href="http://us.pycon.org/2008/tutorials/Generators/"&gt;"Generator Tricks for Systems Programmers"&lt;/a&gt; tutorial (which was also excellent and which I'll write about later).&lt;br /&gt;&lt;br /&gt;But I noticed that the code in the third step (step 2) of that recipe actually works without using sys._getframe():&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SPOILER WARNING&lt;/span&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;sys&lt;/span&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;re&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;from&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;string&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; Template&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;getchunks&lt;/span&gt;(s):&lt;br /&gt;   matches &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;list&lt;/span&gt;(re&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;finditer(&lt;span style="color: rgb(186, 33, 33);"&gt;r"\$\{(.*?)\}"&lt;/span&gt;, s))&lt;br /&gt;&lt;br /&gt;   &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;if&lt;/span&gt; matches:&lt;br /&gt;       pos &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102);"&gt;0&lt;/span&gt;&lt;br /&gt;       &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;for&lt;/span&gt; match &lt;span style="color: rgb(170, 34, 255); font-weight: bold;"&gt;in&lt;/span&gt; matches:&lt;br /&gt;           &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;yield&lt;/span&gt; s[pos : match&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;start()]&lt;br /&gt;           &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;yield&lt;/span&gt; [match&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;group(&lt;span style="color: rgb(102, 102, 102);"&gt;1&lt;/span&gt;)]&lt;br /&gt;           pos &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; match&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;end()&lt;br /&gt;       &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;yield&lt;/span&gt; s[pos:]&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;interpolate&lt;/span&gt;(templateStr):&lt;br /&gt;   result &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;''&lt;/span&gt;&lt;br /&gt;   &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;for&lt;/span&gt; chunk &lt;span style="color: rgb(170, 34, 255); font-weight: bold;"&gt;in&lt;/span&gt; getchunks(templateStr):&lt;br /&gt;       &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;isinstance&lt;/span&gt;(chunk, &lt;span style="color: rgb(0, 128, 0);"&gt;list&lt;/span&gt;):&lt;br /&gt;           result &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;''&lt;/span&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;join((result, &lt;span style="color: rgb(0, 128, 0);"&gt;str&lt;/span&gt;(&lt;span style="color: rgb(0, 128, 0);"&gt;eval&lt;/span&gt;(chunk[&lt;span style="color: rgb(102, 102, 102);"&gt;0&lt;/span&gt;]))))&lt;br /&gt;       &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;else&lt;/span&gt;:&lt;br /&gt;           result &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;''&lt;/span&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;join((result, chunk))&lt;br /&gt;   &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;return&lt;/span&gt; result&lt;br /&gt;&lt;br /&gt;name &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'Guido van Rossum'&lt;/span&gt;&lt;br /&gt;places &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'Amsterdam'&lt;/span&gt;, &lt;span style="color: rgb(186, 33, 33);"&gt;'LA'&lt;/span&gt;, &lt;span style="color: rgb(186, 33, 33);"&gt;'New York'&lt;/span&gt;, &lt;span style="color: rgb(186, 33, 33);"&gt;'DC'&lt;/span&gt;, &lt;span style="color: rgb(186, 33, 33);"&gt;'Chicago'&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt;s &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;"""My name is ${'Mr. ' + name + ', Esquire'}.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(186, 33, 33);"&gt;I have visited the following cities:  ${', '.join(places)}.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(186, 33, 33);"&gt;"""&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;print&lt;/span&gt; interpolate(s)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;That's because the eval in the interpolate function can find "name" and "places" in the global namespace.  I can't recall if Leihong or Kumar noticed this in the tutorial, but I imagine they intended something like this:&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;sys&lt;/span&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;re&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;from&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;string&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;import&lt;/span&gt; Template&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;getchunks&lt;/span&gt;(s):&lt;br /&gt; matches &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;list&lt;/span&gt;(re&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;finditer(&lt;span style="color: rgb(186, 33, 33);"&gt;r"\$\{(.*?)\}"&lt;/span&gt;, s))&lt;br /&gt;&lt;br /&gt; &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;if&lt;/span&gt; matches:&lt;br /&gt;     pos &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102);"&gt;0&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;for&lt;/span&gt; match &lt;span style="color: rgb(170, 34, 255); font-weight: bold;"&gt;in&lt;/span&gt; matches:&lt;br /&gt;         &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;yield&lt;/span&gt; s[pos : match&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;start()]&lt;br /&gt;         &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;yield&lt;/span&gt; [match&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;group(&lt;span style="color: rgb(102, 102, 102);"&gt;1&lt;/span&gt;)]&lt;br /&gt;         pos &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; match&lt;span style="color: rgb(102, 102, 102);"&gt;.&lt;/span&gt;end()&lt;br /&gt;     &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;yield&lt;/span&gt; s[pos:]&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;interpolate&lt;/span&gt;(templateStr):&lt;br /&gt; &lt;span style="color: rgb(186, 33, 33); font-style: italic;"&gt;"""Implement this function"""&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;main&lt;/span&gt;():&lt;br /&gt; name &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'Guido van Rossum'&lt;/span&gt;&lt;br /&gt; places &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'Amsterdam'&lt;/span&gt;, &lt;span style="color: rgb(186, 33, 33);"&gt;'LA'&lt;/span&gt;, &lt;span style="color: rgb(186, 33, 33);"&gt;'New York'&lt;/span&gt;, &lt;span style="color: rgb(186, 33, 33);"&gt;'DC'&lt;/span&gt;, &lt;span style="color: rgb(186, 33, 33);"&gt;'Chicago'&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt; s &lt;span style="color: rgb(102, 102, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;"""My name is ${'Mr. ' + name + ', Esquire'}.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(186, 33, 33);"&gt;    I have visited the following cities:  ${', '.join(places)}.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(186, 33, 33);"&gt;    """&lt;/span&gt;&lt;br /&gt; &lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;print&lt;/span&gt; interpolate(s)&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 128, 0); font-weight: bold;"&gt;if&lt;/span&gt; __name__ &lt;span style="color: rgb(102, 102, 102);"&gt;==&lt;/span&gt; &lt;span style="color: rgb(186, 33, 33);"&gt;'__main__'&lt;/span&gt;:&lt;br /&gt; main()&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;You'll need to use sys._getframe() in interpolate() to get this to work.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;TODO&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I should look into &lt;a href="http://peak.telecommunity.com/DevCenter/Trellis"&gt;Trellis&lt;/a&gt;, &lt;a href="http://elixir.ematia.de/trac/wiki"&gt;Elixer&lt;/a&gt; and &lt;a href="http://codespeak.net/lxml/"&gt;lxml&lt;/a&gt;, which were used in the tutorial to give use cases for frame hacks.&lt;br /&gt;&lt;br /&gt;And before I move on to the next section of the "Secrets of the Framework Creators" tutorial, I should describe the string.Template class and the re.finditer function.  Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-3029311903019496636?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/Q4alTb55FwE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/3029311903019496636/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=3029311903019496636" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/3029311903019496636?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/3029311903019496636?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/Q4alTb55FwE/frame-hacks.html" title="Frame Hacks" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://pypap.blogspot.com/2008/03/frame-hacks.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4HRn49fSp7ImA9WxZWFko.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-1585739225990539990</id><published>2008-03-16T06:54:00.000-07:00</published><updated>2008-03-16T07:15:37.065-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-16T07:15:37.065-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="&quot;Secrets of the Framework Creators&quot;" /><category scheme="http://www.blogger.com/atom/ns#" term="tutorial" /><category scheme="http://www.blogger.com/atom/ns#" term="pycon" /><category scheme="http://www.blogger.com/atom/ns#" term="pdb" /><title>Secrets of the "Secrets of the Framework Creators"</title><content type="html">As I &lt;a href="http://yacitus.blogspot.com/2008/02/im-going-to-pycon.html"&gt;wrote in my personal blog&lt;/a&gt;, I'm at &lt;a href="http://us.pycon.org/2008/about/"&gt;PyCon&lt;/a&gt;.  There has already been plenty of good fodder for a handful of blog posts.  But I'll start at the beginning and work my way through the conference chronologically.&lt;br /&gt;&lt;br /&gt;Thursday was tutorial day.  The first was &lt;a href="http://us.pycon.org/2008/tutorials/FrameworksHsu/"&gt;"Secrets of the Framework Creators"&lt;/a&gt;, presented by &lt;a href="http://feihonghsu.blogspot.com/"&gt;Feihong Hsu&lt;/a&gt; and &lt;a href="http://farmdev.com/"&gt;Kumar McMillan&lt;/a&gt;.  I've taken quite a few conference tutorials in the past (though this was my first at PyCon), but this must be the best-prepared.  Leihong and Kumar put together a web-site and had the foresight to make it available for download instead of hosting it (which was good thinking since the conference Wi-Fi worked only periodically until yesterday).  You can download it yourself from the &lt;a href="http://groups.google.com/group/secrets-of-the-framework-creators/files"&gt;Google Group&lt;/a&gt; they set up.  (I asked their permission to blog about this.  They also said they'd accept new members of the group that didn't take the tutorial.)&lt;br /&gt;&lt;br /&gt;As you can see, they start (in index.html) by introducing themselves, and the tutorial.  Then there are links to the four sections covered: Frame Hacks, Decorators, Metaclasses and Magic Methods.  And finally on the main page is an introduction to PDB, should we need it.  I didn't, since I have had to teach myself PDB and use it once or twice--because I was sloppy and didn't write unit tests.  And I had already seen the breakpoint trick in one of &lt;a href="http://jjinux.blogspot.com/2007/08/python-coding-in-debugger-for-beginners.html"&gt;-JJ's posts&lt;/a&gt;.  But I didn't realize that when in PDB, you're in a "custom" Python interactive session.  It's nice to know that anything I'm used to doing there should work in PDB.&lt;br /&gt;&lt;br /&gt;In each of the four sections is a getting started section that introduces the concept, some (much appreciated) use cases that give examples of where it's been used, and a couple recipes to give you practice using each technique.  They even think to list the prerequisite knowledge required for each recipe (with a link to documentation).  Each recipe has hidden hints to help us along, and the solution if you're completely stuck.  And they conclude each section with "caveats": warnings about the trade-offs and limitations of the technique.&lt;br /&gt;&lt;br /&gt;It must have taken them quite a bit of time to put this together.  (It's taking me a while just to describe it.)&lt;br /&gt;&lt;br /&gt;They had time in the tutorial to go through one recipe in each section, and then we voted and used the time remaining to go through the second recipe in (if I recall correctly) Metaclasses and Frame Hacks.&lt;br /&gt;&lt;br /&gt;I'm now working my way through the material again, so it (hopefully) sinks in.  My next couple posts will be on what I learned in the frame hacks section.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-1585739225990539990?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/xubiutT1sIA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/1585739225990539990/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=1585739225990539990" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/1585739225990539990?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/1585739225990539990?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/xubiutT1sIA/secrets-of-secrets-of-framework.html" title="Secrets of the &quot;Secrets of the Framework Creators&quot;" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://pypap.blogspot.com/2008/03/secrets-of-secrets-of-framework.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4MRHsyfyp7ImA9WxZWFko.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-566204787336709595</id><published>2008-03-16T06:40:00.000-07:00</published><updated>2008-03-16T06:43:05.597-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-16T06:43:05.597-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="metapost" /><title>I'm going to call it PyPap</title><content type="html">I didn't intend for three months to go by before I finished my first "real" post to my new blog.  And this isn't going to be a "real" post either.  I just can't allow any more time to go by, and have any hope of this being a "real" blog.&lt;br /&gt;&lt;br /&gt;The problem is I set my sights too high.  I just don't have enough Python experience to write authoritative posts on Python Patterns and Practices.  I aspire to get there someday, and perhaps this blog will help me get there faster.  But in the meantime, I'm going to rename the blog from its URL: "PyPap".  That feels much less pretentious to me, and should reduce my own expectations for future posts.&lt;br /&gt;&lt;br /&gt;So for any of you out there that stumble upon this, hopefully what follows are semi-regular posts on bits of Python that are new to me.  They may not be patterns, or practices, but hopefully some of them prove to be useful to you too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-566204787336709595?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/FmFv8x5U9mo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/566204787336709595/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=566204787336709595" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/566204787336709595?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/566204787336709595?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/FmFv8x5U9mo/im-going-to-call-it-pypap.html" title="I'm going to call it PyPap" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://pypap.blogspot.com/2008/03/im-going-to-call-it-pypap.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cESXwycCp7ImA9WxZWFko.&quot;"><id>tag:blogger.com,1999:blog-6716655737319338935.post-868175831631452708</id><published>2007-12-17T06:50:00.000-08:00</published><updated>2008-03-16T06:43:28.298-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-16T06:43:28.298-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="metapost" /><title>My Second Blog</title><content type="html">I finished listening to Scott Bain's "Emergent Design: The Evolutionary Nature of Professional Software Development" audio-only webinar (which I recommend--I got it through their &lt;a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=159242053"&gt;podcast&lt;/a&gt; on iTunes--I was unable to find it on NetObjective's &lt;a href="http://www.netobjectives.com/resources"&gt;website&lt;/a&gt;).  I was inspired by that and &lt;a href="http://blog.doughellmann.com/"&gt;Doug Hellmann's blog&lt;/a&gt; (especially his &lt;a href="http://blog.doughellmann.com/search/label/PyMOTW"&gt;PyMOTW&lt;/a&gt; posts, about which we recently had a very brief correspondence) to start this blog.&lt;br /&gt;&lt;br /&gt;I'm going to try to write here about Python practices and design patterns in Python as regularly as I can.  (I don't know if I'll be able to do so every week, but I'll try.)  As Doug Hellmann wrote to me (about PyMOTW):&lt;br /&gt;&lt;blockquote&gt;I really did start that project as a way to make myself write on a regular basis and to learn...&lt;/blockquote&gt;My intentions for this blog are the same.&lt;br /&gt;&lt;br /&gt;(BTW, my other blog is at &lt;a href="http://yacitus.blogspot.com/"&gt;yacitus.blogspot.com&lt;/a&gt;.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6716655737319338935-868175831631452708?l=pypap.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyPap/~4/t-4uI4wn5Hw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://pypap.blogspot.com/feeds/868175831631452708/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6716655737319338935&amp;postID=868175831631452708" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/868175831631452708?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6716655737319338935/posts/default/868175831631452708?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyPap/~3/t-4uI4wn5Hw/my-second-blog.html" title="My Second Blog" /><author><name>yacitus</name><uri>http://www.blogger.com/profile/09766896734206041912</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://pypap.blogspot.com/2007/12/my-second-blog.html</feedburner:origLink></entry></feed>

