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

 <title>Dave Dash</title>
 <link href="http://davedash.com/tag/python/atom.xml" rel="self"/>
 <link href="http://davedash.com/tag/python"/>
 <updated>2012-01-17T21:54:19-08:00</updated>
 <id>http://davedash.com/</id>
 <author>
   <name>Dave Dash</name>
   <email>dd+atom1@davedash.com</email>
 </author>

 
 <entry>
   <title>Naming things and a recursion</title>
   <link href="http://davedash.com/2012/01/05/naming-things-and-a-recursion/"/>
   <updated>2012-01-05T00:00:00-08:00</updated>
   <id>http://davedash.com/2012/01/05/naming-things-and-a-recursion</id>
   <content type="html">&lt;p&gt;Most Mozilla webdev projects have an awful project structure, and it's
partially my fault.  I'm &lt;a href=&quot;https://github.com/mozilla/playdoh/pull/67&quot;&gt;attemtping to fix that&lt;/a&gt;, but I
cringe every time someone creates a new &lt;a href=&quot;http://playdoh.rtfd.org/&quot;&gt;playdoh&lt;/a&gt;
(Mozilla's Django template)
based project.&lt;/p&gt;

&lt;h3&gt;The typical python project&lt;/h3&gt;

&lt;p&gt;Your typical python project looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/my_project
    someotherstuff/
    docs/
    theactualthingicareabout/
    setup.py
    LICENSE
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;MOZtrosity&lt;/h3&gt;

&lt;p&gt;We didn't have a good guide when we first started writing Django projects, so
we opted for something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;theactualthingicareabout/
    apps/
        foo/
        bar/
    __init__.py
    urls.py
    settings.py
    LICENSE
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In otherwords, the Django Project, which is a python module, is immediately
checked out.  If you check this out to an invalid directory, e.g. you do something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone github.com/davedash/myawesomeproject.git will.not.work\!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Bad things will happen.&lt;/p&gt;

&lt;h3&gt;So?&lt;/h3&gt;

&lt;p&gt;To some people this seems like an easy thing to work-a-round, but when it takes
three of my excellent coworkers a week to diagnose an issue, where this ended
up being the root cause...  well it becomes a higher priority issue.&lt;/p&gt;

&lt;p&gt;So here's what happened this week, when we tried to deploy
&lt;a href=&quot;https://github.com/mozilla/lumbergh/&quot;&gt;the new careers site&lt;/a&gt; to a VM hardware.&lt;/p&gt;

&lt;p&gt;Our ops team sensibly checked out the project like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone https://github.com/mozilla/lumbergh.git careers
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;They did everything right.  Sure, they were creative and chose &lt;code&gt;careers&lt;/code&gt; over
the default &lt;code&gt;lumbergh&lt;/code&gt;, but they knew the shortcomings of our system and picked
a name that would resolve as a valid python package.&lt;/p&gt;

&lt;p&gt;Unfortunately we'd hit some &lt;em&gt;recursion error&lt;/em&gt; anytime we tried to hit a URL.
So we knew there was an issue with the URL resolver, but we couldn't figure it
out.&lt;/p&gt;

&lt;p&gt;Here's what the project layout looked like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;careers/ # I could be called anything, but they chose careers
    __init__.py
    apps/
        careers/  # I'm going to cause problems,
                  # but neither devs nor ops will suspect a thing! mwahaha
            __init__.py
            models.py
            urls.py
            views.py
    settings.py
    urls.py
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;other files.&lt;/p&gt;

&lt;p&gt;We configure our &lt;code&gt;apps/&lt;/code&gt; directory to be part of our &lt;code&gt;PYTHON_PATH&lt;/code&gt; so we can
do things like &lt;code&gt;from careers import views&lt;/code&gt;... you can probably see where this
is going.&lt;/p&gt;

&lt;p&gt;Here's the main &lt;code&gt;urls.py&lt;/code&gt; &lt;a href=&quot;https://github.com/mozilla/lumbergh/blob/master/urls.py&quot;&gt;1&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;...
urlpatterns = patterns('',
    (r'', include('careers.urls')),
)
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The main &lt;code&gt;urls.py&lt;/code&gt; includes &lt;code&gt;careers.urls&lt;/code&gt; which if you look at the above
project layout, resolves to two different python packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;careers/urls.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;careers/apps/careers/urls.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Python chose the first, and therefore &lt;code&gt;urls.py&lt;/code&gt; kept calling upon itself.&lt;/p&gt;

&lt;h3&gt;So what did we learn?&lt;/h3&gt;

&lt;p&gt;Do better.&lt;/p&gt;

&lt;p&gt;First of all, we need a better project layout. This will continue to cause
problems for even the brightest developers.&lt;/p&gt;

&lt;p&gt;Secondly, if you don't do this at least name apps carefully.
Django's app model can be a bit much for
non third party apps.  Sometimes there's one app which spans the entire
project, and it's tempting to call it the same name as the project
(e.g. &lt;code&gt;careers&lt;/code&gt;), but sometimes a lamer more generic name like &lt;code&gt;common&lt;/code&gt; is
better.&lt;/p&gt;

&lt;p&gt;But really, the second point is moot if we just clean up.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Better querying for ElasticSearch</title>
   <link href="http://davedash.com/2011/05/17/better-querying-for-elasticsearch/"/>
   <updated>2011-05-17T00:00:00-07:00</updated>
   <id>http://davedash.com/2011/05/17/better-querying-for-elasticsearch</id>
   <content type="html">&lt;p&gt;I wrote &lt;a href=&quot;/2011/03/25/filter-queries-using-pyes/&quot;&gt;about how to write filter queries using &lt;code&gt;pyes&lt;/code&gt;&lt;/a&gt;.
Unfortunately after using ElasticSearch in &lt;a href=&quot;http://builder.addons.mozilla.org&quot;&gt;the Add-ons Builder&lt;/a&gt;, I realized
that our code would become unwieldy and hard to read if we kept using straight
up &lt;code&gt;pyes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I prefer to write APIs so that are natural and conform to how I think, not one
that simply mirrors another system.&lt;/p&gt;

&lt;p&gt;So rather than this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;    &lt;span class=&quot;n&quot;&gt;filters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TermFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;platform&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;all&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;TermFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;product&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;firefox&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;TermFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;version&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;4.0&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ANDFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FilteredQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MatchAllQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_term_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I made &lt;a href=&quot;https://github.com/davedash/elasticutils/&quot;&gt;something simpler&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;elasticutils&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;S&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;all&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;firefox&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;4.0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Here were the design thoughts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I wanted something easy to remember, &lt;code&gt;S&lt;/code&gt; for search.&lt;/li&gt;
&lt;li&gt;I wanted smart defaults, by default &lt;code&gt;S()&lt;/code&gt; matches all documents, unless you
give it a query term.&lt;/li&gt;
&lt;li&gt;I didn't want to write python that looked like Java, or JSON or even a
&lt;code&gt;dict&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I wanted to write something that felt like the Django-ORM&lt;/li&gt;
&lt;li&gt;Ultimately I want code that I enjoy writing.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;So here it is, I expect it to power Firefox Add-ons, the Add-ons Builder and
Firefox Input shortly.&lt;/p&gt;

&lt;p&gt;This is all part of &lt;a href=&quot;https://github.com/davedash/elasticutils/&quot;&gt;ElasticUtils&lt;/a&gt;.
Let me know if you are using it, and pull requests are welcome!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How we slug at Mozilla</title>
   <link href="http://davedash.com/2011/03/24/how-we-slug-at-mozilla/"/>
   <updated>2011-03-24T00:00:00-07:00</updated>
   <id>http://davedash.com/2011/03/24/how-we-slug-at-mozilla</id>
   <content type="html">&lt;p&gt;One problem we find with slug generators, is they do an awful job with unicode.
For a string like this: &lt;code&gt;Bän...g (bang)&lt;/code&gt; you get something like
&lt;code&gt;bng---g--bang-&lt;/code&gt; or at best &lt;code&gt;bang-bang&lt;/code&gt;.  But it's 2011, urls can have
unicode... here's what we really want: &lt;code&gt;bäng-bang&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In some cases transliteration might be acceptable.  But if we look at Django's
approach it fails at Russian.  Here's a comparison with ours for the Russian
phrase &quot;Быстрее и лучше!&quot; (&quot;Faster and better!&quot;):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from django.template.defaultfilters import slugify as djslugify
&amp;gt;&amp;gt;&amp;gt; from slugify import slugify
&amp;gt;&amp;gt;&amp;gt; str = u'Быстрее и лучше!'
&amp;gt;&amp;gt;&amp;gt; print djslugify(str)

&amp;gt;&amp;gt;&amp;gt; print slugify(str)
быстрее-и-лучше
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So as you can see, the built-in Django &lt;code&gt;slugify&lt;/code&gt; could be disastrous.  So take
a look at &lt;a href=&quot;https://github.com/mozilla/unicode-slugify&quot;&gt;ours&lt;/a&gt;.  If you have some more test cases, please fork it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bulk load ElasticSearch using pyes</title>
   <link href="http://davedash.com/2011/02/25/bulk-load-elasticsearch-using-pyes/"/>
   <updated>2011-02-25T00:00:00-08:00</updated>
   <id>http://davedash.com/2011/02/25/bulk-load-elasticsearch-using-pyes</id>
   <content type="html">&lt;p&gt;When indexing a lot of data, you can save time by bulk loading data.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;pyes&lt;/code&gt; you can do the following:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyes&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ES&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-index&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-index&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-index&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-index&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This will make 4 independent network calls.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyes&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ES&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-index&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bulk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-index&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bulk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-index&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bulk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-index&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;my-type&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bulk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;refresh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Will do this in one call.  This is handy for those &quot;reindex all the items we
can&quot; weekends.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Installing ElasticSearch plugins</title>
   <link href="http://davedash.com/2011/02/24/installing-elasticsearch-plugins/"/>
   <updated>2011-02-24T00:00:00-08:00</updated>
   <id>http://davedash.com/2011/02/24/installing-elasticsearch-plugins</id>
   <content type="html">&lt;p&gt;I'm slowly trying to familiarize myself with ElasticSearch and the &lt;code&gt;pyes&lt;/code&gt;
python interface.  ElasticSearch uses a lot of plugins, and while the plugin
system is easy to use, it's not obvious where to find the plugins.&lt;/p&gt;

&lt;p&gt;They are &lt;a href=&quot;http://elasticsearch.googlecode.com/svn/plugins/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to install the attachments plugin, you can do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;bin/plugin install mapper-attachments
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And voilà it's installed.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pythonic string formatting in Javascript</title>
   <link href="http://davedash.com/2010/11/19/pythonic-string-formatting-in-javascript/"/>
   <updated>2010-11-19T00:00:00-08:00</updated>
   <id>http://davedash.com/2010/11/19/pythonic-string-formatting-in-javascript</id>
   <content type="html">&lt;p&gt;We do a lot of string manipulation on the &lt;a href=&quot;https://addons.mozilla.org/&quot;&gt;Firefox Addons&lt;/a&gt; site.  A lot of
it has to do with localization so one thing that comes up is being able to
format strings.  Here's a little snippet to give yourself python like string
formatting:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;    &lt;span class=&quot;cm&quot;&gt;/* Python(ish) string formatting:&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     * &amp;gt;&amp;gt;&amp;gt; format(&amp;#39;{0}&amp;#39;, [&amp;#39;zzz&amp;#39;])&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     * &amp;quot;zzz&amp;quot;&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     * &amp;gt;&amp;gt;&amp;gt; format(&amp;#39;{x}&amp;#39;, {x: 1})&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     * &amp;quot;1&amp;quot;&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;re&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/\{([^}]+)\}/g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title>The Python textcluster Package</title>
   <link href="http://davedash.com/2010/07/08/the-python-textcluster-package/"/>
   <updated>2010-07-08T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/07/08/the-python-textcluster-package</id>
   <content type="html">&lt;p&gt;Earlier I wrote about &lt;a href=&quot;http://davedash.com/2010/03/18/finding-the-most-common-firefox-issues/&quot;&gt;finding the most common Firefox issues&lt;/a&gt;.  I had
wanted to automate that process and continually find these issues.
Unfortunately I never had time to do this.&lt;/p&gt;

&lt;p&gt;When they announced &lt;a href=&quot;http://aakash.doesthings.com/2010/06/25/hi-my-name-is-firefox-input/&quot;&gt;Firefox Input&lt;/a&gt;, I thought about doing this again...
just with Firefox Input data but then I went on paternity leave and time kind
of crept away.  But I mentioned the idea this week and it piqued some interest.&lt;/p&gt;

&lt;p&gt;So I found myself with a bit of time to work on it.  The first stage was
releasing a python library called &lt;a href=&quot;http://github.com/davedash/textcluster&quot;&gt;&lt;code&gt;textcluster&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://github.com/davedash/textcluster&quot;&gt;&lt;code&gt;textcluster&lt;/code&gt;&lt;/a&gt; takes the &lt;a href=&quot;http://davedash.com/2010/03/18/finding-the-most-common-firefox-issues/&quot;&gt;work I did earlier&lt;/a&gt; and makes it a bit more
general purpose.  The idea is I can do something like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;docs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;Every good boy does fine.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;Every good girl does well.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;Cats eat rats.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;quot;Rats don&amp;#39;t sleep.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Corpus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;docs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cluster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Which results in:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[
    (
        &quot;Rats don't sleep.&quot;,
        {'Cats eat rats.': 0.21353467285253394}
    ),
    (
        'Every good girl does well.',
        {'Every good boy does fine.': 0.32030200927880093}
    )
]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The number is the &quot;similarity&quot; between the strings relative to the entire
document corpus.&lt;/p&gt;

&lt;p&gt;My next trick is to see if I can run this memory-intensive calculation over a
data-set of 25,000 opinions submitted.  If I can we can get some interesting
data about what people think of the new &lt;a href=&quot;http://www.mozilla.com/en-US/firefox/all-beta.html&quot;&gt;Firefox beta&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>&lambda;^2: safely doing class based views in Django</title>
   <link href="http://davedash.com/2010/03/09/2-safely-doing-class-based-views-in-django/"/>
   <updated>2010-03-09T00:00:00-08:00</updated>
   <id>http://davedash.com/2010/03/09/2-safely-doing-class-based-views-in-django</id>
   <content type="html">&lt;p&gt;When I started rewriting the API for &lt;a href=&quot;https://addons.mozilla.org/&quot;&gt;addons.mozilla.org&lt;/a&gt;, my views were mostly the same: get some data and render it as either JSON or XML.  I also wanted all my API methods to take an &lt;code&gt;api_version&lt;/code&gt; parameter, so I decided class based views would be best.  This way my classes could just inherit from a base class.&lt;/p&gt;

&lt;p&gt;To do this I had to implement a &lt;a href=&quot;http://github.com/davedash/zamboni/blob/b5a147820840e66b542691e7239f15eccdebeec9/apps/api/views.py#L39&quot;&gt;&lt;code&gt;__call__&lt;/code&gt; method&lt;/a&gt;.  This works fine, except I wanted to store things into the class -- after all the whole point of my use of classes was to keep the code a bit more compact, and cleaner.  So, why pass the api_version around everywhere?  Unfortunately thread-safety comes to play, and you need a separate instance of your class for each request.&lt;/p&gt;

&lt;!--more--&gt;


&lt;h3&gt;&amp;lambda;&lt;/h3&gt;

&lt;p&gt;Django's &lt;code&gt;urlpatterns&lt;/code&gt; expects a callable object.  So you can't give it an instance of &lt;code&gt;AddonDetailView()&lt;/code&gt;.  But you could give it a callable that creates an instance of &lt;code&gt;AddonDetailView()&lt;/code&gt; and passes it &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt;.  Luckily python has &lt;code&gt;lambda&lt;/code&gt; functions.  You can &lt;a href=&quot;http://github.com/davedash/zamboni/blob/b5a147820840e66b542691e7239f15eccdebeec9/apps/api/urls.py#L10&quot;&gt;note how we solved that in our &lt;code&gt;urlpatterns&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;&amp;lambda; &amp;lambda;&lt;/h3&gt;

&lt;p&gt;But wrapping all your urls with &lt;code&gt;lambda&lt;/code&gt; is tedious and remembering to pass &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; is error prone.&lt;/p&gt;

&lt;p&gt;So let's make a &lt;code&gt;lambda&lt;/code&gt; function that returns... a &lt;code&gt;lambda&lt;/code&gt; function that &lt;a href=&quot;http://github.com/davedash/zamboni/blob/609ec5467dd6db6a6647f375e95abced5203a1b2/apps/api/urls.py#L9&quot;&gt;turns an instance of our class into a callable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can now return to coding and not think about thread safety.&lt;/p&gt;

&lt;p&gt;&amp;lambda;&amp;lambda;&amp;lambda;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Delicious keeps you in the know</title>
   <link href="http://davedash.com/2009/08/04/delicious-keeps-you-in-the-know/"/>
   <updated>2009-08-04T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/08/04/delicious-keeps-you-in-the-know</id>
   <content type="html">&lt;p&gt;My last task at Delicious was to build along with the amazing &lt;a href=&quot;http://zooie.wordpress.com/&quot;&gt;Vik Singh&lt;/a&gt; was to build a new feed of bookmarks that was heavily influenced by Twitter.  It was one of the most interesting and enjoyable pieces of code that I worked on at Delicious.&lt;/p&gt;

&lt;p&gt;Over two months since my final check-in, the code is &lt;a href=&quot;http://delicious.com/&quot;&gt;now in production&lt;/a&gt;.  It is mostly as intended, but is lacking an RSS or JSON feed (which I had already built).  This is somewhat disappointing since I was hoping that Delicious would remain as open as it had been in the past.&lt;/p&gt;

&lt;p&gt;The algorithm is fairly simple we take a look at what trending topics exist at any moment in time (via Google Trends and Twitter) and we combine it with a list of popular terms.  We take the whole lot of these items and   query search twitter and store an in-memory data table of tweets.  We also take a snapshot of new URLs to the Delicious corpus (basically anything on &lt;a href=&quot;http://delicious.com/recent/&quot;&gt;Delicious recent&lt;/a&gt; with 1 save).  We cluster the Delicious URLs and then find tweets that are similar to each of these clusters.&lt;/p&gt;

&lt;p&gt;The code for this is similar to &lt;a href=&quot;http://zooie.wordpress.com/2009/01/15/twitter-boss-real-time-search/&quot;&gt;Vik's TweetNews&lt;/a&gt; - but I think the Delicious data is a nicer fit.&lt;/p&gt;

&lt;p&gt;We optimized this quite a bit and built a very fast inverted-index and tweaked the code to run in about a minute.  Like TweetNews the heart of this was built using Python.  Python while being a dynamic language is quite amazing for manipulating and iteratiting over sets of data.&lt;/p&gt;

&lt;p&gt;While building this tool, it became my way to feel pulse of what's going on.  I could ditch a lot of my RSS feeds and rely solely on Delicious to be on the up and up.  Unfortunately I can't subscribe to a feed for this.  Either delicious has made a mistake and didn't launch their feeds at the same time as their web (entirely possible, since Delicious hasn't been updated for most of 2009) or they are deliberately taking a step backwards.&lt;/p&gt;

&lt;p&gt;This step backwards is weird from the usability issue.  Delicious has always been a tool that allowed for multiple types of consumers and a tool that appealed to developers thanks to its myriad of RSS and JSON feeds.    I'm glad I didn't have to be on the losing side of that decision.  Delicious relies heavily on Google Trends and Twitter Search.  While there is no requirement for them to share the data they are mashing up, it would be the right thing to do.&lt;/p&gt;

&lt;p&gt;Let me know what you think of the new feeds.  I wish I could share a github link or something snazzy so you could play around with it, but this post should be a good starting point for other real-time data mashups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Read &lt;a href=&quot;http://blog.delicious.com/blog/2009/08/delicious-homepage-gets-%E2%80%9Cfresh%E2%80%9D.html&quot;&gt;Vik's account of this on the Delicious Blog&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>From Delicious to Mozilla</title>
   <link href="http://davedash.com/2009/05/26/from-delicious-to-mozilla/"/>
   <updated>2009-05-26T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/05/26/from-delicious-to-mozilla</id>
   <content type="html">&lt;p&gt;Today I said my good-byes to Delicious.com and Yahoo! and tonight I went to the &lt;a href=&quot;http://blog.mozilla.com/addons/2009/05/26/add-ons-meetup-tonight/&quot;&gt;Addons Meetup&lt;/a&gt; @ Mozilla to get a sneak peak at what I'll be working on in less than two weeks.&lt;/p&gt;

&lt;p&gt;I was thrilled.  I had no idea how many people to expect, but the Mozilla living room was packed - and most people were there the whole time.  Real developers with really cool addons giving feedback to &lt;a href=&quot;http://addons.mozilla.org/&quot;&gt;addons.mozilla.org&lt;/a&gt; directly.  No matter how many blog comments, forums answered, customer care emails I responded to at Delicious - nothing beats the real insight and instant feedback you get from meeting a group of users face to face.&lt;/p&gt;

&lt;p&gt;My brain, because of Delicious is always in data mining and analysis mode so through each presentation and each question asked, my brain was churning through things that I could build to bring some level of utility to the community.&lt;/p&gt;

&lt;p&gt;I'm also happy to be joining an organization where everything is open sourced and available for comment.  So I'm hoping to post a lot more on some of the cool tricks I do at Mozilla.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Reading urlopen and probably any file-ish things in python fast</title>
   <link href="http://davedash.com/2009/05/21/reading-urlopen-and-probably-any-file-ish-things-in-python-fast/"/>
   <updated>2009-05-21T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/05/21/reading-urlopen-and-probably-any-file-ish-things-in-python-fast</id>
   <content type="html">&lt;p&gt;So I've been churning away in my last few days in Delicious-land trying to optimize some python code.&lt;/p&gt;

&lt;p&gt;I was doing essentially this:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
file = urlopen(&quot;http://myhost.com/my.json&quot;)

for line in file:
  pass

&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;and it was taking almost a minute... for a ~3000 line json feed.  Being the n00b that I am, I started getting my python learn on... and thought... an open url connection seems like a bad idea... let's do this:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
file = urlopen(&quot;http://myhost.com/my.json&quot;)
lines = file.read().split(&quot;\n&quot;)

for line in lines:
  pass

&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;Zoom!  Took less than a second... actually putting real code in their (e.g. &lt;code&gt;simplejson.loads()&lt;/code&gt;) bumped it to 2 seconds.  Hooray.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Python Generators</title>
   <link href="http://davedash.com/2009/04/08/python-generators/"/>
   <updated>2009-04-08T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/04/08/python-generators</id>
   <content type="html">&lt;p&gt;Someone had mentioned &quot;generators&quot; in python to me, so I decided to figure out what it was... and I figured it out.  I think a simple example would help explain it:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
&gt;&gt;&gt; def fib():
...  i1 = 0
...  i2 = 1
...  while True:
...    yield i2
...    i3 = i2 + i1
...    i1 = i2
...    i2 = i3
... 
&gt;&gt;&gt; a = fib()
&gt;&gt;&gt; a
&lt;generator object at 0x319468&gt;
&gt;&gt;&gt; a.next()
1
&gt;&gt;&gt; a.next()
1
&gt;&gt;&gt; a.next()
2
&gt;&gt;&gt; a.next()
3
&gt;&gt;&gt; a.next()
5
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;Basically you can iterate over this &quot;generator&quot; which is a special function that &quot;yield&quot;s more than one value if you keep pinging it.&lt;/p&gt;

&lt;p&gt;Adding this to the toolkit in my brain.  I'm thinking one potential use is taking a resultset from a datastore (e.g. mysql) and converting it into an object.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>A stitch in Fabric saves time</title>
   <link href="http://davedash.com/2009/03/02/a-stitch-in-fabric-saves-time/"/>
   <updated>2009-03-02T00:00:00-08:00</updated>
   <id>http://davedash.com/2009/03/02/a-stitch-in-fabric-saves-time</id>
   <content type="html">&lt;p&gt;Each day as I grow as a developer I pick up better habits.  One is automating anything that I'll have to do more than once.&lt;/p&gt;

&lt;p&gt;Therefore, deploying important projects has evolved:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edit files live on the site.&lt;/li&gt;
&lt;li&gt;FTP files from my local machine onto the live site and do tweaking as needed.&lt;/li&gt;
&lt;li&gt;Develop using a cross-platform capable framework and deploy live via rsync.&lt;/li&gt;
&lt;li&gt;One step deployment.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;I looked at a few methods for performing one-step deployment.  Shell scripts seemed to basic, and things like Puppet seemed to large a scale.  So I looked into Capistrano and &lt;a href=&quot;http://www.nongnu.org/fab/&quot;&gt;Fabric&lt;/a&gt;, and settled on &lt;a href=&quot;http://www.nongnu.org/fab/&quot;&gt;Fabric&lt;/a&gt;, because it was barebones and python.&lt;/p&gt;

&lt;p&gt;I'm at a stage with my project where I need to test it on an external server, so rather than uploading it and winging it I actually thought about a few things.&lt;/p&gt;

&lt;!--more--&gt;


&lt;h3&gt;The task&lt;/h3&gt;

&lt;p&gt;I was thinking the ideal situation is a single command line that I can type that will upload my files to the server.  Furthermore it should upload first to a new directory and then symlink and restart the server to do the cutover.  I can easily write another script to rollback.&lt;/p&gt;

&lt;p&gt;The way I setup my Nginx and Apache servers was they would look for the symlinks: staging, test, production to serve up the respective environments (I'm using a single host for this example).&lt;/p&gt;

&lt;h3&gt;Directory Structure&lt;/h3&gt;

&lt;p&gt;I use a very particular directory structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$WWW_APPS/mysite.com/&lt;/code&gt; - is my root app deployment directory.

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;releases/&lt;/code&gt; - each code push is stored in a unique directory

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;&lt;code&gt;100/&lt;/code&gt; - the directory name is the &lt;code&gt;svn&lt;/code&gt; revision, but is a series of precise &lt;code&gt;svn&lt;/code&gt; exports, not a checkout.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;staging&lt;/code&gt; - this symbolic link links to a specific revision directory that has been designated for staging purposes.  This might be the last directory in &lt;code&gt;releases/&lt;/code&gt;, e.g. &lt;code&gt;$WWW_APPS/mysite.com/releases/100/&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;config/&lt;/code&gt; - any config files go here (e.g. nginx or apache)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mysite.com/&lt;/code&gt; - the actual Django project&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scripts/&lt;/code&gt; - any utility scripts, mostly database model changes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;site-packages/&lt;/code&gt; - any related libraries that I need, this isn't the best approach I need to investigate &lt;code&gt;virtualenv&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;static/&lt;/code&gt; - all my static assets go here&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;staging.rollback&lt;/code&gt; - the former &lt;code&gt;staging&lt;/code&gt; symlink is demoted to &lt;code&gt;staging.rollback&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$WWW/mysite.com/&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;staging&lt;/code&gt; - This is where the static assets get served from according to nginx.  It's a symbolic link to &lt;code&gt;$WWW_APPS/staging/static&lt;/code&gt;.  This link does not change during deployment.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uploads_staging/&lt;/code&gt; - This directory contains uploads (user data).  It requires manual adjustment when there are data changes (deletes, adds, updates).  For the most part it can stay unchanged from one deployment to the next.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Subversion&lt;/h3&gt;

&lt;p&gt;I'm currently using subversion to maintain my code.  If you are starting a project anew, I suggest using &lt;code&gt;git&lt;/code&gt; as it is designed with branching in mind.  The script below should be adaptable for &lt;code&gt;git&lt;/code&gt; instead of &lt;code&gt;svn&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That being said, when I deploy code, I use the revision number as the directory name for that deployment (e.g. &lt;code&gt;$WWW_APPS/mysite.com/releases/100/&lt;/code&gt; for &lt;code&gt;r100&lt;/code&gt;) .&lt;/p&gt;

&lt;p&gt;This forces me to commit my changes and not deploy code that is not checked in.&lt;/p&gt;

&lt;p&gt;Other viable alternatives would be time-stamped directories.  Anything that is unique between deployments will be sufficient.&lt;/p&gt;

&lt;h3&gt;The &lt;code&gt;fabfile.py&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Here's the &lt;code&gt;fabfile.py&lt;/code&gt; I constructed.  It's by no means final&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
def staging():
    &quot;Pushes current code to staging, hups Apache&quot;
    # get the build number    
    local('svn up mysite.com')
    
    config.svn_version   = svn_get_version()
    
    if not config.svn_version:
        abort()
    
    config.static_path   = '/var/www/static.mysite.com'
    config.svn_path      = 'http://svn.mysite.com/trunk'
    config.svn_export    = 'svn export -q -r %(svn_version)s'
    
    run('mkdir %(path)s', fail='abort')
    
    # svn export mysite.com to path 
    run('%(svn_export)s %(svn_path)s/mysite.com %(path)s/mysite.com', fail='abort')
    
    # svn export site-packages to site-packages
    run('%(svn_export)s %(svn_path)s/site-packages %(path)s/site-packages', fail='abort')
    
    # svn export mysite.com to path 
    run('%(svn_export)s %(svn_path)s/scripts %(path)s/scripts', fail='warn')
    
    # svn export configs
    run('%(svn_export)s %(svn_path)s/config %(path)s/config', fail='abort')
    
    # export /var/www/static.mysite.com/releases/%(svn_version) 
    run('%(svn_export)s %(svn_path)s/static %(path)s/static', fail='abort')
    
    # symlink to images from /var/www/static.mysite.com/staging/images/menuitems/* new release dir
    run(&quot;rm -r %(path)s/static/images/menuitems&quot;, fail=abort)
    run(&quot;ln -s %(static_path)s/menuitems_staging %(path)s/static/images/menuitems&quot;, fail=abort)

    # rotate &quot;staging&quot; symlinks
    run('rm %(releases_path)s/staging.rollback', fail='warn')
    run('mv %(releases_path)s/staging  %(releases_path)s/staging.rollback', fail='warn')

    # staging sym to new destination
    run('ln -s %(path)s %(releases_path)s/staging', fail='abort')
    
    # server is hup'd
    invoke(hup)

def rm_cur_rev():
    config.svn_version   = svn_get_version()
    run('rm -rf %(path)s', fail='abort')

def hup():
    sudo('/etc/init.d/apache2 restart')
    sudo('/etc/init.d/nginx restart')
    
    
def svn_get_version():
    from subprocess import Popen, PIPE
    output = Popen([&quot;svn&quot;, &quot;info&quot;, &quot;mysite.com&quot;], stdout=PIPE).communicate()[0]
    return output.partition('Revision: ')[2].partition('\n')[0]



config.fab_hosts = ['mysite.com']
config.fab_user = 'builder'
config.releases_path = '/var/www_apps/mysite.com'
config.path          = '%(releases_path)s/releases/$(svn_version)'


&lt;/textarea&gt;&lt;/div&gt;


&lt;h3&gt;Final Thoughts&lt;/h3&gt;

&lt;p&gt;There's room for improvement, but this is a start.  &lt;code&gt;virtualenv&lt;/code&gt; looks like another avenue I might want to explore (especially when it comes time to upgrade Django, python, MysqlDB or PIL).  This also doesn't take care of priming the server with necessary packages - again, something &lt;code&gt;virtualenv&lt;/code&gt; could make easier for me.&lt;/p&gt;

&lt;p&gt;However, this file was not too difficult to create.  I sat down, thought about the ideal solution, implemented the steps and iterated on that until the script worked.  I have pushed 19 revisions of code so far, mostly to test this process, but also to make necessary adjustments.  I've probably saved countless hours of logging in and doing things manually.&lt;/p&gt;

&lt;p&gt;How do you deploy your apps?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Versioning Django Models</title>
   <link href="http://davedash.com/2009/02/13/versioning-django-models/"/>
   <updated>2009-02-13T00:00:00-08:00</updated>
   <id>http://davedash.com/2009/02/13/versioning-django-models</id>
   <content type="html">&lt;p&gt;In symfony, versioning a model was not terribly difficult.  I had my own specialized brute-force way of doing this.&lt;/p&gt;

&lt;p&gt;In my experience it's been a lot easier to write python code than PHP code, so naturally I figured this would be an easy task.  It was not.  I suspect that it was not easy because I have a naive understanding of Django and my symfony knowledge was fairly well grounded.&lt;/p&gt;

&lt;p&gt;I tried looking for a generic implementation of django model versioning, but failed.  So I came up with a specific solution.&lt;/p&gt;

&lt;!--more--&gt;


&lt;h3&gt;How I think of versions&lt;/h3&gt;

&lt;p&gt;For my app I chose to use a sparse versioning system.  I'd have one interface for interacting with a model.  For example, I have a &lt;code&gt;Restaurant&lt;/code&gt; model  and a &lt;code&gt;RestaurantVersion&lt;/code&gt; model.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Restaurant&lt;/code&gt; would directly store immutable elements like &lt;code&gt;name&lt;/code&gt; or &lt;code&gt;rating&lt;/code&gt; or &lt;code&gt;approved&lt;/code&gt; and it would encapsulate versioned elements like &lt;code&gt;description&lt;/code&gt; by proxying to &lt;code&gt;RestaurantVersion&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means I only need to interface with one class and let the versioning happen behind the scenes.&lt;/p&gt;

&lt;h3&gt;The Django implementation of &lt;code&gt;RestaurantVersion&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;RestaurantVersion&lt;/code&gt; held the data that I thought might suffer from corruption, and therefore require reversion.  Therefore there's nothing surprising in this table:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
class RestaurantVersion(models.Model):
    restaurant       = models.ForeignKey('Restaurant', null=True, blank=True)
    user             = models.ForeignKey(Profile, null=True, blank=True)
    description      = models.TextField(blank=True)
    html_description = models.TextField(blank=True)
    url              = models.CharField(max_length=765, blank=True)
    created_at       = models.DateTimeField(auto_now_add=True)
    
    def save(self, force_insert=False, force_update=False):
        self.html_description = markdown(self.description)
        super(RestaurantVersion, self).save(force_insert, force_update)
        
    class Meta:
        db_table = u'restaurant_version'

&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;The only thing of note is that I'm enforcing a &lt;code&gt;1:M&lt;/code&gt; relation between &lt;code&gt;Restaurant&lt;/code&gt; and &lt;code&gt;RestaurantVersion&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;The Django implementation of &lt;code&gt;Restaurant&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Restaurant&lt;/code&gt; is where the magic happens.  It needs to do a few things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do what a normal object does.&lt;/li&gt;
&lt;li&gt;Proxy attributes to the corresponding attribute of a &lt;code&gt;RestaurantVersion&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Generate a new &lt;code&gt;RestaurantVersion&lt;/code&gt; on demand.&lt;/li&gt;
&lt;li&gt;(optional) Manage which version is &quot;active&quot;.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;I say &quot;4&quot; is optional because I don't do this myself.  I built versioning into a few models because it was easier to do upfront than worry about it down the road.&lt;/p&gt;

&lt;p&gt;Here's the code I use:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;

class Restaurant(models.Model):
    name           = models.CharField(max_length=765, blank=True)
    stripped_title = models.CharField(max_length=384, blank=True)
    approved       = models.IntegerField(null=True, blank=True)
    version        = models.ForeignKey(RestaurantVersion, related_name=&quot;the_restaurant&quot;)
    updated_at     = models.DateTimeField(auto_now=True)
    created_at     = models.DateTimeField(auto_now_add=True)
    new_version    = None
    
    def save(self, force_insert=False, force_update=False):
        if not self.stripped_title:
            self.stripped_title = slugify(self.name)
        
        super(Restaurant, self).save(force_insert, force_update)
        if self.new_version:
            self.new_version.restaurant = self
            self.new_version.save()
            self.version = self.new_version
            super(Restaurant, self).save(force_insert, force_update)        
        
    def __setattr__(self, name, value):
        if name == 'description':
            self.get_new_version().description = value
        
        elif name == 'url':
            self.get_new_version().url = value
        
        else:
            object.__setattr__(self, name, value)

    def __getattr__(self, name):
        try:
            if name == 'description':
                return self.version.description

            elif name == 'url':
                return self.version.url
        except RestaurantVersion.DoesNotExist:
            return ''
            
        models.Model.__getattribute__(self, name)
    
    def get_new_version(self):
        if self.new_version == None:
            try:
                rv    = self.version
                rv.id = None
            except RestaurantVersion.DoesNotExist:
                rv = RestaurantVersion()
            
            self.new_version = rv

        return self.new_version
            
    class Meta:
        db_table     = u'restaurant'
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;It's not rocket science, but it wasn't necessarily easy either.  Let's look at requirements 2 and 4 in a bit more detail.&lt;/p&gt;

&lt;h4&gt;Proxy attributes to the corresponding &lt;code&gt;RestaurantVersion&lt;/code&gt; attributes&lt;/h4&gt;

&lt;p&gt;Proxying attributes is a way of masking the whole versioning infrastructure from the developer.  We do this with &lt;code&gt;__getattr__&lt;/code&gt; and &lt;code&gt;__setattr__&lt;/code&gt; methods.&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
    def __getattr__(self, name):
        try:
            if name == 'description':
                return self.version.description

            elif name == 'url':
                return self.version.url
        except RestaurantVersion.DoesNotExist:
            return ''
            
        models.Model.__getattribute__(self, name)
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;__getattr__&lt;/code&gt; determins if you are looking for &lt;code&gt;description&lt;/code&gt; or &lt;code&gt;url&lt;/code&gt; attributes of a &lt;code&gt;Restaurant&lt;/code&gt;.  If you are then it uses the current &lt;code&gt;RestaurantVersion&lt;/code&gt;'s attribute.&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
    def __setattr__(self, name, value):
        if name == 'description':
            self.get_new_version().description = value
        
        elif name == 'url':
            self.get_new_version().url = value
        
        else:
            object.__setattr__(self, name, value)
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;__setattr__&lt;/code&gt; is very similar, except since we're changing a versionable attribute we're going to make a request to a method, &lt;code&gt;get_new_version()&lt;/code&gt;, which we will detail later.  It does what it says, though, it gets the &quot;new&quot; &lt;code&gt;RestaurantVersion&lt;/code&gt; of the &lt;code&gt;Restaurant&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;Generate a new &lt;code&gt;RestaurantVersion&lt;/code&gt; on demand&lt;/h4&gt;

&lt;p&gt;As you can see from the above code, I am &quot;auto-versioning&quot;.  This is done mostly via &lt;code&gt;get_new_version()&lt;/code&gt;.  We also have to do a few tricks to make sure the bidirectional relationship gets maintained on save.&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
    def get_new_version(self):
        if self.new_version == None:
            try:
                rv    = self.version
                rv.id = None
            except RestaurantVersion.DoesNotExist:
                rv = RestaurantVersion()
            
            self.new_version = rv

        return self.new_version
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;get_new_version()&lt;/code&gt; either returns the current &quot;new version&quot;, a brand new &quot;new version&quot; or a &quot;copy&quot; of the current version.&lt;/p&gt;

&lt;p&gt;The &quot;copy&quot; is done simply by setting the &lt;code&gt;id&lt;/code&gt; attribute of the new version to &lt;code&gt;None&lt;/code&gt;.  Django takes care of assigning it a new &lt;code&gt;id&lt;/code&gt; on save, thus preserving the old version.&lt;/p&gt;

&lt;p&gt;Note that when we create a brand new &lt;code&gt;RestaurantVersion&lt;/code&gt;, we don't immediately set it's &lt;code&gt;restaurant&lt;/code&gt; attribute.  That's because we haven't saved the current &lt;code&gt;restaurant&lt;/code&gt; yet.  It's a &quot;chicken and the egg&quot; problem that gets solved in our &lt;code&gt;save()&lt;/code&gt; method:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
    def save(self, force_insert=False, force_update=False):
        if not self.stripped_title:
            self.stripped_title = slugify(self.name)
        
        super(Restaurant, self).save(force_insert, force_update)
        if self.new_version:
            self.new_version.restaurant = self
            self.new_version.save()
            self.version = self.new_version
            super(Restaurant, self).save(force_insert, force_update)
        
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;We first save the &lt;code&gt;Restaurant&lt;/code&gt;, then we save a new version if there is one.  If we save a new version we want to update the &lt;code&gt;Restaurant&lt;/code&gt; a second time.  This ensures that there's a &lt;code&gt;1:1&lt;/code&gt; relationship between &lt;code&gt;Restaurant&lt;/code&gt; and the current &lt;code&gt;RestaurantVersion&lt;/code&gt; and it also establishes a &lt;code&gt;1:M&lt;/code&gt; relationship between &lt;code&gt;Restaurant&lt;/code&gt; and &lt;em&gt;all&lt;/em&gt; &lt;code&gt;RestaurantVersion&lt;/code&gt;s.&lt;/p&gt;

&lt;h3&gt;Conclusion and Drawbacks&lt;/h3&gt;

&lt;p&gt;While, I think that this setup works in my particular situation, I feel like it has some major flaws.&lt;/p&gt;

&lt;p&gt;The code is quite messy and very specific to this model.  My goal was to take care of this quickly, not necessarily in a reusable manner.  I also was not familiar enough with the Django model to create some sort of extension.&lt;/p&gt;

&lt;p&gt;This way of versioning does not allow for versioned attributes to be set upon instantiation of the model:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;r=Restaurant(description=&quot;Great place&quot;) 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;won't work.  You'll have to do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;r=Restaurant()
r.description=&quot;Great place&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I figured this was acceptable.&lt;/p&gt;

&lt;p&gt;Lastly I'm not entirely happy with having to explicitly save the &lt;code&gt;Restaurant&lt;/code&gt; model twice, but I think my bidirectional relation requires this.&lt;/p&gt;

&lt;p&gt;All in all this works in my particular situation.  I'm hoping that this can be simplified.  I'm curious to hear about other versioning schemes.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PHPs strengths: array_count_values</title>
   <link href="http://davedash.com/2008/12/07/phps-strengths-array_count_values/"/>
   <updated>2008-12-07T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/12/07/phps-strengths-array_count_values</id>
   <content type="html">&lt;p&gt;I always like to think of what different interpreted programming languages bring to the table.&lt;/p&gt;

&lt;p&gt;Perl is great with string manipulation.  I tend to use perl if I need to rewrite/reformat text.&lt;/p&gt;

&lt;p&gt;Python makes it easy to write clean, organized code and has a lot of syntactical sugar like list comprehensions.&lt;/p&gt;

&lt;p&gt;For PHP one of my coworkers suggested that maybe it's ease is what it brings to the table.  I've accepted that wryly at first, but after some thought it's actually a real strength.&lt;/p&gt;

&lt;p&gt;PHP has positioned itself to be easily adoptable.  When I learned PHP/FI 2.0 it was because I had exhausted server-side includes and needed something better.  PHP/FI was a great solution because it was easy to install (my ISP had it) and documented easy things that I could do.  After all it was just some additional changes to my templates.&lt;/p&gt;

&lt;p&gt;I never for once thought that I'd be paid at a company to code in it... but then the internet just got big.&lt;/p&gt;

&lt;p&gt;The other way php positioned itself is the library of functions it has out of the box.  Today I found myself looking for a python equivalent to &lt;a href=&quot;http://www.php.net/array_count_values&quot;&gt;&lt;code&gt;array_count_values&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Its a function I wouldn't use every day, but there are rare instances where having a set of data aggregated by count would be very useful.  That's exactly what this function does.&lt;/p&gt;

&lt;p&gt;Even python's lists, sets and dictionaries, which can do with simple operations what PHP needs an army of &lt;code&gt;array_&lt;/code&gt; functions to do, didn't reveal anything useful.  So I will use the following:&lt;/p&gt;

&lt;div&gt;
&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
def list_count_values(l):
    d = {}
    
    for item in l:
        if item in d:
            d[item] += 1
        else:
            d[item] = 1
    
    return d
&lt;/textarea&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>Python String Formatting</title>
   <link href="http://davedash.com/2008/12/06/python-string-formatting/"/>
   <updated>2008-12-06T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/12/06/python-string-formatting</id>
   <content type="html">&lt;p&gt;Python 2.6 (and Py3K) introduce a new way to format strings.  Perviously you did this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&quot;%s, Here is my string, %s!&quot; % ('Salutations', 'Dave')
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&quot;{0}, Here is my string, {1}!&quot;.format('Salutations','Dave')
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At first glance this looks like syntactical-sugar.  But now you can do some clever things (which you could have done before, but I think are more intuitive now).  You can easily repeat strings:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def tag(name, value):
    return &quot;&amp;lt;{0}&amp;gt;{1}&amp;lt;/{0}&amp;gt;&quot;.format(name, value)
&lt;/code&gt;&lt;/pre&gt;
</content>
 </entry>
 
 <entry>
   <title>postgresql and python in osx</title>
   <link href="http://davedash.com/2008/08/10/postgresql-and-python-in-osx/"/>
   <updated>2008-08-10T00:00:00-07:00</updated>
   <id>http://davedash.com/2008/08/10/postgresql-and-python-in-osx</id>
   <content type="html">&lt;p&gt;I want to start dabbling with postgreSQL on OS X.  After several SVN checkouts, binary packages, etc, I've realize the easiest path to success is just installing from fink unstable.&lt;/p&gt;

&lt;p&gt;Running:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;fink install psycopg2-py2.5
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;will get you everything you need, &lt;code&gt;python&lt;/code&gt;, the &lt;code&gt;pyscopg2&lt;/code&gt; driver and even &lt;code&gt;postgresql&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately I had MacPython binary and a postgres binary which I couldn't easily install (and if anybody knows how to uninstall at least the former, I'm all ears).  I decided to just merge the site-packages for both the fink installed python2.5 and the MacPython:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rm -rf /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/
$ ln -s /sw/lib/python2.5/site-packages /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now if I installed more python packages via fink they will work in MacPython.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>py vs php: stemming</title>
   <link href="http://davedash.com/2008/02/16/py-vs-php-stemming/"/>
   <updated>2008-02-16T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/02/16/py-vs-php-stemming</id>
   <content type="html">&lt;p&gt;I've been porting some PHP to python during SuperHappyDevHouse and was amazed at how little code I needed to write since python makes list manipulation a breeze.&lt;/p&gt;

&lt;p&gt;Today I was working on stemming (ala &lt;a href=&quot;http://tartarus.org/martin/PorterStemmer/&quot;&gt;Porter Stemming algorithm&lt;/a&gt;).  &lt;a href=&quot;http://reviewsby.us/&quot;&gt;reviewsby.us&lt;/a&gt; uses stemming in the search engine to make queries:&lt;/p&gt;

&lt;p&gt;Stemming turns &lt;code&gt;hello everybody how are you guy's&lt;/code&gt; into a collection &lt;code&gt;'everybodi', 'gui', 'hello'&lt;/code&gt;.  To produce this in php I do the following:&lt;/p&gt;

&lt;!--more--&gt;




&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;php&quot;&gt;
    public static function stemPhrase($phrase)
    {
        // remove apostrophe's and periods
        $phrase = strtolower(str_replace(array('\'', '.'), null, $phrase));
        
        // split into words
        $words = str_word_count($phrase, 1);

        // ignore stop words
        $words = array_diff($words, STOP_WORDS_ARRAY);

        // stem words
        $stemmed_words = array();

        foreach ($words as $word)
        {
            $stemmed_words[] = PorterStemmer::stem($word, true);
        }

        return $stemmed_words;
    }
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;With some magic python:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
def stem_phrase(phrase):
    words = phrase.lower().replace('.','').replace(&quot;'&quot;,'').split()

    # ignore stop words
    words = list(set(words)-set(STOP_WORDS))

    p = PorterStemmer()
    
    return [p.stem(word,0,len(word)-1) for word in words]

&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;The magic here is list mappings.  Learning about them, they don't seem that great, but as soon as you start coding you stop using a lot of for loops.&lt;/p&gt;

&lt;p&gt;I'm sure my PHP can be cleaned up and reduced as well, but its fun exploiting the magic of languages.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>unix timestamp in python</title>
   <link href="http://davedash.com/2008/02/14/unix-timestamp-in-python/"/>
   <updated>2008-02-14T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/02/14/unix-timestamp-in-python</id>
   <content type="html">&lt;p&gt;I spent far too much time learning that:&lt;/p&gt;

&lt;div&gt;&lt;textarea class=&quot;python&quot; name=&quot;code&quot;&gt;
from time import time
print time()
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;gives me the nice numeric representation of the unix timestamp.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>the magic of django: get_callable</title>
   <link href="http://davedash.com/2008/02/08/the-magic-of-django-get_callable/"/>
   <updated>2008-02-08T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/02/08/the-magic-of-django-get_callable</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://symfony-project.com/&quot;&gt;symfony&lt;/a&gt; is an amazing framework simply because of the uphill battle it has
with PHP.  There's a lot of behind the scenes magic that ameliorates the
frustrations one might have with PHPs lack of syntactical magic.&lt;/p&gt;

&lt;p&gt;A lot of work is done to make sure certain things are autoloaded and that
certain things behave the way you expect.&lt;/p&gt;

&lt;p&gt;I hadn't had a chance to peek under Django's hood too much myself, but it
appears that despite the inherent magic of python, there were some much needed
additions.  My savior for today was &lt;code&gt;get_callable&lt;/code&gt;.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;I have a very particular vision of interacting with OpenID.  Basically I like
to decouple as much of the OpenID interactions away from the inner workings of
my web site.  I do, however, want a hook where I can supply some of my own
logic after OpenID has been verified.&lt;/p&gt;

&lt;p&gt;It's roughly how I implimented the sfOpenIDPlugin.   Luckily this time, I was
able to rely on the &lt;a href=&quot;http://www.openidenabled.com/openid/libraries/python/&quot;&gt;OpenID 2.1
libraries&lt;/a&gt; from
OpenIDEnabled.&lt;/p&gt;

&lt;p&gt;I did ditch their example code, because I wanted a sexy package.  The package
isn't quite ready for primetime, but you can &lt;a href=&quot;http://svn.spindrop.us/django/trunk/&quot;&gt;have a
gander&lt;/a&gt; (and yes, I do welcome
collaborators and am open to merging my work with the myriad of work that's out
there).&lt;/p&gt;

&lt;h3&gt;Getting to the point&lt;/h3&gt;

&lt;p&gt;Anyway, &lt;code&gt;get_callable&lt;/code&gt; is what allowed me to write my &quot;hook&quot; into my OpenID
logic.&lt;/p&gt;

&lt;p&gt;In my &lt;code&gt;settings.py&lt;/code&gt; I defined:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;OPENID_SUCCESS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;myproject.myapp.views.openid_handler&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The way my OpenID library works, is it does it's business and when it verifies
a url belongs to someone it then delivers he request to the &lt;code&gt;OPENID_SUCCESS&lt;/code&gt;
hook.  Here's how:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OPENID_SUCCESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_callable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OPENID_SUCCESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;get_callable&lt;/code&gt; works some python magic by splitting
&lt;code&gt;myproject.myapp.views.openid_handler&lt;/code&gt; into the module: &lt;code&gt;myproject.myapp.views&lt;/code&gt;
and the attribute &lt;code&gt;openid_handler&lt;/code&gt;.  It uses this to produce a callable object.
In the example above I gave it parameters of &lt;code&gt;request&lt;/code&gt; and &lt;code&gt;result&lt;/code&gt; as they
were required by my app.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Templating</title>
   <link href="http://davedash.com/2008/01/28/templating/"/>
   <updated>2008-01-28T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/01/28/templating</id>
   <content type="html">&lt;p&gt;[tags]smarty, symfony, php, python, django[/tags]&lt;/p&gt;

&lt;p&gt;I used to use the Smarty templating system quite heavily in my PHP apps.  Then after switching over to &lt;a href=&quot;http://symfony-project.com/&quot;&gt;symfony&lt;/a&gt;, I broke that habit.&lt;/p&gt;

&lt;p&gt;PHP &lt;em&gt;is&lt;/em&gt; a templating language for better or worse.  Smarty was a way of saying that &quot;well things could be easier&quot;, but that's against the grain of what PHP fundamentally is.&lt;/p&gt;

&lt;p&gt;One frustration of PHP is this.  A &quot;pure&quot; PHP file with no HTML looks like this:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;php&quot;&gt;
    &lt;?php
    
    // code goes here
    // ...
    
    // end of file
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;PHP is an HTML templating system, by default everything in PHP is just stuff waiting to be sent untouched to the browser.  So in essence, PHP web apps aren't really web apps... they are very complicated templates all talking to each other.&lt;/p&gt;

&lt;p&gt;So you'll note in the above example, even a pure PHP file must begin with &lt;code&gt;&amp;lt;?php&lt;/code&gt;, and signal that we're actually doing code.  In fact, to prevent any unintended whitespace being sent to the browser, a PHP only file will by convention omit the closing &lt;code&gt;?&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So my shiny new Django framework is a breath of fresh air.  There's no &lt;code&gt;&amp;lt;?py&lt;/code&gt; tags, it's all just python.  And template files are explicitly template files parsed by a template engine built on top of a scripting language.&lt;/p&gt;

&lt;p&gt;I can easily see PHP evolving into something similar one day.  Where all PHP files are just PHP by default.  It would be more in line with the way MVC development is going.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>python: relative paths</title>
   <link href="http://davedash.com/2008/01/27/python-relative-paths/"/>
   <updated>2008-01-27T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/01/27/python-relative-paths</id>
   <content type="html">&lt;p&gt;So I started yesterday with Django, and I decided I didn't want to futz with creating another mysql database that I'd need to manage, etc.  Instead I'll just use &lt;code&gt;sqlite&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I wanted to keep my &lt;code&gt;sqlite&lt;/code&gt; database within my project regardless of where I might move my project later.  So I did this:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
    import os        
    DATABASE_NAME = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data/db.sqlite')        # Or path to database file if using sqlite3.
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;I confused a lot of people on IRC, but it's really quite easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;__file__&lt;/code&gt; is the filename of the current script, very similar to PHP's &lt;code&gt;__FILE__&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;os.path.abspath&lt;/code&gt; calculates the absolute path, hence the absolute path of the current file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;os.path.join&lt;/code&gt; does all the nasty business of joining paths together and figuring out what type of slashes are needed, etc.&lt;/li&gt;
&lt;li&gt;'data/db.sqlite' is a string&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;So really all we were doing is creating a relative path, but setting it absolutely.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>python: it begins</title>
   <link href="http://davedash.com/2008/01/26/python-it-begins/"/>
   <updated>2008-01-26T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/01/26/python-it-begins</id>
   <content type="html">&lt;p&gt;[tags]php, python, symfony, frameworks, programming[/tags]&lt;/p&gt;

&lt;p&gt;The problem I have with python, is I really like what I can do with it, and it makes me hate that I have to use PHP.&lt;/p&gt;

&lt;p&gt;PHP works.  I've used it for over 10 years without problem.  My web development methodology was this: I want to do &lt;code&gt;x&lt;/code&gt;, but I need to first learn &lt;code&gt;y&lt;/code&gt;.  Well one day &lt;code&gt;y&lt;/code&gt; became PHP/FI and then PHP 3 and then PHP 4 and then PHP5.  It was a natural progression.&lt;/p&gt;

&lt;p&gt;I came from a (what was at the time) traditional C/C++/Java background and decided that PHP while amateurish was still a better solution for web development.  A few years later I was proven right by companies like Yahoo! and Facebook.&lt;/p&gt;

&lt;p&gt;I did have my issues, and I worked through them, symfony and other frameworks like it, have made PHP development so much better, but eventually you get let in on little secrets.  Secrets like other scripting languages.&lt;/p&gt;

&lt;p&gt;In the last year I dabbled with ruby, but decided I didn't want to look at rails.  A few people pointed me in the direction of python and Django as an alternative to PHP alternatives.  So I've spent time learning python.&lt;/p&gt;

&lt;p&gt;Yesterday and today I gave myself a real project.  I started hacking away at del.icio.us for a Winter Hack Day at Yahoo!  I would write a few lines of code, and then realize that I can write it a little better a little cleaner using some neat little python constructs.  It's enjoyable in the way that PHP is not.&lt;/p&gt;

&lt;p&gt;It might just be a phase, but I sincerely doubt it.  A lot of people I know who use python love it.  Many have been using it for years (even while I secretly thought, &quot;python? really?&quot;  Well, I'm starting to think they've been onto something.  We'll see where I end up.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>python: UnicodeEncodeError: 'ascii' codec can't encode character u'\xbb' ...: ordinal not in range...</title>
   <link href="http://davedash.com/2008/01/25/python-unicodeencodeerror-ascii-codec-cant-encode-character-uxbb-ordinal-not-in-range/"/>
   <updated>2008-01-25T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/01/25/python-unicodeencodeerror-ascii-codec-cant-encode-character-uxbb-ordinal-not-in-range</id>
   <content type="html">&lt;p&gt;I don't fully understand utf-8 errors, but I've been getting this error.&lt;/p&gt;

&lt;p&gt;So here's a quick fix:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setdefaultencoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title>Python, Named arguments: Pure Genius</title>
   <link href="http://davedash.com/2007/12/21/python-named-arguments-pure-genius/"/>
   <updated>2007-12-21T00:00:00-08:00</updated>
   <id>http://davedash.com/2007/12/21/python-named-arguments-pure-genius</id>
   <content type="html">&lt;p&gt;I decided I want to learn python, if only to learn Django and to &quot;get&quot; what all the python hub-bub is about.&lt;/p&gt;

&lt;p&gt;Python's named arguments in function calls is pure genius.  Let me explain.&lt;/p&gt;

&lt;p&gt;In PHP, and many other languages you can define a function as such:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function foo($a = 2, $b = 2)
{
    return pow($a,$b);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you follow, &lt;code&gt;foo()&lt;/code&gt; will give you &lt;code&gt;4&lt;/code&gt;.  &lt;code&gt;foo(3)&lt;/code&gt; is &lt;code&gt;9&lt;/code&gt; and &lt;code&gt;foo(99,0)&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt;.  In python we can do the same thing, but it'll pay to use some better variable names:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def foo(base=2, exponent=2):
    return base**exponent
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Similarly &lt;code&gt;foo()&lt;/code&gt; will give you &lt;code&gt;4&lt;/code&gt;.  &lt;code&gt;foo(3)&lt;/code&gt; is &lt;code&gt;9&lt;/code&gt; and &lt;code&gt;foo(99,0)&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt;.  But what if we forgot what the order was?  Did base come first or was it exponent?  We can do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;foo(exponent=99, base=2)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since &lt;code&gt;base&lt;/code&gt; and &lt;code&gt;exponent&lt;/code&gt; both have default values, we can even omit &lt;code&gt;base&lt;/code&gt; and let it use the default:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;foo(exponent=10)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This means rather than passing an &lt;code&gt;$options&lt;/code&gt; array to my functions and checking whether an option was set or not, I can just specify which options I want in my function call.  Or instead of remembering the order of the arguments, I can use whatever order suits me.  Or instead of calling a function like &lt;code&gt;bar(null, null, null, 2)&lt;/code&gt; I can just skip those first three arguments all together.&lt;/p&gt;

&lt;p&gt;A side effect of this, is now there's a real use, even for simple functions, to give your variables easy to remember names.&lt;/p&gt;
</content>
 </entry>
 

</feed>

