<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Fitzgerald Steele &#187; python</title>
	<atom:link href="http://fitzgeraldsteele.wordpress.com/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://fitzgeraldsteele.wordpress.com</link>
	<description>Usability, User Experience, Social Media, Web Design and Development...</description>
	<lastBuildDate>Mon, 04 Jan 2010 15:59:33 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='fitzgeraldsteele.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/1c947ff76c2910d1ea01c039045e041c?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Fitzgerald Steele &#187; python</title>
		<link>http://fitzgeraldsteele.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://fitzgeraldsteele.wordpress.com/osd.xml" title="Fitzgerald Steele" />
		<item>
		<title>URI Routing in Expression Engine, CodeIgniter, Django, and Rails</title>
		<link>http://fitzgeraldsteele.wordpress.com/2010/01/04/uri-routing-in-expression-engine-codeigniter-django-and-rails/</link>
		<comments>http://fitzgeraldsteele.wordpress.com/2010/01/04/uri-routing-in-expression-engine-codeigniter-django-and-rails/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 15:59:33 +0000</pubDate>
		<dc:creator>fitzgeraldsteele</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ux]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[ee]]></category>
		<category><![CDATA[expressionengine]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://fitzgeraldsteele.wordpress.com/?p=367</guid>
		<description><![CDATA[Comparing URI routing between ExpressionEngine, CodeIgniter, Django, and Rails<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=367&subd=fitzgeraldsteele&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>One of the reasons I think I&#8217;m having trouble grokking Expression Engine (EE) is because it has a slightly different take on the <a href="http://en.wikipedia.org/wiki/Model-view-controller">MVC paradigm</a> than I&#8217;m used to from its cousin CodeIgniter, or other web frameworks like Rails or Django.  ExpressionEngine seems to focus on the View (or template in EE-speak), where those other frameworks have you spend more time on the Controller or Model.</p>
<p>Let&#8217;s look at URL routing&#8230;how does the URL map to the code that gets executed and rendered in the browser?  Let&#8217;s make it a simple example where we&#8217;re implementing a site with a structure like this &#8211; A Home/Overview page with a few sections, and each section has a couple pages:</p>
<p>Home<br />
|-Section1<br />
|<br />
|-DetailPage1<br />
|<br />
|-Section2<br />
|<br />
|-DetailPage1<br />
.<br />
.<br />
.</p>
<p>I want to have URLs like this:</p>
<p>/home/</p>
<p>&#8220;Home page&#8221; of the site, with it&#8217;s own glossy template with prominent links to each section:</p>
<p>/home/section1<br />
/home/section2</p>
<p>Section home pages.  These should have the same look and feel, although populated with different data.  (And I don&#8217;t want to hear from you REST people saying it should be /home/section/1 &#8212; this is just a generic example)</p>
<p>/home/section1/detailpage1<br />
/home/section2/detailpage1</p>
<p>Details pages for those that really want to dig into the subject.  These should have the same look and feel even though their in different sections.</p>
<p>Got it?  Great&#8230;let&#8217;s compare how to do that in various frameworks:</p>
<h3>Expression Engine (v1.6.8 EE Core, although v2.0 is in beta)</h3>
<p>Routing Method: Template Based</p>
<p><a href="http://expressionengine.com/docs/general/urls.html">EE maps urls to template groups and templates</a> in this format: /template_group/template/parameter.  I can get the Home Page URL I want by setting Home as the name of my template_group, and define a default template named index.</p>
<p>I haven&#8217;t found a good way to get the section page URLs I want.  The few ways I tried all seemed suboptimal:</p>
<ul>
<li> I could create a new template for each Section, but that seems like overkill &#8212; may as well write plain HTML for each page.</li>
<li>I could overload the the Home/index template to show something different based on the second segment of the url (if segment_2 =! &#8221; do something.  Now I&#8217;ve complicated my template.</li>
<li>I could make categories for each of the sections, and create a single entry for each category to show the details.  But using the category tag enforces that you have a category delimiter in your URL, so now my url path will be something like /Home/category/section1/list</li>
</ul>
<p>The solution I&#8217;m driving toward is changing my around my URL structure so its:</p>
<p>/home/list/section1</p>
<p>/home/list/section2</p>
<p>I added a new segment to my URL structure. I have a template named list, which then uses the section name as a parameter to pull the correct weblog entry.  I can do /home/detailspage1/section1 in a similar manner.</p>
<p>What if I want to add more levels to my hierarchy, like /home/section/detail/moredetail/errata/?  I don&#8217;t see how to do that in EE Core. I need the Pages Module, which comes with the paid version, which allows you to explicitly set the page URI and template.  But my budget doesn&#8217;t allow me to sink cash into this for an experiment.  I could also try out the Structure 3rd party Add-On.</p>
<h3>CodeIgniter</h3>
<p>Routing Method: Filesystem Based</p>
<p><a href="http://codeigniter.com/user_guide/general/urls.html">CodeIgniter maps URLs to controller classes and methods</a>.  So given the url /home/section1/detail, it&#8217;s going to find the controller class named &#8216;home&#8217;, and execute the &#8217;section1&#8242; method with the &#8216;detail&#8217; passed as a parameter.  In the section1 you can return arbitrary HTML, or render a view &#8212; normally an HTML file with variable placeholders.  You can make a deeper hierarchy by 1) placing controllers in a nested directory tree, or 2) customizing the URI Routing rules, similar to how its done in Django and Rails.</p>
<h3>Django and Rails (and CodeIgniter advanced)</h3>
<p>Routing Method: Explicit URI Routing Rules</p>
<p>In this paradigm, the developer must open a URI routing file and write code that tells the framework to run a particular controller method when a URI is requested.  Very often you use regular expressions to make routing less verbose/more generic.  Let&#8217;s say we were doing this example with <a href="http://docs.djangoproject.com/en/dev//topics/http/urls/">Django </a>&#8211; I&#8217;d write a couple lines in urls.py like:</p>
<p>(r&#8217;^home/?P&lt;sectionname&gt;(\w)+&#8217;, project.app.controllername.function)</p>
<p>Which would tell Django to run the app.section.controller.function, passing in sectionname as an argument (yes, I know in Django they call them views instead of controllers).  Inside the controller is the code to pull the appropriate data from the database.  Rails is similar, although with Scaffolding it makes a lot more assumptions about how you structure your pages and controllers, and do some of this routing for you.</p>
<p>With this style, the extra complexity buys you more flexibility.  You can define any URL or URL structure of arbitrary hierarchy.  Here, your coding efforts are in the controller rather than the view/template &#8212; the view just renders the data it is given.  One benefit of this is that your template developer doesn&#8217;t have to know as much about the data structure, and can work more independently of the coding/data.</p>
<h3>Conclusion</h3>
<p>Once again, pick the right tool for the job&#8230;</p>
<p>I guess EE&#8217;s focus on templates speaks to its target audience.  It started life as a simple blogging system, and grew/morphed into a more general CMS.  So it has a relatively simple data model and controller, and instead makes you spend more time on templates, where the target audience is probably most comfortable.  CodeIgniter, Rails, and Django on the other hand are targeted to a more technical audience&#8230;people that built web applications by hand but now want tools to make that job easier.   So in those frameworks you spend most of your time customizing the data model, and specifying the controller behavior.  The templates are relatively dumb in comparison.</p>
<p>Also, I&#8217;m guessing EE is or was targeted to single or small teams of developers/designers building a site either for themselves or a client.  The result is that there is a lot of interplay between the data and the templates, and teammates have to be in pretty close contact to make sure everything works.  Contrast this with Django which grew up in a newspaper environment with lots of contributors.  They needed a system where designers, developers, and content writers could work relatively independently in order to meet a short deadline.  So I feel like that framework better separates the concerns.</p>
<p>It would probably be a more fair to compare ExpressionEngine to something like WordPress or MovableType &#8212; other blog engines that have blossomed into content management systems.  WordPress even won<a href="http://www.packtpub.com/award"> 2009 Open Source CMS of the year</a>, so that really is something to investigate.</p>
<p>This whole diatribe is predicated on the assumption that the URL structure is important  to anyone.  Maybe I&#8217;m trying to uphold some strange kind of RESTful ideal that isn&#8217;t practical.  Certainly the client for this project doesn&#8217;t care.  I only care so far as the framework acknowledges that my information architecture is going to change and grow over time &#8212; categories will come and go, new subsections will be added.  I see the RESTful pattern as a way to organize the information structure in a scalable way.  Frameworks that facilitate the RESTful style, and follow a more traditional MVC build approach,  more cleanly separate the various parts of the system, and make it easier to change and grow the IA over time.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/fitzgeraldsteele.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/fitzgeraldsteele.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/fitzgeraldsteele.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/fitzgeraldsteele.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/fitzgeraldsteele.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/fitzgeraldsteele.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/fitzgeraldsteele.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/fitzgeraldsteele.wordpress.com/367/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/fitzgeraldsteele.wordpress.com/367/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/fitzgeraldsteele.wordpress.com/367/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=367&subd=fitzgeraldsteele&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://fitzgeraldsteele.wordpress.com/2010/01/04/uri-routing-in-expression-engine-codeigniter-django-and-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">fitzgeraldsteele</media:title>
		</media:content>
	</item>
		<item>
		<title>Learning Web Frameworks: Expression Engine, Acquia Drupal, Ruby on Rails</title>
		<link>http://fitzgeraldsteele.wordpress.com/2009/10/05/learning-web-frameworks-expression-engine-acquia-drupal-ruby-on-rails/</link>
		<comments>http://fitzgeraldsteele.wordpress.com/2009/10/05/learning-web-frameworks-expression-engine-acquia-drupal-ruby-on-rails/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 06:00:15 +0000</pubDate>
		<dc:creator>fitzgeraldsteele</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[acquia]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[expression engine]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://fitzgeraldsteele.wordpress.com/?p=298</guid>
		<description><![CDATA[I work for a corporate website team.  When our internal &#8216;clients&#8217; want a new web project &#8212; new page, contact or registration form, major page redesign, etc &#8212; they download, print, fill out, and mail us a paper form.  We recognized the waste involved with this paper form, and the irony that the website team [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=298&subd=fitzgeraldsteele&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I work for a corporate website team.  When our internal &#8216;clients&#8217; want a new web project &#8212; new page, contact or registration form, major page redesign, etc &#8212; they download, print, fill out, and mail us a paper form.  We recognized the <a href="http://www.epa.gov/lean/thinking/types.htm">waste</a> involved with this paper form, and the irony that the website team does not have a web enabled project request form.  We do most of our work in base PHP, but we&#8217;re also evaluating various web toolsets/frameworks/CMSs to adopt for more of our projects going forward.  So we used this small form as a little case study.  Let&#8217;s implement this form in a number of different tools.  That way we get practical experience in these different technologies, and we can see first hand what attributes we&#8217;re looking for in a web framework.</p>
<h2>Project Requirements</h2>
<p>We met for a half-hour just to make our project requirements explicit.  We documented the requirements in a <a href="http://agileproductdesign.com/blog/the_new_backlog.html">story map</a>, and made a quick wireframe:</p>
<ul>
<li>Client enters their contact details (name, department, phone, email)
<ul>
<li>Optional: Pull the contact details from the enterprise LDAP server</li>
</ul>
</li>
<li>Client enters project details (name, description, budget code, deadline date, and whether the project has VP approval)</li>
<li>On submission, show confirmation page and email confirmation to client.  Also send email notification to our project managers that a new request has been made</li>
<li>Members of our team may view the list of projects (especially budget codes, which we need for our time sheets), and see project details</li>
<li>Project managers can add an estimate (number of hours we think the project will take), and estimate description</li>
<li>When the estimate is created, automatically email an estimate to the client</li>
</ul>
<p>Now, to build it&#8230;</p>
<h3>Expression Engine</h3>
<p>I got the sense that <a href="http://expressionengine.com/">Expression Engine</a> started its life as a blogging only platform, and someone said, &#8220;hey&#8230;we could probably use this as a general purpose CMS too!&#8221;  I felt that if I wanted a blog or multi-blog site, EE would be great, but we clearly did not understand the &#8220;EE Way.&#8221;  EE does not come with a form builder out of the box, but we found the <a href="http://www.solspace.com/software/detail/freeform/">FreeForm</a> module which got us on our way.  There&#8217;s no GUI form builder or admin panel; it requires a developer to build the form, which was a major downside for our team.  At the end of a 3 hour sprint, we had an expression engine form, styled how we wanted, submitting project requests and sending the project request emails to our managers, but not a confirmation to the client.  We didn&#8217;t get to any edit estimate functionality, and certainly didn&#8217;t have a way to email the client when the estimate was made.</p>
<p>We never really felt like we &#8216;got&#8217; ExpressionEngine. It would definitely take a bit more time to figure out if this is the right tool for our CMS needs. The developers on our team felt like it would&#8217;ve been much simpler to just write the thing in plain-old PHP.</p>
<p>Verdict: With 4 people working for 3 hours, we got some minimal functionality, but we must be missing something.</p>
<h3>Acquia Drupal</h3>
<p>Ahh, <a href="http://drupal.org/">Drupal</a>.  Apparantly THE open source CMS.  Yet, to paraphrase Peter Parker&#8217;s uncle, with great power comes great complexity &#8212; and a steep learning curve.  <a href="http://acquia.com/">Acquia</a> is a batteries-included Drupal distribution, with optional paid technical support, which is attractive to our company.  Acquia includes the Webform module, which is a GUI, drag/drop form builder from inside the Drupal admin interface.  While the team was at lunch, I built the form by myself.  Furthermore, the <a href="http://drupal.org/project/webform">Webform</a> module provides a nice admin interface that allows for viewing all the results, updating entries, even downloading the submissions into a CSV file. One thing I really liked about the Webform module was that it comes with an area where you can post your own custom PHP code to be run after a submission&#8230;very cool.  Another nice feature was the conditional emails:  if the submission selects A, email to person A; selectB, email person B etc.</p>
<p>I had it in the default Acquia Marina template.  I don&#8217;t think we really get how to use Drupal&#8217;s templating system yet, so I&#8217;m not sure how we would apply our own custom styles/templates.  But I&#8217;m confident that we&#8217;ll be able to understand Druapl templating before Expression Engine internals (which is based on <a href="http://codeigniter.com/">CodeIgniter</a> &#8212; which by the way I really like as a web framework).</p>
<p>Verdict: The webform module is the bomb: 1 person, 15 minutes, done.  Not sure how to bend Drupal templates to make it look how we want, though.</p>
<h3>Ruby on Rails</h3>
<p>I&#8217;ve been looking for an opportunity to try a non-blog/wiki type <a href="http://www.rubyonrails.org">rails</a> app.  I checked out the <a href="http://headfirstlabs.com/books/hfrails/">Heads First Rails</a> book from the local library, which taught me a lot.</p>
<p>It turns out Rails is tailor made for this type of job.  <a href="http://guides.rubyonrails.org/getting_started.html#getting-up-and-running-quickly-with-scaffolding">Rails scaffolding</a> gives you an Apple-esque out of the box experience.  One command line basically got the full app functionality.  Given the name of the database model, and a list of field names and types, rails generates a database model, and the controller and view code for basic CRUD functionality:</p>
<pre class="brush: bash;">

ruby script/generate scaffold project first_name:string last_name:string email:string phone:string project_name:string project_description:text date_needed:date budget_code:integer vp_approval:boolean
</pre>
<p>Rails just really gives lots of tools to do the things you probably want to do on a web app.  Need to add/change the database schema after the initial generate?  <a href="http://guides.rubyonrails.org/migrations.html">Migrations</a> are your friend.  Send emails that get triggered on code events?  Use <a href="http://guides.rubyonrails.org/action_mailer_basics.html">Active Mailer</a> (ruby script/generate mailer) and you&#8217;re mostly done.  The views/templating/partials makes sense.  Scaffolding also gives you infrastructure for unit tests and acceptance tests (via the <a href="http://www.cukes.info">Cucumber</a> behavior driven development framework).</p>
<p>So I was super excited about how quickly I could get something up and running.  I call over one of our graphic artists and one of our project managers to give them a demo of how to create, scaffold, migrate, and configure a rails app.  And I got mixed reactions.  Yes, scaffolding is impressive,  but you still have to be a bit of at techie/programmer to understand how to do it.  I think they were a bit intimidated by the command line knowledge required, as well as the need to learn a new programming language.  As I created a number of apps to show different parts of the generate/scaffolding script, the PM noted, &#8220;well, it looks like sometimes it&#8217;s easier just to build a whole new application rather than fix one.&#8221;  I thought that was insightful&#8230;she recognized that the auto-generated code makes it really &#8216;cheap&#8217; to build a new application.</p>
<p>Verdict: Convention over configuration is great, as long as you can learn the conventions.  Once I started to learn the conventions, I could do a lot in a very little time.</p>
<h2>Conclusion</h2>
<p>At the risk of sounding cliché, you have to pick the right tool for the job, for your team.  For this single, stand-alone project, we&#8217;ll probably roll with the Rails app.  We can get that up and running super quickly.  I don&#8217;t know that we would &#8216;bet the farm&#8217; for our entire site on Rails just yet, though.  Big learning curve for our department.  We&#8217;re really looking for a content management system.  We&#8217;ve got several instances of WordPress we use, so we&#8217;re used to that.  Personally, I&#8217;m leaning toward Drupal.  Yes, high learning curve, but it has a really flexible content model, lots of modules, an active developer community, support for workflow and fine-grained authentication/authorization.  And, with Acquia you have commercial support.</p>
<p>But of course the door is still open, and we&#8217;re looking at other toys to play with.  I&#8217;m going to try doing this form in <a href="http://pylonshq.com/">Pylons</a>, which looks heavily influenced by Ruby on Rails, with a couple advantages 1) written in python which I already know, 2) less opinionated about which tools you use at various points in the web stack.  It scaffolds a rest style controller, but not the views, models, or tests.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/fitzgeraldsteele.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/fitzgeraldsteele.wordpress.com/298/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/fitzgeraldsteele.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/fitzgeraldsteele.wordpress.com/298/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/fitzgeraldsteele.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/fitzgeraldsteele.wordpress.com/298/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/fitzgeraldsteele.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/fitzgeraldsteele.wordpress.com/298/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/fitzgeraldsteele.wordpress.com/298/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/fitzgeraldsteele.wordpress.com/298/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=298&subd=fitzgeraldsteele&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://fitzgeraldsteele.wordpress.com/2009/10/05/learning-web-frameworks-expression-engine-acquia-drupal-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">fitzgeraldsteele</media:title>
		</media:content>
	</item>
		<item>
		<title>New Python File &#8212; TextMate Template</title>
		<link>http://fitzgeraldsteele.wordpress.com/2009/08/12/new-python-file-textmate-template/</link>
		<comments>http://fitzgeraldsteele.wordpress.com/2009/08/12/new-python-file-textmate-template/#comments</comments>
		<pubDate>Wed, 12 Aug 2009 14:40:04 +0000</pubDate>
		<dc:creator>fitzgeraldsteele</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://fitzgeraldsteele.wordpress.com/?p=222</guid>
		<description><![CDATA[Textmate has the ability to create new files based on a template you create.  It had a few templates for Python, but nothing exactly like I want.
When I start a new python script or module, I want to:

Follow the Pythonista style
Parse some command line arguments &#8211; usually an input file
Enable logging (either file based, or [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=222&subd=fitzgeraldsteele&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><a href="http://macromates.com/">Textmate</a> has the ability to create new files based on a template you create.  It had a few templates for Python, but nothing exactly like I want.</p>
<p>When I start a new python script or module, I want to:</p>
<ul>
<li>Follow the <a href="http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#command-line-processing">Pythonista</a> style</li>
<li>Parse some command line arguments &#8211; usually an input file</li>
<li>Enable logging (either file based, or to the console)</li>
</ul>
<p>I created a new TextMate template to do those things.</p>
<ol>
<li>Select Bundles &gt; Bundle Editor &gt; Show Bundle Editor</li>
<li>Select and Open the Python Bundle</li>
<li>Find the Python Bundle Templtes</li>
<li>Copy one into a new Template.  Give it a sensible name</li>
<li>Replace the template.py text with the following&#8230;</li>
</ol>
<pre class="brush: python;">
#!/usr/bin/env python
# encoding: utf-8
&quot;&quot;&quot;
untitled.py

Created by Jerry Steele on 2009-08-12.
Copyright (c) 2009 ACT. All rights reserved.
&quot;&quot;&quot;
import os
import sys
import logging
import optparse

LOG = None

def process_command_line(argv):
 &quot;&quot;&quot;
 Return a 2-tuple: (settings object, args list).
 `argv` is a list of arguments, or `None` for ``sys.argv[1:]``.
 &quot;&quot;&quot;
 global LOG
 if argv is None:
 argv = sys.argv[1:]

 # initialize the parser object:
 parser = optparse.OptionParser(
 formatter=optparse.TitledHelpFormatter(width=78),
 add_help_option=None)

 # define options here:
 parser.add_option(&quot;-f&quot;, &quot;--file&quot;, dest=&quot;filename&quot;,
 help=&quot;read data from FILENAME&quot;)
 parser.add_option(&quot;-v&quot;, &quot;--verbose&quot;, dest=&quot;verbose&quot;, default=False,
 action='store_true', help=&quot;write debug log to FILENAME&quot;)
 parser.add_option(&quot;-L&quot;, &quot;--log&quot;, dest=&quot;logfile&quot;, help=&quot;write debug log to FILENAME&quot;)
 parser.add_option(      # customized description; put --help last
 '-h', '--help', action='help',
 help='Show this help message and exit.')

 options, args = parser.parse_args(argv)

 # check number of arguments, verify values, etc.:

 # set up logging
 if options.verbose:
 LOG = setlogging(options.logfile)

 if not options.filename:
 pass
 #LOG.error(&quot;Input filename not specified&quot;)
 #parser.error(&quot;You must supply an input file&quot;)
 # further process settings &amp; args if necessary

 return options, args

def main(argv=None):
 settings, args = process_command_line(argv)

 # application code here, like:
 # run(settings, args)
 return 0        # success

def setlogging(logfile=None):
 consolelevel = logging.DEBUG
 logger = logging.getLogger(__name__)
 logger.setLevel(consolelevel)
 # create formatter and add it to the handlers
 formatter = logging.Formatter(&quot;%(asctime)s - %(name)s - %(levelname)s - %(message)s&quot;)
 # create console handler with a higher log level
 ch = logging.StreamHandler()
 ch.setLevel(consolelevel)
 ch.setFormatter(formatter)
 # add the handlers to logger
 logger.addHandler(ch)

 # create file handler which logs error messages
 if logfile:
 filelevel = logging.ERROR
 fh = logging.FileHandler(logfile)
 fh.setLevel(filelevel)
 fh.setFormatter(formatter)
 logger.addHandler(fh)

 #test logging
 logger.debug(&quot;debug message&quot;)
 logger.info(&quot;info message&quot;)
 logger.warn(&quot;warn message&quot;)
 logger.error(&quot;error message&quot;)
 logger.critical(&quot;critical message&quot;)

 return logger

if __name__ == '__main__':
 status = main()
 sys.exit(status)
</pre>
<p>Even if you don&#8217;t use Textmate, you can still use this to quickstart python modules.  Just remove/replace the $TM_ variables</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/fitzgeraldsteele.wordpress.com/222/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/fitzgeraldsteele.wordpress.com/222/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/fitzgeraldsteele.wordpress.com/222/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/fitzgeraldsteele.wordpress.com/222/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/fitzgeraldsteele.wordpress.com/222/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/fitzgeraldsteele.wordpress.com/222/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/fitzgeraldsteele.wordpress.com/222/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/fitzgeraldsteele.wordpress.com/222/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/fitzgeraldsteele.wordpress.com/222/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/fitzgeraldsteele.wordpress.com/222/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=222&subd=fitzgeraldsteele&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://fitzgeraldsteele.wordpress.com/2009/08/12/new-python-file-textmate-template/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">fitzgeraldsteele</media:title>
		</media:content>
	</item>
		<item>
		<title>Even Simpler Web Response Testing in Python with Pylot</title>
		<link>http://fitzgeraldsteele.wordpress.com/2009/02/18/even-simpler-web-response-testing-in-python-with-pylot/</link>
		<comments>http://fitzgeraldsteele.wordpress.com/2009/02/18/even-simpler-web-response-testing-in-python-with-pylot/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 14:40:28 +0000</pubDate>
		<dc:creator>fitzgeraldsteele</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://fitzgeraldsteele.wordpress.com/?p=83</guid>
		<description><![CDATA[About a month ago a wrote a simple web response timer, because I didn&#8217;t quickly find a tool out there that could do it.
I should have looked harder.
I finally found pylot &#8212; a python program for running HTTP load tests.  Pylot does what I needed to do (calculate some statistics around page response time) and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=83&subd=fitzgeraldsteele&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>About a month ago a wrote a <a href="http://fitzgeraldsteele.wordpress.com/2009/01/15/simple-web-response-time-testing-with-python/">simple web response timer</a>, because I didn&#8217;t quickly find a tool out there that could do it.</p>
<p>I should have looked harder.</p>
<p>I finally found <a href="http://www.pylot.org/">pylot</a> &#8212; a python program for running HTTP load tests.  Pylot does what I needed to do (calculate some statistics around page response time) and a <a href="http://www.pylot.org/gettingstarted.html">whole lot more</a>.  Pylot is designed to benchmark/load test HTTP web services, so you can profile arbitrary URL&#8217;s with either HTTP GET or POST requests.  Or, you can just give it a simple URL or two like I did.  You define a simple XML file with your &#8220;test cases&#8221; (the URLs you want to profile, along with any parameters), and give it some runtime parameters (number of virtual users that will hit the URL, request interval, rampup time, whether or not to launch a GUI to watch the stats in real time).</p>
<p>Much simpler than what I did.  And it generates much prettier reports and graphs, without the need for loading into a separate statistics program.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/fitzgeraldsteele.wordpress.com/83/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/fitzgeraldsteele.wordpress.com/83/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/fitzgeraldsteele.wordpress.com/83/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/fitzgeraldsteele.wordpress.com/83/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/fitzgeraldsteele.wordpress.com/83/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/fitzgeraldsteele.wordpress.com/83/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/fitzgeraldsteele.wordpress.com/83/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/fitzgeraldsteele.wordpress.com/83/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/fitzgeraldsteele.wordpress.com/83/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/fitzgeraldsteele.wordpress.com/83/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=83&subd=fitzgeraldsteele&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://fitzgeraldsteele.wordpress.com/2009/02/18/even-simpler-web-response-testing-in-python-with-pylot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">fitzgeraldsteele</media:title>
		</media:content>
	</item>
		<item>
		<title>Using Regular Expressions and Generators to Tokenize a File</title>
		<link>http://fitzgeraldsteele.wordpress.com/2009/01/30/using-regular-expressions-and-generators-to-tokenize-a-file/</link>
		<comments>http://fitzgeraldsteele.wordpress.com/2009/01/30/using-regular-expressions-and-generators-to-tokenize-a-file/#comments</comments>
		<pubDate>Fri, 30 Jan 2009 20:26:24 +0000</pubDate>
		<dc:creator>fitzgeraldsteele</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[batteries included]]></category>
		<category><![CDATA[generators]]></category>
		<category><![CDATA[python to the rescue]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[regular expressions]]></category>

		<guid isPermaLink="false">http://fitzgeraldsteele.wordpress.com/?p=78</guid>
		<description><![CDATA[Generator Tricks for System Programmers really opened my eyes to the utility of python generators.  Yesterday I took an opportunity to use one, and bone up on my regular expression ninja skills to boot.
I received an email from a colleague containing some references to reports our company had written, so that we can post them [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=78&subd=fitzgeraldsteele&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><a href="http://www.dabeaz.com/generators/">Generator Tricks for System Programmers</a> really opened my eyes to the utility of python generators.  Yesterday I took an opportunity to use one, and bone up on my regular expression ninja skills to boot.</p>
<p>I received an email from a colleague containing some references to reports our company had written, so that we can post them in appropriate places on our website.  He clearly went through some pains to organize the information in a very human-readable manner:</p>
<pre>CATEGORY 1
Report Title1 (report type year)
Report Title2 (report type year)
CATEGORY 2
...</pre>
<p>Which is great.  The trouble is, I also need the existing URL associated with each of these reports.  And it may make sense to pull this list from a database, so I&#8217;d like to treat each one of those as a row with certain attributes:</p>
<pre>NAME  | TYPE | YEAR | CATEGORY</pre>
<p>Oh sure, I could copy the text into Excel and put everything into columns by hand, but where&#8217;s the fun of that?  Python to the rescue!</p>
<p>Python generators are kind of like a list, but without the list.  Like a list, it is a sequence of things (ints, strings, other lists, objects, etc).  Like a list, you can iterate through each value of the generator.  But instead of storing the entire list in memory, it evaluates some function to generate the next value.  This means that generators can more efficiently deal with very large sets of inputs.  You&#8217;re not loading the whole input set into memory, instead you just ask for the &#8216;next&#8217; value, and the generator decides what to spit out.  It might mean reading the next line of a file, adding or modifying an object, or calculating the next value in the Fibonacci sequence.</p>
<p>Check out the System Admin&#8217;s Guide to Generators for a more full explanation, or look up the documentation on the <a href="http://www.python.org/dev/peps/pep-0255/">yield statement</a>.  Python also has a nice shorthand for <a href="http://www.python.org/dev/peps/pep-0289/">generator expressions</a>, that is very similar to how list comprehensions are done.  It often leads to pretty clean, readable code.  Here&#8217;s the key section of code from this example:</p>
<pre class="brush: python;">

regex = re.compile(r&quot;(?P&lt;name&gt;.*) \((?P&lt;type&gt;.*) (?P&lt;year&gt;\d*)\)&quot;)    

with open ('researchreports.txt') as infile:
    lines = (l.rstrip() for l in infile)   
    matches = ((regex.search(l),l) for l in lines)   
    newline = (matcherfunction(m) for m in matches)
</pre>
<p>First, we define the regular expression used to parse the line, and extract the report name, type, and year.  The next four lines do the actual work:</p>
<ul>
<li>Open the file for reading</li>
<li>From the open file, spit out each line, stripping off whitespace from the end</li>
<li>For each of those lines, run the regular expression.  Spit out a tuple of (Match Object, original line).</li>
<li>For each of those tuples, run the matcher function, which spits out the tuple (name, type, year), or the original line in the event where the original line wasn&#8217;t in the right format.</li>
</ul>
<p>That&#8217;s basically the end of the magic.  The rest is just writing out to a csv file.  Python&#8217;s CSV module to the rescue.  Here&#8217;s the whole code in case you&#8217;re interested.</p>
<pre class="brush: python;">

#!/usr/bin/env python

from csv import writer
import re

def matcherfunction(m):
    &quot;&quot;&quot;if we have a MatchObject, return the parsed output.  if not, return the original line&quot;&quot;&quot;
    if m[0]:
        return (m[0].group('name'), m[0].group('type'), m[0].group('year'))
    else:
        return m[1],

regex = re.compile(r&quot;(?P&lt;name&gt;.*) \((?P&lt;type&gt;.*) (?P&lt;year&gt;\d*)\)&quot;)       
with open ('researchreports.txt') as infile:
    lines = (l.rstrip() for l in infile)   
    matches = ((regex.search(l),l) for l in lines)   
    newline = (matcherfunction(m) for m in matches)

    with open ('researchreports.csv', 'w') as outf:
        csvfile = writer(outf)
        headers = ['','TYPE','YEAR', 'URL', 'CATEGORIES']
        csvfile.writerow(headers)
        csvfile.writerows(newline)
</pre>
<p>Did I over complicate the problem?  Probably.  I could&#8217;ve just read in the whole file as a string, and then done a global regex search/replace.  But that would be problematic if I were dealing with a huge input file.  The advantage of this approach is that it doesn&#8217;t matter how many rows there are; it&#8217;ll march through them with no worries about memory limitations.  Second, it&#8217;ll be easier to modify and reuse this approach than a custome RegEx.  Finally, it apparantly fits my mental model of how to solve the problem.</p>
<p>What I really want is for someone to show me how to do this in one line with awk/sed.  =)</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/fitzgeraldsteele.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/fitzgeraldsteele.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/fitzgeraldsteele.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/fitzgeraldsteele.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/fitzgeraldsteele.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/fitzgeraldsteele.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/fitzgeraldsteele.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/fitzgeraldsteele.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/fitzgeraldsteele.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/fitzgeraldsteele.wordpress.com/78/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=78&subd=fitzgeraldsteele&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://fitzgeraldsteele.wordpress.com/2009/01/30/using-regular-expressions-and-generators-to-tokenize-a-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">fitzgeraldsteele</media:title>
		</media:content>
	</item>
		<item>
		<title>Simple Web Response Time Testing with Python</title>
		<link>http://fitzgeraldsteele.wordpress.com/2009/01/15/simple-web-response-time-testing-with-python/</link>
		<comments>http://fitzgeraldsteele.wordpress.com/2009/01/15/simple-web-response-time-testing-with-python/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 19:54:02 +0000</pubDate>
		<dc:creator>fitzgeraldsteele</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[usability]]></category>
		<category><![CDATA[ux]]></category>
		<category><![CDATA[profiling]]></category>
		<category><![CDATA[response time]]></category>
		<category><![CDATA[timing]]></category>

		<guid isPermaLink="false">http://fitzgeraldsteele.wordpress.com/2009/01/15/simple-web-response-time-testing-with-python/</guid>
		<description><![CDATA[For my day job, I&#8217;m creating a series of HTML pages that each have a table that shows how our various services and solutions map onto problems our customers are likely to have.  The main site is currently thousands of static HTML pages, with a bit of PHP thrown in a few pages to do [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=66&subd=fitzgeraldsteele&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>For my day job, I&#8217;m creating a series of HTML pages that each have a table that shows how our various services and solutions map onto problems our customers are likely to have.  The main site is currently thousands of static HTML pages, with a bit of PHP thrown in a few pages to do page footers.  We&#8217;re working on upgrading to a dynamic CMS type site.  In the meantime, I used the opportunity to learn a bit more about PHP and I wrote a small function to generate the table HTML given a JSON document describing the table headers, rows, and content.</p>
<p>As I was debugging the sites, I felt like there was sometimes a noticeable delay in rendering the page that wasn&#8217;t there on the existing static pages.  Was this my imagination, or something that our users might notice and complain about.  Hmm, I don&#8217;t have any web profiling software, and I couldn&#8217;t find anything that I could quickly install and run.  And I had some time.  Looks like I have to write some code.  In the immortal words of <a href="http://www.youtube.com/watch?v=Zll_jAKvarw">Leeroy Jenkins</a>, Let&#8217;s Do This!&#8221;</p>
<p><em>(Update: </em><a href="http://fitzgeraldsteele.wordpress.com/2009/02/18/even-simpler-web-response-testing-in-python-with-pylot/"><em>I found a simpler way to profile pages in python</em></a><em>)</em></p>
<h3>Python timeit Module</h3>
<p>Python&#8217;s mantra is Batteries Included, implying that for whatever coding task you have, there&#8217;s probably something in the standard library that will do muct of what you want.  You shouldn&#8217;t have to go and write something completely from scratch.  I knew about python&#8217;s time module.  I was planning on using it to mark the time before fetching my webpage, mark the time after fetching the page, and comparing the two.  But I stumbled onto the <a href="http://docs.python.org/library/timeit.html">timeit module</a>, which makes it even a bit easier.  Timeit basically wraps up that logic of marking time before and after some bit of code in convenient package.  You give the timeit.Timer() class a bit of code that you want to time.  The timeit() method will run the code a specified number of times (default 1,000,000) and return the average time for code execution.  The repeat() method will run the timeit() method a specified number of times, and return a list of the average times.</p>
<p>In action, it looks like this:</p>
<pre class="brush: python;">
import timeit

# Request the page 100 times, time the response time

t = timeit.Timer(&quot;h.request('http://PAGE/URL',headers={'cache-control':'no-cache'})&quot;, &quot;from httplib2 import Http; h=Http()&quot;)
times_p1 = t.repeat(100,1)
</pre>
<p>Three lines of code&#8230;not bad.  The Timer() class takes two strings as parameters: 1) The python code you would like repeated and timed, 2) Python code required to run before each run of the test code.  If you&#8217;re familiar with Unit Testing, then the 2nd parameter is like the setUp() method.  Notice I&#8217;m using the httplib2 library instead of the standard urllib library.  I like <a href="http://code.google.com/p/httplib2/">httplib2</a> for requesting urls because I&#8217;m familiar with it, it combines requesting the url and reading its contents, and its really good about dealing with caching.  In this case, I don&#8217;t want the server to cache.</p>
<p>The second line instructs my Timer() to run 100 sets of my test code, with 1 trial per set.  The output is a list of 100 times.</p>
<p>The documentation for timeit.repeat() gives some good advice on how much stock to put into these numbers, and using mean/standard deviation to describe the performance.  But what I really wanted to know was whether or not my page took significantly longer to load than a similar page with no dynamic content.  I expanded my code to repeatedly time a second, static page, and the two lists in two columns of a csv file.</p>
<pre class="brush: python;">
import timeit
from csv import writer

# Hit the dynamic page 100 times, time the response time

t = timeit.Timer(&quot;h.request('http://PAGE1/URL',headers={'cache-control':'no-cache'})&quot;,&quot;from httplib2 import Http; h=Http()&quot;)
times_p1 = t.repeat(100,1)

# Now hit a similar static page 100 times
t = timeit.Timer(&quot;h.request('http://PAGE2/URL', headers={'cache-control':'no-cache'})&quot;,&quot;from httplib2 import Http; h=Http()&quot;)
times_p2 = t.repeat(100,1)

# the times to a CSV file
times = zip(times_p1,times_t2)

with open('times.csv','w') as f:
    w = writer(f)
    w.writerows(times)
</pre>
<p>Note we&#8217;re using the <a href="http://effbot.org/zone/python-with-statement.htm">python with statement</a> from Python 2.5+, which encapsulates some of the try/except/finally logic you&#8217;d normally write when opening a file.    Because I had even more spare time, I imported my new times.csv file into a statistics program (SPSS) to calculate mean, and perform a <a href="http://en.wikipedia.org/wiki/Student%27s_t-test">T-Test</a> to see if the means of the two columns they are statistically different.  I also could have used various statistics scripting tools: <a href="http://www.scipy.org">scipy</a>, <a href="http://www.r-project.org/">R</a>, for example.  But I didn&#8217;t have THAT much time.  <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>There was a statistically significant difference.  The dynamic page was, on average, about 1.2 ms slower than the static page.  This makes practically no difference to the user experience of the page, and makes my development life much easier (and also illustrates how <a href="http://www.uoregon.edu/%7Emgall/statistical_significance_v.htm">practical significance may differ from statistical significance</a>).  I&#8217;ll continue to generate pages dynamically.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/fitzgeraldsteele.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/fitzgeraldsteele.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/fitzgeraldsteele.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/fitzgeraldsteele.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/fitzgeraldsteele.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/fitzgeraldsteele.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/fitzgeraldsteele.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/fitzgeraldsteele.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/fitzgeraldsteele.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/fitzgeraldsteele.wordpress.com/66/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=66&subd=fitzgeraldsteele&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://fitzgeraldsteele.wordpress.com/2009/01/15/simple-web-response-time-testing-with-python/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">fitzgeraldsteele</media:title>
		</media:content>
	</item>
		<item>
		<title>Newbie&#8217;s Experience Setting Up a Pinax Site</title>
		<link>http://fitzgeraldsteele.wordpress.com/2008/10/16/newbies-experience-setting-up-a-pinax-site/</link>
		<comments>http://fitzgeraldsteele.wordpress.com/2008/10/16/newbies-experience-setting-up-a-pinax-site/#comments</comments>
		<pubDate>Thu, 16 Oct 2008 19:20:28 +0000</pubDate>
		<dc:creator>fitzgeraldsteele</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scholarlycommunication]]></category>
		<category><![CDATA[social media]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[pinax]]></category>
		<category><![CDATA[research]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://fitzgeraldsteele.wordpress.com/?p=22</guid>
		<description><![CDATA[As I mentioned last week, I&#8217;m using Pinax to test a new website for my research lab.  The site is now in private alpha, which means I&#8217;m getting some internal users to log in, test it out, and give me feedback, and I don&#8217;t think it will fall over.  I&#8217;m writing up my experience to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=22&subd=fitzgeraldsteele&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><a href="http://fitzgeraldsteele.wordpress.com/2008/10/10/playing-with-pinaxplaying-with-pinax/">As I mentioned last week</a>, I&#8217;m using <a href="http://pinaxproject.com">Pinax </a>to test a new website for my research lab.  The site is now in private alpha, which means I&#8217;m getting some internal users to log in, test it out, and give me feedback, and I don&#8217;t think it will fall over.  I&#8217;m writing up my experience to 1) help others get started quickly, and 2) start talking about how the pinax community can get people ramped up faster.</p>
<p>My background:</p>
<ul>
<li>Journeyman Python Programmer.  Can independently write code, diagnose most problems.</li>
<li>Journeyman HTML/CSS/Javascript. Can independently write code, diagnose most problems.</li>
<li>Some experience doing apache configuration, though not recently. No experience with mod_python or mod_wsgi.  I largely rely on documentation and examples found on the interwebs.</li>
<li>No major prior experience with <a href="http://www.djangoproject.com">django</a>, and none deploying it via Apache/mod_{python,wsgi}.  I almost exclusively rely on documentation and examples found on the web (although my python experience helps)</li>
</ul>
<p>The nice thing about pinax is that it has an active community; in particular an active IRC channel (#pinax on freenode).  The pinax maintainers have been there, patiently answered my newbie questions, and got me going.</p>
<h3>Step 1 &#8211;  Get the base pinax software running.</h3>
<p>Download and install django and pinax.   I first did this on a WinXP desktop.  Crap.  The templates aren&#8217;t rendering properly.  I try commenting out the offending lines in the templates, but problem after problem comes up.  Jump on #pinax.  Did you do seed the database with <code>manage.py syncdb</code>?   Uhh, no.  I do that, but still having problems.  Back to #pinax.  Are you running WinXP?  Why yes!  Oh, pinax on Windows has a known bug (<a href="http://groups.google.com/group/django-hotclub/msg/e41d4220d7f65299">which really is caused by one of the external apps they rely on</a>).  Copy some files to a new location, or install on an OS which supports soft links.  I choose door 2, recheckout on my Ubuntu machine, sync the database, run the django dev server (<code> manage.py runserver</code>) and we&#8217;re good to go.</p>
<h3>Step 2 &#8211; Make sure everything in the base site works as expected.</h3>
<p>The pinax project comes with a complete working example under the directory projects/complete_projects.  I copy this to a new directory so that I can refer back to the complete_project in case I screw something up.  This means you have to change the ROOT_URLCONF in the settings.py</p>
<p>Added some users via the admin interface&#8230;looks great.  Added an account via the Sign-Up page.  Accounts are created (with or without OpenID), but no confirmation emails are being sent.  Hmm  Check out the included <a href="http://code.google.com/p/django-mailer/">django-mailer</a> app, which uses the same configuration as the <a href="http://docs.djangoproject.com/en/dev/topics/email/">standard django.core.mailer</a>.  We need to add some settings to settings.py: EMAIL_HOST, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD.  I set these to use my gmail account to do email.  But really, it&#8217;d be better to have the emails coming from the local machine, and I really don&#8217;t want to hardcode my gmail password into the config file.  I need <a href="http://www.sendmail.org/">sendmail</a> on this machine (<code>sudo apt-get install sendmail</code>).  Now that the local machine has its own SMTP server, I can remove the EMAIL_* settings from settings.py.</p>
<p>Hmm&#8230;emails still not going out.  Let&#8217;s look at the django-mailer docs.  Oh, I see&#8230;email messages aren&#8217;t actually sent until manage.py send_mail is run from the command line.  The recommended solution is to add a couple lines to the system crontab so that they are run regularly (<a href="http://pinaxproject.com/docs/deployment.html">this is now much clearer in the pinax deployment docs</a>).  Now we&#8217;re sending emails!</p>
<h3>Step 3 &#8211; Configure templates, images, and site text for our lab.</h3>
<p>Ok&#8230;first thing is that the default site says &#8216;Pinax&#8217; everywhere.  I need to change that to the name of our lab, GROK Lab.  There&#8217;s an <a href="http://code.google.com/p/django-hotclub/issues/detail?id=29">outstanding ticket</a> to use a SITE_NAME variable in settings.py which would be displayed throughout the site.  Until that gets resolved, we just have to find all the hardcoded [Pp]inax strings are replace them with the SITE_NAME variable.  I just used grep to find them all, and then I replaced the ones I needed to replace (I left things like Built with Pinax, About Pinax, James Tauber is the awesomest creater of Pinax ever, etc).  Pinax has several translations available, which I think means that I should have been making most of my changes to externalized text strings in locale/en/LC_MESSAGES.  But I didn&#8217;t, and just changed the template files.  I&#8217;m not sure what will happen when another language is selected.  Should learn more about <a href="http://docs.djangoproject.com/en/dev/topics/i18n/#topics-i18n">django internationalization</a>.</p>
<p><em><strong>Update 11/14</strong></em><em>: Fernando Correia did some more digging on how to <a href="http://fernandoacorreia.wordpress.com/2008/10/23/exploring-pinax-part-2/">properly externalize strings in django</a>.</em></p>
<p>One particular place this got me into trouble was, again, the django-mailer app.  Invitations to join the site are generated via two templates: templates/friends/join_invite_message.txt and templates/friends/join_invite_subject.txt.  I wanted the subject of my email to say &#8220;You have been invited to join the new SITE_NAME.&#8221;  I tried to use the variable substitution syntax {% site_name %} but got an exception that I couldn&#8217;t use that tag inside a trans tag.  Read more django docs to learn about <a href="http://docs.djangoproject.com/en/dev/ref/templates/#ref-templates-index">template tags</a> and internationalization.  I also tried changing the join_invite_subject.txt to use {%blocktrans %}, similar to the other template file in that directory.  Oops.  I accidentally added newlines to the subject template, which django-mailer does not like.  I revert to the original join_invite_subject file, and simply hardcode &#8216;GROK Lab&#8217; into the subject string.  Hmm&#8230;still getting the same error messages about newlines in the header, even though I&#8217;ve changed the template.  Oh, the old messages with the bad header are still in the email queue&#8230;its trying to send those, not render new ones based on this template.  I clear out the emails with the bad header out of the database via the admin interface, and email is working again.  Whew&#8230;</p>
<p>The logo image says Pinax.  That&#8217;s no good&#8230;I want to replace that with our lab logo.  Everything is nicely styled with CSS.  My image is a slightly different shape than the pinax logo, so I need to change the height/width in the base.css #tabhead .logo img selector to match my logo file (I made our logo the same height as the original pinax logo to simplify).</p>
<p>This is supposed to be a serious research site, so we probably don&#8217;t need games (although I played some on cloud27 &#8212; they&#8217;re pretty fun, and might be a nice way to encourage a more active community).  I commented out the arcade and games apps in the settings.py, all the related ARCADE_* variables, and the URLpattern in urls.py.  Oops&#8230;many of the templates expect to have the arcade app installed (for example, the navigation tabs are hard coded).  Use grep again to find all mentions of &#8216;arcade,&#8217; and comment them all out.</p>
<p>Finally, there were some functionality that the default installation hides if the user is not logged in.  I wanted to be able to have some read views of the people, projects, blogs, tweets available to anyone who visited the site, but only allow writing if they were logged in.  This involved again grepping through the templates for the right section of code, and adding {% if user.authenticated %} &#8230; {% endif %} tags.</p>
<h3>Step 4 &#8211; Configure site to run through Apache instead of the dev server.</h3>
<p>So I had the site up and running using the django development server on the default port 8000.  But I needed it deployed through apache so that in case of a server restart, I did not have to restart the site by hand.  <a href="http://www.20seven.org/journal/2008/09/pinax-setup-and-deploy.html">The most commonly referenced post for deploying pinax is here</a>.  It gives two sample configurations depending on whether you want to use apache modules mod_wsgi or mod_python.  Which one do I want to use?  What&#8217;s the difference between the two?  No idea.  Look up <a href="http://djangobook.com/en/1.0/chapter20/">django docs on deployment</a>; it seems to recommend mod_python, so I&#8217;ll try that. I wrestle with that for a few hours, but little success.  Back to #pinax, where the consensus is mod_wsgi good, ignore mod_python.  Ok, after another few minutes of messing with my apache site config file, and the pinax.wsgi file, we got it up and running.  A few gotchas:</p>
<ul>
<li>Added the appropriate WSGIScriptAlias to my apache site config.  I could view the site; however, I got errors that apache didn&#8217;t have permissions to write to the db.  Added WSGIDaemonProcess to the site config and that fixed it.</li>
<li>I could access the admin site, but it did not have the correct styles/media.  Needed to add an Alias and Directory commands to the apache site.</li>
<li>Changed the name of the pinax.wsgi to match our site name; need to change the DJANGO_SETTINGS_MODULE variable inside this file</li>
</ul>
<p>So the appropriate section of my apache VirtualHost configuration looks like this:</p>
<p><code># attempt to setup pinax<br />
WSGIScriptAlias / /path/to/your/pinax/project/deploy/pinax.wsgi<br />
WSGIProcessGroup name<br />
WSGIDaemonProcess name user=unixusername group=unixgroup threads=25</code></p>
<p><code>Alias /media/ "/path/to/django/contrib/admin/media/"<br />
&lt;Directory "/path/to/django/contrib/admin/media/"&gt;<br />
Order allow,deny<br />
Options Indexes<br />
Allow from all<br />
IndexOptions FancyIndexing<br />
&lt;/Directory&gt;</code></p>
<p>When debugging this, it was helpful to watch all the appropriate log files to see what error messages were being generated where: <code>tail -f <em>apache.log apacheerror.log projectsend_mail.log project.send_mail_deferred.log</em></code><em></em>.</p>
<h3>Conclusions</h3>
<p>Clearly one area where we can improve pinax is the installation experience.  Compare it to the wordpress install experience&#8230;download into a web accessible directory, open a web page, short configuration, done.</p>
<p>More difficult to deal with is the fact that, in order to use pinax, you need to acquire at least a passing knowledge of django convention and configuration, apache convention and configuration, and all the external apps bundled with pinax.  This can be a tall order.</p>
<p>Still, I got my site up and running, with much more integrated functionality than I would have had with django alone.  I learned alot about pinax, django, and apache, and should have less trouble on my next site.  And I get the desired &#8216;oohs&#8217; and &#8216;ahhs&#8217; and &#8216;damn, how long did it take you to do this?&#8217; from people in the demo.</p>
<p>The next step is a bit more fun.  Now that I&#8217;ve got a basic feel for the technology, I can really think about how to design the site and workflows to best serve the users.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/fitzgeraldsteele.wordpress.com/22/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/fitzgeraldsteele.wordpress.com/22/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/fitzgeraldsteele.wordpress.com/22/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/fitzgeraldsteele.wordpress.com/22/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/fitzgeraldsteele.wordpress.com/22/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/fitzgeraldsteele.wordpress.com/22/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/fitzgeraldsteele.wordpress.com/22/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/fitzgeraldsteele.wordpress.com/22/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/fitzgeraldsteele.wordpress.com/22/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/fitzgeraldsteele.wordpress.com/22/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=22&subd=fitzgeraldsteele&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://fitzgeraldsteele.wordpress.com/2008/10/16/newbies-experience-setting-up-a-pinax-site/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">fitzgeraldsteele</media:title>
		</media:content>
	</item>
		<item>
		<title>Playing with Pinax</title>
		<link>http://fitzgeraldsteele.wordpress.com/2008/10/10/playing-with-pinax/</link>
		<comments>http://fitzgeraldsteele.wordpress.com/2008/10/10/playing-with-pinax/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 21:55:02 +0000</pubDate>
		<dc:creator>fitzgeraldsteele</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[scholarlycommunication]]></category>
		<category><![CDATA[social media]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[pinax]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[research]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://fitzgeraldsteele.wordpress.com/?p=20</guid>
		<description><![CDATA[pinax is cool<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=20&subd=fitzgeraldsteele&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I&#8217;ve had fun this afternoon playing with <a href="http://pinaxproject.com">Pinax</a>, and new social media framework based on <a href="http://www.djangoproject.com">Django</a>.  I got it up and running very quickly, and with very little configuration (changing template files here and there, styles, etc) I&#8217;ve got a brand new website for my <a href="http://groklab.org">research lab</a> that features user profiles, project sites complete with wikis and task assignment, social bookmarking, discussion boards, and a host of other features. I showed it to a couple of my labmates.  They were able to log in and get up and running without any prompting for me, so it seems to have a familiar and easy-to-use-and-learn interface.  Those that were running their own projects enjoyed the project interface, and the ability to link and follow activities of different team members.</p>
<p>I think James and the rest of the Pinax team have hit the nail right on the head.  Out of the box I get about 90% of the functionality I was considering building for our lab.  I&#8217;d like to create and and in a django-references app, which would store citation information, who&#8217;s read what, who&#8217;s written what, etc.</p>
<p>I&#8217;m looking forward to seeing how much functionality I can add in how much time.  This type of thing could really transform scholarly communication:)</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/fitzgeraldsteele.wordpress.com/20/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/fitzgeraldsteele.wordpress.com/20/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/fitzgeraldsteele.wordpress.com/20/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/fitzgeraldsteele.wordpress.com/20/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/fitzgeraldsteele.wordpress.com/20/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/fitzgeraldsteele.wordpress.com/20/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/fitzgeraldsteele.wordpress.com/20/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/fitzgeraldsteele.wordpress.com/20/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/fitzgeraldsteele.wordpress.com/20/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/fitzgeraldsteele.wordpress.com/20/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=20&subd=fitzgeraldsteele&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://fitzgeraldsteele.wordpress.com/2008/10/10/playing-with-pinax/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">fitzgeraldsteele</media:title>
		</media:content>
	</item>
		<item>
		<title>Python tip: Sorting lists by its contents</title>
		<link>http://fitzgeraldsteele.wordpress.com/2008/09/11/python-tip-sorting-lists-by-its-contents/</link>
		<comments>http://fitzgeraldsteele.wordpress.com/2008/09/11/python-tip-sorting-lists-by-its-contents/#comments</comments>
		<pubDate>Thu, 11 Sep 2008 17:05:31 +0000</pubDate>
		<dc:creator>fitzgeraldsteele</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[scholarlycommunication]]></category>
		<category><![CDATA[friendfeed]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[science21]]></category>
		<category><![CDATA[sorting]]></category>

		<guid isPermaLink="false">http://fitzgeraldsteele.wordpress.com/2008/09/11/python-tip-sorting-lists-by-its-contents/</guid>
		<description><![CDATA[Not sure why this was so hard for me to use the sorted() method this morning.
I&#8217;m playing with the FriendFeed API, I wanted to retrieve the entries of a FriendFeed room, and then sort the returned entries by the number of comments&#8230;
Getting the latest 30 entries is a simple HTTP call.  FriendFeed returns a json [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=8&subd=fitzgeraldsteele&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Not sure why this was so hard for me to use the sorted() method this morning.</p>
<p>I&#8217;m playing with the <a href="http://code.google.com/p/friendfeed-api/wiki/ApiDocumentation">FriendFeed API</a>, I wanted to retrieve the entries of a FriendFeed room, and then sort the returned entries by the number of comments&#8230;</p>
<p>Getting the latest 30 entries is a simple HTTP call.  FriendFeed returns a json structure which is nicely parsed with simplejson (soon to be part of the standard python library).</p>
<pre class="brush: python;">
import simplejson
import urllib2

r = urllib2.urlopen('http://friendfeed.com/api/feed/room/science21')
json = simplejson.loads(r.read())

# I just want to look at the entries in the room
e = json['entries']
</pre>
<p>I want to sort the entries by the number of comments.  In other words, I want to use the number of comments as a sort key.  Luckly, <a href="http://wiki.python.org/moin/HowTo/Sorting">Python&#8217;s sorted() method has a key attribute, which takes a callable that returns a single value to be used as a key</a>.  We use the <a href="http://docs.python.org/lib/module-operator.html">operator module</a> in order to generate the sorting key method:</p>
<pre class="brush: python;">
ln = lambda x: len(operator.getitem(x,'comments'))
esorted = sorted(e,key=ln,reverse=True)&lt;/code&gt;

for i in esorted:
print i['title'].encode('utf-8'), len(i['comments'])
</pre>
<p>That took me all morning to get, which shows some of my Python programming limitations.  My first attempt, I tried this:</p>
<p><code>In [94]: es = sorted(e, key=len(operator.itemgetter('comments')))<br />
---------------------------------------------------------------------------<br />
TypeError                                 Traceback (most recent call last)</p>
<p>/home/fitzgeraldsteele/&lt;ipython console&gt; in &lt;module&gt;()</p>
<p>TypeError: object of type 'operator.itemgetter' has no len()<br />
</code><br />
Now I recall that an object must have a .__len__() method in order to work with len().  But operator.itemgetter() returns a function, not an object with a .__len__(), hence the TypeError exceptin I got.</p>
<p>Then I tried this:<br />
<code><br />
esorted = sorted(e, key=lambda x: len(operator.getitem(x,'comments')))<br />
</code><br />
Which is very similar to the solution I ended up with, but this one returns the list in different order.  <span style="text-decoration:line-through;">I&#8217;m not sure why yet</span>. <strong>Update</strong>: Duh&#8230;we get a different order because the first one has reverse=True, and the second one doesn&#8217;t.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/fitzgeraldsteele.wordpress.com/8/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/fitzgeraldsteele.wordpress.com/8/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/fitzgeraldsteele.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/fitzgeraldsteele.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/fitzgeraldsteele.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/fitzgeraldsteele.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/fitzgeraldsteele.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/fitzgeraldsteele.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/fitzgeraldsteele.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/fitzgeraldsteele.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/fitzgeraldsteele.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/fitzgeraldsteele.wordpress.com/8/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=fitzgeraldsteele.wordpress.com&blog=4793962&post=8&subd=fitzgeraldsteele&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://fitzgeraldsteele.wordpress.com/2008/09/11/python-tip-sorting-lists-by-its-contents/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">fitzgeraldsteele</media:title>
		</media:content>
	</item>
	</channel>
</rss>