<?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/mozilla/atom.xml" rel="self"/>
 <link href="http://davedash.com/tag/mozilla"/>
 <updated>2010-08-29T14:12:50-07:00</updated>
 <id>http://davedash.com/</id>
 <author>
   <name>Dave Dash</name>
   <email>dd+atom1@davedash.com</email>
 </author>

 
 <entry>
   <title>Trimming Whitespace in Django Forms</title>
   <link href="http://davedash.com/2010/08/18/trimming-whitespace-in-django-forms/"/>
   <updated>2010-08-18T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/08/18/trimming-whitespace-in-django-forms</id>
   <content type="html">&lt;p&gt;I've been using frameworks for a number of years.  So I expect a lot of things
to happen &quot;for free&quot; in Django.  One is whitespace removal.  In &lt;a href=&quot;http://delicious.com/&quot;&gt;Delicious&lt;/a&gt;
we had a lot of data in our database with leading and trailing whitespace.  On
the frontend we moved to symfony (actually ysymfony) and that prevented a lot
of this.&lt;/p&gt;

&lt;p&gt;So I was quite surprised that &lt;a href=&quot;http://code.djangoproject.com/ticket/6362&quot;&gt;this is not the case with Django&lt;/a&gt;.  So I
decided we could solve this at the form level, and released a
&lt;a href=&quot;http://github.com/mozilla/happyforms&quot;&gt;ridiculously simple library&lt;/a&gt;.  After some googling, I found that I was
&lt;a href=&quot;http://www.peterbe.com/plog/automatically-strip-whitespace-in-django-forms&quot;&gt;not the first to do this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to use this, fork it, submit pull requests, etc.  I suspect in the
future we'll handle other global form filtering - like stripping high order
Unicode since MySQL is often not a fan.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The Perils of One Giant Fixture</title>
   <link href="http://davedash.com/2010/08/12/the-perils-of-one-giant-fixture/"/>
   <updated>2010-08-12T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/08/12/the-perils-of-one-giant-fixture</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/static/images/2010/08/12/time.jpg&quot; alt=&quot;Timing&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A while back, I thought it would be good to consolidate all the data used in
testing the django-layer of &lt;a href=&quot;https://addons.mozilla.org/&quot;&gt;AMO&lt;/a&gt; into a single data fixture.
Unfortunately we have 600 tests, which were now loading and unloading large
amounts of data each time the test would run.  This made our tests take 20
minutes.&lt;/p&gt;

&lt;p&gt;I decided to cut this down quite a bit, by using smaller fixture files.  Each
fixture file attempts to be a singular primary object (e.g. an Addon or a
Collection or a User) and its associated supporting objects.  It's far from
perfect, but it's achieved tests that run in under 10 minutes.&lt;/p&gt;

&lt;p&gt;The other side effect is tests will be simpler.  They'll only include the
addons needed to generate an effect, and if something can't be done easily with
the fixtures in place, we can always alter the data during the test.&lt;/p&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>Firefox Input, powered by Sphinx</title>
   <link href="http://davedash.com/2010/07/06/firefox-input%2C-powered-by-sphinx/"/>
   <updated>2010-07-06T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/07/06/firefox-input,-powered-by-sphinx</id>
   <content type="html">&lt;p&gt;Thursday, I decided to take a half-day for my sanity, but saw an email about
how Whoosh wasn't going to cut it for &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 was CC'd about
this and there was mention that Sphinx might be possible.&lt;/p&gt;

&lt;p&gt;Sphinx is my hammer, and everything is a nail.  So I said, let's do this.
That translated into me spending my weekend, soothing &lt;a href=&quot;/tag/baby&quot;&gt;my newborn&lt;/a&gt; and
working on Sphinx.  Luckily this was easy, since &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/&quot;&gt;AMO&lt;/a&gt; and &lt;a href=&quot;http://support.mozilla.com/en-US/kb/&quot;&gt;SUMO&lt;/a&gt;
are both running Sphinx in a similar &lt;a href=&quot;http://fredericiana.com/2010/06/23/under-the-hood-of-firefox-input/&quot;&gt;Django environment&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to move quickly, I copied code from the &lt;a href=&quot;http://github.com/jbalogh/zamboni/&quot;&gt;Zamboni&lt;/a&gt; project to
&lt;a href=&quot;http://github.com/fwenzel/reporter&quot;&gt;Firefox Input&lt;/a&gt;.  Even our deployment into staging and production wasn't
done by our usual &quot;Sphinx guy&quot; in IT.  Ultimately, everything landed in place.&lt;/p&gt;

&lt;p&gt;So &lt;a href=&quot;http://input.mozilla.com/&quot;&gt;try it out&lt;/a&gt; and file bugs or let me know if searches don't go as
planned.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Your objects, and all their friends</title>
   <link href="http://davedash.com/2010/06/25/your-objects%2C-and-all-their-friends/"/>
   <updated>2010-06-25T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/06/25/your-objects,-and-all-their-friends</id>
   <content type="html">&lt;p&gt;This is complicated.&lt;/p&gt;

&lt;p&gt;In my ever-evolving quest to &lt;a href=&quot;/2010/03/05/django-fixture-magic-testing-issues-with-real-data/&quot;&gt;get data out of the AMO database&lt;/a&gt; for tests, I
found myself not just extracting a single object, but a list of complicated
requirements in order to fully replicate behavior in production in a testing
environment.&lt;/p&gt;

&lt;p&gt;For &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/&quot;&gt;AMO&lt;/a&gt; we can use &lt;a href=&quot;http://pypi.python.org/pypi/django-fixture-magic&quot;&gt;fixture magic&lt;/a&gt; to dump a single add-on and all of
it's &lt;em&gt;database&lt;/em&gt; dependencies so that it will insert safely into a
test-database.  But we need more than just valid data.  We need some supporting
data.  For an add-on to be browsable and searchable it needs to have a valid
version and the version needs to have a valid file.&lt;/p&gt;

&lt;p&gt;In our app we can check for these things by using this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my_addon.current_version.files.all()[0]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course we need to check that &lt;code&gt;my_addon.current_version&lt;/code&gt; exists and that
&lt;code&gt;files.all()&lt;/code&gt; has at least one object.  This ends up being a lot of work if you
just know the &lt;code&gt;id&lt;/code&gt; of the add-on object.&lt;/p&gt;

&lt;p&gt;So what I want is something simple, like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./manage.py custom_dump addon 3615
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it should get me everything I need to test add-on 3615, including a Version
object and any files associated with the version.&lt;/p&gt;

&lt;p&gt;Turns out this &lt;em&gt;just works&lt;/em&gt;.  It works if you define the following settings:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;c&quot;&gt;## Fixture Magic&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;CUSTOM_DUMPS&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;addon&amp;#39;&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;c&quot;&gt;# ./manage.py custom_dump addon id&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;primary&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;addons.addon&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# This is our reference model.&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;dependents&amp;#39;&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;c&quot;&gt;# These are items we wish to dump.&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;# Magic turns this into current_version.files.all()[0].&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&amp;#39;current_version.files.all.0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;order&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;app1.model1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;app2.model2&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,),&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# stuff gets sorted&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;#39;excludes&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&amp;#39;app1.model1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;fields&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;to&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;hide&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Using this we're able to find out that &lt;code&gt;addon&lt;/code&gt; means an &lt;code&gt;addons.addon&lt;/code&gt; object
and that you want the &lt;code&gt;addon&lt;/code&gt; object with an id of &lt;code&gt;3615&lt;/code&gt;.  From there we'll
try looking for dependent objects.  Using some black magic we can turn:
&lt;code&gt;current_version.files.all.0&lt;/code&gt; into
&lt;code&gt;addon.objects.get(pk=3615).current_version.files.all()[0]&lt;/code&gt;.  This gives us a
file.&lt;/p&gt;

&lt;p&gt;If we mimic our &lt;code&gt;dump_object&lt;/code&gt; command we can get the &lt;code&gt;file&lt;/code&gt; into the database
and everything that the file needs to be valid.  This in turn gives us enough
data (usually) to begin testing a single &lt;code&gt;addon&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So have fun with this, if you're database is remotely complicated, this can
save you some time replicating it during testing.&lt;/p&gt;

&lt;p&gt;Also note, that you can re-order models and exclude certain fields.  This can
make your fixtures very easy to load.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>So your Wordpress has been hacked</title>
   <link href="http://davedash.com/2010/05/19/so-youre-wordpress-has-been-hacked/"/>
   <updated>2010-05-19T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/05/19/so-youre-wordpress-has-been-hacked</id>
   <content type="html">&lt;p&gt;Last week, someone informed me that my blog had been hacked:&lt;/p&gt;

&lt;p&gt;
    &lt;a href=&quot;http://www.flickr.com/photos/davedash/4621504223/&quot;
            title=&quot;My blog got hacked by davedash, on Flickr&quot;&gt;
    &lt;img src=&quot;http://farm5.static.flickr.com/4063/4621504223_210d430c1f_m.jpg&quot;
        width=&quot;240&quot; height=&quot;111&quot; alt=&quot;My blog got hacked&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;


&lt;p&gt;I'm not quite sure what the vector was.  Wordpress wasn't very secure and I
didn't take too many measures to harden it.  A coworker of mine (on our security
team) decided it might be fun to have a look at the infected Wordpress
Installation.&lt;/p&gt;

&lt;h3&gt;Here's how the hack works&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Your blog appears normal to you and your visitors.&lt;/li&gt;
&lt;li&gt;Some rogue PHP code detects if Google is crawling your site and modifies
the text and links so it looks like your website is a Viagra pharmacy.&lt;/li&gt;
&lt;li&gt;The links go to other infected blogs and thus builds up page rank for this
ring of blogs.  So the upside is that your blog may be a top result... for
&lt;em&gt;VIAGRA&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Prevention&lt;/h3&gt;

&lt;p&gt;Here are some tips for prevention, but you can find a lot more by googling for
Wordpress hacks.  My solutions are more technical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't use Wordpress - I recently switched to Jekyll since it was conceptually
easier to understand, and it's coder-friendly.&lt;/li&gt;
&lt;li&gt;Remove all users other than your own.&lt;/li&gt;
&lt;li&gt;Change your password.&lt;/li&gt;
&lt;li&gt;Check your code into git so you can see what files have changed.&lt;/li&gt;
&lt;li&gt;Prevent Wordpress from writing to your webroot.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Restoration&lt;/h3&gt;

&lt;p&gt;Here's what you'll need to do to de-spam yourself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify that you are still spammed by using
Google Webmaster Tools|Labs|Fetch as Googlebot.&lt;/li&gt;
&lt;li&gt;Back up your blog and database.&lt;/li&gt;
&lt;li&gt;Move your Wordpress installation to a new directory.&lt;/li&gt;
&lt;li&gt;Install Wordpress from scratch.&lt;/li&gt;
&lt;li&gt;Remove all users except for yourself.&lt;/li&gt;
&lt;li&gt;Change your password.&lt;/li&gt;
&lt;li&gt;Copy your theme to your new installation.&lt;/li&gt;
&lt;li&gt;Install &lt;em&gt;only&lt;/em&gt; the plugins you need.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;By step 4, you should be able to verify, using &lt;em&gt;Fetch as Googlebot&lt;/em&gt;,
that your website is no longer an online pharmacy.&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Test Driven Confidence</title>
   <link href="http://davedash.com/2010/04/20/test-driven-confidence/"/>
   <updated>2010-04-20T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/04/20/test-driven-confidence</id>
   <content type="html">&lt;p&gt;If you're already testing your web applications, you can skip this post.&lt;/p&gt;

&lt;p&gt;One of the bugs I am working for &lt;a href=&quot;https://addons.mozilla.org/&quot;&gt;AMO&lt;/a&gt; on involves porting a small, but moderately complicated checkbox from our PHP site and rewriting it for Django.&lt;/p&gt;

&lt;p&gt;I decided to look at the existing implementation and found it to not work correctly at all.  This was frustrating, especially since I verified that my own code worked, and that QA verified that it worked as well.&lt;/p&gt;

&lt;p&gt;This is frustrating on many levels.  Chances are some minor assumption I made changed, and thus broke this functionality.  Discovering regressions is never fun, and fixing them is can be long and tedious if you can't automatically verify that everything is working correctly.&lt;/p&gt;

&lt;p&gt;Lucky for me, coming up with tests is easy, you just do what you would do to verify the code satisfies the requirements and then code it.  Sometimes the tests can take longer than writing the actual code, but ultimately you can ship with confidence.  You can be confident that your feature won't break in the future without immediate notice, and you can be confident that your new code won't break anything else.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Finding the most common Firefox issues</title>
   <link href="http://davedash.com/2010/03/18/finding-the-most-common-firefox-issues/"/>
   <updated>2010-03-18T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/03/18/finding-the-most-common-firefox-issues</id>
   <content type="html">&lt;p&gt;Cheng Wang of the Mozilla Support team, a few months back, decided to present on some design ideas for &lt;a href=&quot;http://support.mozilla.com/en-US/kb/&quot;&gt;Firefox Support&lt;/a&gt;.  One of the issues he noted was that there are a lot of repeated issues and that it would be useful to group them.  Grouping them lets you see how often something occurs, and secondly let's you see how urgent it might be.&lt;/p&gt;

&lt;p&gt;Luckily grouping and clustering text is something computers can do.  So I wrote &lt;a href=&quot;http://github.com/davedash/SUMO-issues&quot;&gt;this utility&lt;/a&gt; that does just that.&lt;/p&gt;

&lt;p&gt;I ran this script over a sampling of data from the last week:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firefox won't start after update. (65 related issues)

&lt;ul&gt;
&lt;li&gt;5.6:  Firefox updated, Gmail not delivering mails&lt;/li&gt;
&lt;li&gt;5.6:  How to change My Profile when Firefox won't load?&lt;/li&gt;
&lt;li&gt;7.5:  Once I close firefox, cannot start firefox again except system restart&lt;/li&gt;
&lt;li&gt;5.6:  When intalling updates Firefox uninstalls itself&lt;/li&gt;
&lt;li&gt;16.8:  firefox won't start after update 3.6&lt;/li&gt;
&lt;li&gt;11.2:  Upgraded to Firefox 3.6 and now it won't start&lt;/li&gt;
&lt;li&gt;14.9:  Firefox won't start with most extensions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;How do I add a bookmark to more than one folder? (64 related issues)

&lt;ul&gt;
&lt;li&gt;8.9:  How do I get my bookmarks on the bookmarks toolbar to show up as an icon only with no text?&lt;/li&gt;
&lt;li&gt;7.5:  Bookmarks lost after upgrade and cannot save new bookmarks&lt;/li&gt;
&lt;li&gt;7.5:  why do i have to add the .com now to addy's?&lt;/li&gt;
&lt;li&gt;8.7:  When I open sidebar to edit bookmarks, I only see the folder for Bookmarks Toolbar. I do not see a folder just called Bookmarks nor do I see my list of bookmarks, that separately appear under bookmarks menu at top of screen&lt;/li&gt;
&lt;li&gt;7.5:  All my impoted bookmarks go to the same webpage&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;How do I remove the \ask toolbar\&quot;?&quot; (50 related issues)

&lt;ul&gt;
&lt;li&gt;14.9:  How do I remove an unwanted toolbar?&lt;/li&gt;
&lt;li&gt;5.6:  how to remove temporary video files from computer&lt;/li&gt;
&lt;li&gt;7.5:  I have no Toolbars or searchbar and i cant bring them back&lt;/li&gt;
&lt;li&gt;7.5:  nowhere says how to REMOVE a toolbar - only how to add or modify one&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;not able to open youtube videos (45 related issues)

&lt;ul&gt;
&lt;li&gt;5.6:  Cannot open bookmark/history sidebar&lt;/li&gt;
&lt;li&gt;5.6:  After working well for years Firefox will now not open&lt;/li&gt;
&lt;li&gt;6.7:  opening bookmarks do not open in new tab&lt;/li&gt;
&lt;li&gt;5.6:  I can't watch videos on youtube with firefox, but on internet explorer i can&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I cannot download Firefox 3.6.  I've tried erasing the download file.  I cannot get beyond logging out of Firefox. (44 related issues)

&lt;ul&gt;
&lt;li&gt;8.4:  when downloading files firefox download manager will freeze and i will have to start over the file download&lt;/li&gt;
&lt;li&gt;5.6:  Firefox will not let me download anything! Can someone help?&lt;/li&gt;
&lt;li&gt;6.3:  cannot download epixHD.com: not compatible with firefox 3.6&lt;/li&gt;
&lt;li&gt;5.0:  Several tabs are coming up when i try to downloads things&lt;/li&gt;
&lt;li&gt;5.0:  Firefox wont open since I downloaded the 3.6 update.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The number on the right of the related issue is a score of how strongly it relates to the main issue.&lt;/p&gt;

&lt;p&gt;The full sample is 352 clusters from an original 3000+ issues.  That's a lot less stuff to go through.  We can tune this to have either less clusters, and more related issues in a cluster, or we can make more clusters of issues and that might result in more accuracy.&lt;/p&gt;

&lt;p&gt;Despite the inaccuracy of clustering we can make some general observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firefox not starting is a big issue.&lt;/li&gt;
&lt;li&gt;Bookmarks are either confusing or broken.&lt;/li&gt;
&lt;li&gt;People don't like toolbars&lt;/li&gt;
&lt;li&gt;Opening things is hard&lt;/li&gt;
&lt;li&gt;Downloading things or Firefox is hard&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Hopefully we can fine tune these reports and have them run regularly... maybe automatically posting to Tumblr?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>A few weeks in Chrome</title>
   <link href="http://davedash.com/2010/03/17/a-few-weeks-in-chrome/"/>
   <updated>2010-03-17T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/03/17/a-few-weeks-in-chrome</id>
   <content type="html">&lt;p&gt;A number of weeks ago I got annoyed with Firefox and decided to use Chrome for a while.  This reminded me of the olden days where I used Netscape for a while, and then IE6 came out, and then Phoenix came out all the while I'd keep switching to the newest shiniest thing (note: I'm not sure about the timeline of all the browsers either).&lt;/p&gt;

&lt;p&gt;My browser of choice since Firefox was released has been Firefox.  For some time - nothing shiny in browser-land was coming out.  Little UI things in Safari kept me away (and the lack of extensions), but Chrome finally showed promise.  WebKit, out of process plugins, process separated tabs and now extensions.  This was great.&lt;/p&gt;

&lt;p&gt;I immediately felt like I was going to really love Chrome, and be &lt;em&gt;that&lt;/em&gt; guy at the office (I work at Mozilla) who insists on using Chrome (just like I was &lt;em&gt;that&lt;/em&gt; guy at Yahoo! who used Google for everything).  I also wanted to answer the question as to why so many people really like Firefox in spite of Chrome's amazing speed -- even many Googlers will admit to preferring Firefox.&lt;/p&gt;

&lt;p&gt;Overall I'm happy with Chrome, but I'm switching back to Firefox for now.  Here's some things I observed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&quot;&lt;code&gt;/&lt;/code&gt;&quot; in Firefox let's you search.  Which to me seems more natural than Ctrl-F.  I am pleased that Chrome supports a lot of Firefox's shortcuts, like &lt;code&gt;Cmd-1..9&lt;/code&gt; for switching tabs, or &lt;code&gt;Cmd-Shift-T&lt;/code&gt; for reopening a closed tab.&lt;/li&gt;
&lt;li&gt;No titlebar... I kind of miss it.&lt;/li&gt;
&lt;li&gt;XML is way easier to work with in Firefox.  It's collapsable and always looks pretty.&lt;/li&gt;
&lt;li&gt;Certain sites don't work well in Chrome, like Rypple or the AmericanExpress web site.  Rypple surprisingly enough is built using the Google Web Toolkit.  I really wish their was a &quot;FirefoxTab&quot; that would open certain sites in Firefox instead.&lt;/li&gt;
&lt;li&gt;There's a number of Jetpacks and Extensions that only exist for Firefox or they are severely lacking.

&lt;ul&gt;
&lt;li&gt;The Jetpacks for Mozilla's Bugzilla instance are awesome.&lt;/li&gt;
&lt;li&gt;The Delicious and AdBlock extensions on Chrome aren't nearly as good as the ones for Firefox.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Firebug is much better than the Chrome developer tools.  For example, you can adjust css values instantly.&lt;/li&gt;
&lt;li&gt;Extensions die... and don't come back without restart and appear to never have been installed unless you remember them crashing.&lt;/li&gt;
&lt;li&gt;AwesomeBar (the location bar in Firefox) queries your history much better than the OmniBar (the location bar in Chrome)

&lt;ul&gt;
&lt;li&gt;At first I thought this was because of a sparse history, but after several weeks I still have a hard time finding sites I've been to.&lt;/li&gt;
&lt;li&gt;Chrome will show you a handful of results, and then let you know there are more results, but that takes you to a new screen which is a jarring UI.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Chrome can be slow.  The extensions can take a while, and even switching between tabs can be slow.  At this point startup time can be a moot point.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Overall this was a healthy exercise, since I really like to be up on new browsers, and Chrome really seems like it's can be a good browser for many people.  I'll probably try it again after the next major Chrome update.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Making our tests run thrice as fast</title>
   <link href="http://davedash.com/2010/03/16/making-our-tests-run-thrice-as-fast/"/>
   <updated>2010-03-16T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/03/16/making-our-tests-run-thrice-as-fast</id>
   <content type="html">&lt;p&gt;I've written a faster version of &lt;a href=&quot;http://github.com/jbalogh/test-utils/blob/c4c31905a95e59dcc8919c1030b23848ad7fbca6/test_utils/__init__.py#L57&quot;&gt;TransactionTestCase&lt;/a&gt; and packaged it with &lt;a href=&quot;http://github.com/jbalogh/test-utils&quot;&gt;test_utils&lt;/a&gt;.  It's mysql specific since it relies on &lt;code&gt;SET FOREIGN_KEY_CHECKS=0&lt;/code&gt; to flush the database.&lt;/p&gt;

&lt;p&gt;The long story...&lt;/p&gt;

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


&lt;h3&gt;Why speed matters&lt;/h3&gt;

&lt;p&gt;We're closing in on 300 tests for &lt;a href=&quot;http://github.com/jbalogh/zamboni/&quot;&gt;Zamboni&lt;/a&gt;.  As of yesterday, to run our entire test suite it would have taken approximately 5 minutes.  If you run tests before code-reviews, during a code-review, and before you push to master - you've spent about 15 minutes doing tests for a single feature or bug-fix.  We have about 5 developers, so this cycle happens many times in a work day.  In that time many sandwiches can be made and consumed.&lt;/p&gt;

&lt;p&gt;Even shortcuts, like running a subset of tests will only go so far, and ultimately we do want to validate that all our tests pass for any code-change.&lt;/p&gt;

&lt;h3&gt;Testing Sphinx search with &lt;code&gt;TransactionTestCase&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Django recently sped up testing by running tests in a transaction.  However, this means that data never gets committed to the database and therefore external tools, like the Sphinx indexer, will never see any of that data.  So we resort to &lt;code&gt;TransactionTestCase&lt;/code&gt; which &lt;em&gt;will&lt;/em&gt; commit the data.&lt;/p&gt;

&lt;p&gt;Unfortunately &lt;code&gt;TransactionTestCase&lt;/code&gt; is painfully slow.  The accepted practice is to only use &lt;code&gt;TestCase&lt;/code&gt; if you want your tests to be fast.  So, I decided to complain to &lt;a href=&quot;http://blog.ianbicking.org/&quot;&gt;one of our new hires&lt;/a&gt; and he and I decided to tinker in mysql to figure out what was slow.  We discovered the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;delete from [table] is slow&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;truncate [table] is slow&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;... unless you &lt;code&gt;SET FOREIGN_KEY_CHECKS=0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;So we decided we should do our own tear down.  After some tinkering with &lt;code&gt;cProfiler&lt;/code&gt; I discovered that &lt;code&gt;TransactionTestCase&lt;/code&gt; does a (slow) database &lt;code&gt;flush&lt;/code&gt; on setup for a test case.  This wouldn't do.&lt;/p&gt;

&lt;h3&gt;Making our own &lt;code&gt;TransactionTestCase&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;I decided to make our own &lt;code&gt;TransactionTestCase&lt;/code&gt; and it would just run &lt;code&gt;SET FOREIGN_KEY_CHECKS=0&lt;/code&gt; and &lt;code&gt;TRUNCATE&lt;/code&gt; on each table at tear down time.  It would also not do a &lt;code&gt;flush&lt;/code&gt; on set up.&lt;/p&gt;

&lt;p&gt;We write our tests with the idea that they clean up after themselves.  Rather than having them cleanup after the last test.  This is a requirement for us since &lt;code&gt;django-nose&lt;/code&gt; doesn't reorder tests (nor should it) and a standard &lt;code&gt;django.test.TestCase&lt;/code&gt; assumes a clean database.&lt;/p&gt;

&lt;p&gt;Looking at a single test &lt;code&gt;test_sphinx_indexer&lt;/code&gt;, using &lt;code&gt;django.test.TransactionTestCase&lt;/code&gt; took ~30 seconds.  Using our new &lt;code&gt;TransactionTestCase&lt;/code&gt; it takes ~4 seconds!&lt;/p&gt;

&lt;h3&gt;Fast tests are good&lt;/h3&gt;

&lt;p&gt;We can now run our 275 tests in ~100 seconds versus the ~300 seconds it used to take.  Furthermore, skipping our sphinx tests (which are the only tests that use &lt;code&gt;TransactionTestCase&lt;/code&gt;) only saves us ~10seconds.  That's not a lot of overhead for better coverage.&lt;/p&gt;

&lt;p&gt;This took me the better part of a day, but solving this now, means we're going to more often than not run our sphinx tests all the time rather than skip them.  Our QA team will assure you that search is probably the most regression prone part of our site, so running these tests are vital to quality.&lt;/p&gt;

&lt;p&gt;If you need to use &lt;code&gt;TransactionTestCase&lt;/code&gt; in mysql, &lt;a href=&quot;http://github.com/jbalogh/test-utils&quot;&gt;give ours a try&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;p&gt;&lt;!--more--&gt;&lt;/p&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>django-fixture-magic: Testing issues with real data.</title>
   <link href="http://davedash.com/2010/03/05/django-fixture-magic-testing-issues-with-real-data/"/>
   <updated>2010-03-05T00:00:00-08:00</updated>
   <id>http://davedash.com/2010/03/05/django-fixture-magic-testing-issues-with-real-data</id>
   <content type="html">&lt;p&gt;I just released &lt;a href=&quot;http://github.com/davedash/django-fixture-magic&quot;&gt;Fixture Magic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When dealing with legacy data, you'll run into all kinds of edge cases.  Perhaps, an object might not display correctly unless it has the right parameters, or if it has null parameters it might not display at all.  So when testing &lt;a href=&quot;http://djangoproject.com/&quot;&gt;Django&lt;/a&gt;, it's nice to actually use non-dummy data.&lt;/p&gt;

&lt;p&gt;Luckily Django has a way of pulling real data out of your database using &lt;code&gt;django.core.serializers&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from addons.models import Addon
a = Addon.objects.get(id=3615)
from django.core.serializers import serialize
jsonize = lambda a: serialize(&quot;json&quot;, a, indent=4)
jsonize([a])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This solution runs well in a Django shell and can be lots of fun for the whole family... until things get complicated.
&lt;!--more--&gt;&lt;/p&gt;

&lt;h3&gt;Serializing alone isn't enough.&lt;/h3&gt;

&lt;p&gt;Serializing a fixture with foreign keys means you'll have an un-loadable fixture unless you serialize the dependent fixtures.  Even for one or two foreign keys, this can be a pain.  For &lt;a href=&quot;http://addons.mozilla.org/&quot;&gt;addons.mozilla.org&lt;/a&gt;, we have a spidery-web of dependencies: &lt;code&gt;File&lt;/code&gt;s need a &lt;code&gt;Version&lt;/code&gt; which needs an &lt;code&gt;Addon&lt;/code&gt; which need &lt;code&gt;Translation&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Thus begat the &lt;code&gt;dump_object&lt;/code&gt; management command.  Give it an app, model name and a &lt;code&gt;pk&lt;/code&gt; and it will give you not only a serialized JSON of that object, but all the objects that it requires.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./manage.py dump_object files.file 64874 64876 &amp;gt; my_new_fixture.json
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This looks for the &lt;code&gt;File&lt;/code&gt; model in the &lt;code&gt;files&lt;/code&gt; app and pulls out of the database &lt;code&gt;File&lt;/code&gt;s instances with &lt;code&gt;pk&lt;/code&gt;s of &lt;code&gt;64874&lt;/code&gt; and &lt;code&gt;64876&lt;/code&gt;.  It then recursively searches for any required objects.&lt;/p&gt;

&lt;h3&gt;Too much serial&lt;/h3&gt;

&lt;p&gt;If you create a lot of fixtures, you'll eventually have overlapping serialized objects.  In &lt;code&gt;addons.mozilla.org&lt;/code&gt; we have &lt;code&gt;Addon&lt;/code&gt;s, &lt;code&gt;Version&lt;/code&gt;s (which depend on &lt;code&gt;Addon&lt;/code&gt;s) and &lt;code&gt;AddonCategory&lt;/code&gt;s (which depend on &lt;code&gt;Addon&lt;/code&gt;s and &lt;code&gt;Category&lt;/code&gt;s).  If we wanted to get serialize a specific &lt;code&gt;Addon&lt;/code&gt;, it's dependent &lt;code&gt;Version&lt;/code&gt;s and &lt;code&gt;AddonCategory&lt;/code&gt;s it makes sense to start with &lt;code&gt;dump_object&lt;/code&gt;ing the related &lt;code&gt;Version&lt;/code&gt; and then &lt;code&gt;dump_objecting&lt;/code&gt; the &lt;code&gt;AddonCategory&lt;/code&gt;.  Both &lt;code&gt;dump_object&lt;/code&gt; commands will fetch the &lt;code&gt;Addon&lt;/code&gt; in question, resulting in duplicated data.&lt;/p&gt;

&lt;p&gt;To combat this we can use &lt;code&gt;merge_fixtures&lt;/code&gt; to dedupe our fixtures:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./manage.py dump_object versions.version 64874 &amp;gt; 1.json
./manage.py dump_object categories.addoncategory &amp;gt; 2.json
./manage.py merge_json 1.json 2.json &amp;gt; happy_fixture.json
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This should make creating test data slightly less painful.  So &lt;a href=&quot;http://github.com/davedash/django-fixture-magic&quot;&gt;give it a try&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Palm Pré: A retraction, I really like it now</title>
   <link href="http://davedash.com/2010/01/11/palm-pre-a-retraction-i-really-like-it-now/"/>
   <updated>2010-01-11T00:00:00-08:00</updated>
   <id>http://davedash.com/2010/01/11/palm-pre-a-retraction-i-really-like-it-now</id>
   <content type="html">&lt;p&gt;So before I went on trip to Minnesota last month, I decided maybe I would give the Palm Pré another shot.  After all, my parents have no internet access, so having the Pré... if I could overcome &lt;a href=&quot;/2009/11/19/palm-pre-always-hot/&quot;&gt;my issues&lt;/a&gt;, might be a welcome distraction.&lt;/p&gt;

&lt;p&gt;Before I packed it, I updated to WebOS 1.3.x (a few days later I updated to 1.3.5) and I was blown away.  The horsepower was increased by utilizing the GPU.  The following problems were fixed:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;* The device was no longer hot all the time
* Shutdown and startup were long, but not nearly as long as before.
* Render times were quicker
* All the elements usually rendered quickly in an app
* Network was fairly steady
* Phone calls also seemed fairly drop-free.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All these improvements helped me get over&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;* The tiny keyboard... not so bad in practice.
* No soft keyboard - I missed it, but I could deal without it.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Overall the device was great, it was fast enough to use, and most of the errors were annoying, but things I could deal with.  Cut and paste could be improved, and I wish the USB connector was the same as the one for HTC devices (I can't keep micro or mini USB types straight).&lt;/p&gt;

&lt;p&gt;So I love the device, and Murphy's Law dictates if work gives you a phone you don't like you get to keep it... until you start liking it again.  So I sent the phone back into rotation for other people at Mozilla to try.  Have at it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Google Chrome Extensions Puzzle</title>
   <link href="http://davedash.com/2010/01/06/google-chrome-extensions-puzzle/"/>
   <updated>2010-01-06T00:00:00-08:00</updated>
   <id>http://davedash.com/2010/01/06/google-chrome-extensions-puzzle</id>
   <content type="html">&lt;div style=&quot;float:left; margin-right:1em&quot;&gt;&lt;a href=&quot;http://www.flickr.com/photos/44124375866@N01/4252390433&quot; title=&quot;View 'puzzle' on Flickr.com&quot;&gt;&lt;div style=&quot;text-align:center;&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2684/4252390433_b49093b583_m.jpg&quot; alt=&quot;puzzle&quot; border=&quot;0&quot; width=&quot;161&quot; height=&quot;240&quot; /&gt;&lt;/div&gt;&lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;I went to Add-on-Con some weeks back to represent my employer, the Mozilla Corporation.&lt;/p&gt;

&lt;p&gt;One of the goodies you get as a registrant was a jigsaw puzzle from the Google Chrome Extensions team.&lt;/p&gt;

&lt;p&gt;Perfect, my wife and I love solving jigsaw puzzles.  We finally finished a few days ago.  Anybody who has started at all will realize the puzzle is of a QR-code.  The QR-code is an extension that will eventually lead you to a prize.  It was a bit of a mini-puzzle not nearly as difficult as finding the QR code.&lt;/p&gt;

&lt;p&gt;Although finding a QR code scanner was a bit difficult, I had to borrow a HTC Magic from &lt;a href=&quot;http://fligtar.com/&quot;&gt;Justin Scott&lt;/a&gt; and installed a decent barcode scanner.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Palm Pre: Always hot</title>
   <link href="http://davedash.com/2009/11/19/palm-pre-always-hot/"/>
   <updated>2009-11-19T00:00:00-08:00</updated>
   <id>http://davedash.com/2009/11/19/palm-pre-always-hot</id>
   <content type="html">&lt;p&gt;So I borrowed a Palm Pré that we had at Mozilla to see what it was like.  I was at first very excited, I remember before the Pre was released there was a lot of talk about how awesome-fantastic it was going to be.  The stories of awesomeness sort of died, and I had thought nothing of it.&lt;/p&gt;

&lt;p&gt;Immediately upon using the Pre I figured out why.  In short, it's a crappy phone.  It makes a very good attempt to do a lot, but it does them with such piss-poor performance, that nothing good is noticed.&lt;/p&gt;

&lt;p&gt;I am disappointed.  It's not even in the same class as an iPhone - maybe a future generation of Palm devices will be, but not this one.  I was hoping WebOS would be a good alternative to the iPhone.  It looks like Google will be doing that, though their phones haven't impressed me much either.  I am hoping that maybe this phone is just a dud.&lt;/p&gt;

&lt;p&gt;Here's what I didn't like:
* The Palm was always hot.
* The first run experience is painfully slow.
* The first run was an indicator of things to come, startup and shutdown are ridiculously slow.
* Every application is slow to render.
* Not all elements of an app render.
* The keys are too small.  Some people aren't migrating from a Treo and aren't used to mini keys.
* No soft keyboard.
* The palm website doesn't let you use plus-style addressing
* Media Mode was not self explanatory - and forced the phone to not work.
* Network would constantly drop out.  Couldn't use a lot of the data features.
* Phone calls didn't work so great.
* Did I mention it was ass slow, even the dialing program was slow.
* The battery dies quickly
* I could only cut/paste when composing, but I couldn't cut a string of text from an email.
* Felt too much like an old palm&lt;/p&gt;

&lt;p&gt;Despite the sadness there were a few good things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When it did fetch email, and other notices, it displayed them nicely&lt;/li&gt;
&lt;li&gt;The unification of Facebook and Gmail was pretty cool - it also made me want to trim some of those friends from highschool off my facebook - I ain't ever gonna call em.&lt;/li&gt;
&lt;li&gt;The Icons were pretty.&lt;/li&gt;
&lt;li&gt;The card interface was interesting.&lt;/li&gt;
&lt;li&gt;The travel charger could be modified to work in non US chargers fairly easily.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;All in all, I'm glad that I had a chance to try out this device.  It showed me, that user interfaces above all need to be very fast and responsive.  Furthermore, everything you try to do should be done exceptionally well.  I'm hopeful that software updates can alleviate some of the problem, but I think the root of the problem is slow hardware.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AMO Search: Powered by Sphinx</title>
   <link href="http://davedash.com/2009/09/30/amo-search-powered-by-sphinx/"/>
   <updated>2009-09-30T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/09/30/amo-search-powered-by-sphinx</id>
   <content type="html">&lt;p&gt;Last night, I gave a talk at the &lt;a href=&quot;https://wiki.mozilla.org/AddonMeetups:2009:Chicago&quot;&gt;Addons Meetup&lt;/a&gt; at Threadless HQ in Chicago on the new search engine powering &lt;a href=&quot;http://addons.mozilla.org/&quot;&gt;addons.mozilla.org&lt;/a&gt;.  I'll recap the technical portion of the talk and give a bit more details.&lt;/p&gt;

&lt;p&gt;First, I'd like to thank Harper and Threadless.  It was a great location in the greatest city in the universe.  Before and after the meetup, Harper was just an all-around great guy to hang with and the threadless headquarters was a nice hangout place for meeting people interested in addons.&lt;/p&gt;

&lt;p&gt;Shortly after my talk, our Engineering Ops team deployed the new AMO 5.1 complete with a new Sphinx powered search engine.&lt;/p&gt;

&lt;p&gt;So let's talk about search.  Note: parts of this are a rehash of my talk, so feel free to skip around.&lt;/p&gt;

&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;

&lt;h3&gt;A bit about addons&lt;/h3&gt;

&lt;p&gt;Addons is a huge growing space.  Arguably it's Mozilla's best kept secret.  Sure readers of this blog probably know what Addons are, but ask people who aren't as web-savvy.  Most people don't know what a browser is - and it's hard to explain it to people without getting technical.&lt;/p&gt;

&lt;p&gt;We can just skip that step.  Because Addons are small things that people can easily &quot;get&quot;.&lt;/p&gt;

&lt;p&gt;&quot;It's an easy way to customize the internet when your surfing.&quot;&lt;/p&gt;

&lt;p&gt;While perhaps not technically correct, its one way of explaining it to people.  Maybe a better way is just showing people what they can do with addons.&lt;/p&gt;

&lt;p&gt;On my flight out to Chicago, I talked to a person on the plane who didn't know what a browser was, but after showing her &lt;a href=&quot;http://addons.mozilla.org/&quot;&gt;AMO&lt;/a&gt; she was really intrigued.&lt;/p&gt;

&lt;p&gt;If everyday non-technical people can realize the potential of addons, it's only a matter of time before they start knocking down the doors to AMO.&lt;/p&gt;

&lt;p&gt;So we better be prepared to handle them, and get them what they want.&lt;/p&gt;

&lt;h3&gt;The technical details of addons.mozilla.org&lt;/h3&gt;

&lt;p&gt;Everytime you open Firefox, it pings &lt;a href=&quot;http://addons.mozilla.org/&quot;&gt;AMO&lt;/a&gt; to see if there's any updates to any of the addons that happen to be installed.  Over a third of the people using Firefox have at least one addon, and Firefox is roughly 22% of the browser market.  That means roughly 7% of people opening their browsers are pinging our servers for updates.&lt;/p&gt;

&lt;p&gt;Needless to say it's a lot of traffic, and to support it we need a fair amount of hardware.  AMO is clearly the largest site in the Mozilla universe in both respects.&lt;/p&gt;

&lt;p&gt;Some stats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 mySQL master&lt;/li&gt;
&lt;li&gt;4 mySQL slaves&lt;/li&gt;
&lt;li&gt;2 memached servers&lt;/li&gt;
&lt;li&gt;2 Sphinx indexer/search daemons&lt;/li&gt;
&lt;li&gt;24 Web Frontend&lt;/li&gt;
&lt;li&gt;Multiple Zeus ZXTM clusters all&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Most of this is standard, we'll talk about Sphinx later, but Zeus is amazing.  I didn't know what Zeus was until earlier this year when I interviewed with Mozilla's VP of Engineering Operations.  All our requests get cached so much of our hits actually hit our Zeus cluster and not our web servers.&lt;/p&gt;

&lt;p&gt;To see just how amazing they are read our &lt;a href=&quot;http://blog.mozilla.com/mrz/&quot;&gt;mrz's ops blog&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Why search matters&lt;/h3&gt;

&lt;p&gt;If you have any kind of custom content and unique meta data a custom search solution is a must.  Browsing through a site isn't going to cut it.  Browsing is dead.  Search is how you find things on a web site.  On &lt;a href=&quot;http://addons.mozilla.org/&quot;&gt;AMO&lt;/a&gt; you may see an addon that's featured somewhere, or you might want to see what's out there, but the right search query will find you the right addon in two clicks.&lt;/p&gt;

&lt;h3&gt;Improve Search&lt;/h3&gt;

&lt;p&gt;So my first job on AMO was to &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=498999&quot;&gt;improve addons search&lt;/a&gt;.  It was a vague request and born out of frustration with what we had.  It wasn't a problem that certain things were indexed, or unicode didn't work, or results weren't sorted.  We may have had all those problems, but as a product search needed to be replaced.&lt;/p&gt;

&lt;p&gt;To me it meant that we needed some framework that would allow developers to quickly debug and fix any future search calamities at a moments notice.&lt;/p&gt;

&lt;p&gt;So here were the goals I made for myself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do something that sucks less than what we’ve got&lt;/li&gt;
&lt;li&gt;Do something that makes it easier to suck less in the future&lt;/li&gt;
&lt;li&gt;Do something that’s easy to use for our operations team, web developers and most importantly, end-users&lt;/li&gt;
&lt;li&gt;Reduce strain on our databases, developers and operations teams&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Complex Data&lt;/h3&gt;

&lt;p&gt;Our data set is small (we have 5,000 addons), but there's a lot of secondary meta data about the addons that we track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Addons work in 1 or more locales (e.g. en-US, fr, de, etc)&lt;/li&gt;
&lt;li&gt;Addons are optionally platform specific (Linux, OS X, etc)&lt;/li&gt;
&lt;li&gt;Addons work with one or more products (Firefox, Thunderbird, Seamonkey, Sunbird or Fennec)&lt;/li&gt;
&lt;li&gt;Addons come in multiple flavors (extensions, themes, dictionaries and more)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;We want to index all this data.  Unfortunately to get at much of this data it involves either numerous queries, or numerous joins which put a strain on mysql.  How much strain?&lt;/p&gt;

&lt;p&gt;At peak we get about 10 search queries per second.  If we do something smarter this won't have to cause a lot of strain.&lt;/p&gt;

&lt;h3&gt;Using Sphinx&lt;/h3&gt;

&lt;p&gt;Sphinx is an open source search indexer and daemon.  It's used by Craigslist, the Pirate Bay and &lt;a href=&quot;http://support.mozilla.com&quot;&gt;Mozilla Support&lt;/a&gt;.  It was very easy to use and despite a complicated set of data and business logic, Sphinx was up to the task.&lt;/p&gt;

&lt;h3&gt;The challenges&lt;/h3&gt;

&lt;p&gt;We needed to search for addons in several languages.  So indexing just addons wouldn't work, we need to make sure we have every translation of every addon indexed.  For those counting, we have 5,000 addons, but 18,000 translations of addons.&lt;/p&gt;

&lt;p&gt;All the joining and filtering that needed to be done for our old search still needs to be done, but we can do this all in one shot by using a mysql view.  This view is a flat list of each translated addon as well as all meta data associated with it.  This then gets fed into the sphinx indexer.&lt;/p&gt;

&lt;p&gt;Along the way we ran into some issues which used to be dealt with outside of mysql, such as comparing versions.  It was gross and quite a hack, so we turned the variety of &lt;a href=&quot;http://spindrop.us/2009/08/07/v-is-for-version-hell/&quot;&gt;acceptable version strings into integers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We also learned that stemming wasn't a good idea as we assumed it would be.  Stemming was great for searching through lots of text, but a great deal of addon searches were really just searches for product names, so we opted for substring searches.  We'll see how that fares.  There is probably room for improvement.&lt;/p&gt;

&lt;p&gt;Much of this, however involved knowing our data, and knowing how it will be used by our users.  Once we got that down, we could hammer it all out using Sphinx.&lt;/p&gt;

&lt;h3&gt;Wins&lt;/h3&gt;

&lt;p&gt;So Sphinx gains us a bit architecturally.  We have a complicated query, but it only gets run once every 5 minutes versus the 180,000 times it was run &quot;on demand.&quot;&lt;/p&gt;

&lt;p&gt;Indexing happens rather quickly, just over a minute.&lt;/p&gt;

&lt;p&gt;The API was a breeze to work with, and was easy to drop into our own codebase.&lt;/p&gt;

&lt;p&gt;Because of our relatively small data set, and quick indexing, we're able to scale this simply by cloning and load balancing.  Meaning, we just need to scale for traffic, but addon growth (which is slower than traffic growth) we can safely not worry about for a while.&lt;/p&gt;

&lt;p&gt;Our ops team can monitor the sphinx clusters and just deploy additional nodes as needed.&lt;/p&gt;

&lt;h3&gt;Building a platform&lt;/h3&gt;

&lt;p&gt;What we've done is built a foundation for search.  Not all the problems are gone, but a lot of the problems that our QA team finds are able to be resolved quickly.  We have a nice pile of unit tests as well that help us keep our results in check when we start tweaking dials.&lt;/p&gt;

&lt;p&gt;We even have the groundwork for some nifty advanced search syntax, that hopefully we can inject into future releases of AMO.&lt;/p&gt;

&lt;p&gt;Enjoy.  And if you find anything, &lt;a href=&quot;http://bit.ly/search-bugs&quot;&gt;let me know&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Getting started with pipe viewer</title>
   <link href="http://davedash.com/2009/09/16/getting-started-with-pipe-viewer/"/>
   <updated>2009-09-16T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/09/16/getting-started-with-pipe-viewer</id>
   <content type="html">&lt;p&gt;Despite working on slimming the &lt;code&gt;addons.mozilla.org&lt;/code&gt; database through dieting and exercise - I still have to occasionally do long running database tasks.  So I finally tried out &lt;a href=&quot;http://www.ivarch.com/programs/pv.shtml&quot;&gt;pipe viewer&lt;/a&gt;.  As someone who's impatient this has been awesome.  Here's some quick examples:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[root@ml-db10 sun]# pv -cN source &amp;lt; addons_remora.2009.09.15.sql.gz | gunzip|pv -cN gunzip &amp;gt; addons_remora.2009.09.15.sql
   gunzip: 10.1GB 0:06:48 [25.5MB/s] [   &amp;lt;=&amp;gt;                                  ]
   source: 3.47GB 0:06:48 [8.72MB/s] [======================&amp;gt;] 100%
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we are calling pipe viewer with an argument that says to title this progress meter as &lt;code&gt;source&lt;/code&gt;, and feeding it the gzip'd file.  Pipe viewer will output two things the progress, and the actual file.  We pipe that file into &lt;code&gt;gunzip&lt;/code&gt; to unzip it, and back into another instance of pipe viewer (again with a title, of &lt;code&gt;gunzip&lt;/code&gt;) and the standard output gets redirected to our destination file.&lt;/p&gt;

&lt;p&gt;Now a simpler example is checking the progress of loading a large sql file into mysql:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[root@ml-db10 sun]# pv -cN sql &amp;lt; addons_remora.2009.09.15.sql | mysql -uroot addons_remora -p$PWD
      sql: 2.55GB 0:18:19 [5.68MB/s] [=====&amp;gt;                  ] 25% ETA 0:54:30
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We could have probably combined all this, however:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[root@ml-db10 sun]# pv -cN source &amp;lt; addons_remora.2009.09.15.sql.gz | gunzip|pv -cN gunzip | mysql -u root addons_remora -p$PWD
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Armed with this knowledge you can determine whether to grab a soda, a sandwich or a 2-hour lunch.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>DjangoCon wrapup</title>
   <link href="http://davedash.com/2009/09/15/djangocon-wrapup/"/>
   <updated>2009-09-15T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/09/15/djangocon-wrapup</id>
   <content type="html">&lt;p&gt;I went to &lt;a href=&quot;http://djangocon.org/&quot;&gt;DjangoCon&lt;/a&gt; this past week for work.  Django is one of my favorite frameworks.  I dropped PHP and the symfony framework to learn python and Django and I haven't looked back.  I think for Mozilla's webdev team it would be the framework of choice.  We have 100s of sites in many frameworks, but not a lot of resuability.  Django apps are built to built to be reusable.  If you build correctly you don't have to refactor, it's already done.&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;Here's a collection of notes I collected through the conference.&lt;/p&gt;

&lt;h3&gt;Day one&lt;/h3&gt;

&lt;h4&gt;Keynote - Avi Bryant&lt;/h4&gt;

&lt;blockquote&gt;&lt;p&gt;Frameworks lock us into RDBMS = bad&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;This keynote mentioned the limits of modern frameworks and modern web development.  Essentially frameworks are great for getting started, but as a site grows, the framework gets replaced little by little.  Sometimes it can get in the way - such as with limitation of database choices.&lt;/p&gt;

&lt;h4&gt;UR doing it wrong - James Bennet&lt;/h4&gt;

&lt;p&gt;James outlined a few key problems that many Django developers run into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;learning python as you go&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; doesn't work unless you know some programming upfront&lt;/li&gt;
&lt;li&gt; do the python tutorial&lt;/li&gt;
&lt;li&gt; read python in a nutshell or dive into python&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Things you should know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;subclasses&lt;/li&gt;
&lt;li&gt;super()&lt;/li&gt;
&lt;li&gt;slides went too fast... hopefully they'll be posted&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;All in all RTFM for python and Django :)&lt;/p&gt;

&lt;p&gt;Learn about other py packages... like twisted.  If Twisted Matrix was implemented in Ruby it would be advertised as the second coming of Christ.&lt;/p&gt;

&lt;p&gt;Bennet's Django App review smoketests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;installable via pip, easy_install or setup.py

&lt;ul&gt;
&lt;li&gt;read distutils-guide&lt;/li&gt;
&lt;li&gt;stay away from setuptools&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;have a README&lt;/li&gt;
&lt;li&gt;INSTALL file list deps&lt;/li&gt;
&lt;li&gt;Write DOCUMENTATION

&lt;ul&gt;
&lt;li&gt;use sphinx.pocoo.org&lt;/li&gt;
&lt;li&gt;store it in your package &lt;em&gt;and&lt;/em&gt; upload package docs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;LICENSE (most Django apps use BSD)&lt;/li&gt;
&lt;li&gt;Write unit tests&lt;/li&gt;
&lt;li&gt;django-lint - to look over code (like pep8.py)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;pro-django is a decent book, but not written by Bennet.&lt;/p&gt;

&lt;h4&gt;Testing - Eric Holscher&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Django 1.1 encourages you to test by auto-creating tests.py.&lt;/li&gt;
&lt;li&gt;Support for:

&lt;ul&gt;
&lt;li&gt;Unittests&lt;/li&gt;
&lt;li&gt;Doctest&lt;/li&gt;
&lt;li&gt;Tests done in a db transacation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Test Driven Documentation (TDD + DDD)&lt;/li&gt;
&lt;li&gt;Doctest

&lt;ul&gt;
&lt;li&gt;easy&lt;/li&gt;
&lt;li&gt;can't use PDB&lt;/li&gt;
&lt;li&gt;Hides certain failures&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Unittests via Django TestCase

&lt;ul&gt;
&lt;li&gt;XUnit&lt;/li&gt;
&lt;li&gt;setup/Teardown&lt;/li&gt;
&lt;li&gt;adds db fixtures&lt;/li&gt;
&lt;li&gt;assertions&lt;/li&gt;
&lt;li&gt;mail testing/inbox testing&lt;/li&gt;
&lt;li&gt;url testing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;TestCase

&lt;ul&gt;
&lt;li&gt;Browserless Request/Response testing&lt;/li&gt;
&lt;li&gt;Similar to sfBrowser in symfony&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Google Summer of Code (for Django 1.2)

&lt;ul&gt;
&lt;li&gt;Coverage reports!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I need to learn PDB&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;Deploying Django -&lt;/h4&gt;

&lt;p&gt;Run mod_wsgi in daemon mode.&lt;/p&gt;

&lt;h3&gt;Day 2&lt;/h3&gt;

&lt;h4&gt;&lt;a href=&quot;http://blog.ianbicking.org/2009/09/10/a-new-self-definition-for-foss/&quot;&gt;Keynote - Ian Bicking&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;GNU Manifest:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt; I consider that the golden rule requires that if I like a program I must share it with other people who like it. Software sellers want to divide the users and conquer them, making each user agree not to share with others. I refuse to break solidarity with other users in this way. I cannot in good conscience sign a nondisclosure agreement or a software license agreement. ...&lt;/p&gt;

&lt;p&gt;So that I can continue to use computers without dishonor, I have decided to put together a sufficient body of free software so that I will be able to get along without any software that is not free.&lt;/p&gt;&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;GNU manifesto was the idea of sharing software amongst friends&lt;/li&gt;
&lt;li&gt;GNU has purpose - BSD, etc is just a rule - free to share&lt;/li&gt;
&lt;li&gt;Free is not just the absense of copyright&lt;/li&gt;
&lt;li&gt;Free is not a reaction to existing rules, but a golden rule&lt;/li&gt;
&lt;li&gt;Not just a fight against MS&lt;/li&gt;
&lt;li&gt;Need to find morality (the why) within the practical (the law, or what you can do)&lt;/li&gt;
&lt;li&gt;Open sourcing closed source code isn't building open source&lt;/li&gt;
&lt;li&gt;This might apply to Mozilla... as webkit has taken off more than Gecko.&lt;/li&gt;
&lt;li&gt;Open source is person to person not company to company - despite sponsorship.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Using Django in Non-standard ways - Eric Florenzano&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Django loosely coupled&lt;/li&gt;
&lt;li&gt;Replace templating with Jinja 2&lt;/li&gt;
&lt;li&gt;Copy Django methods into djangoext to easily customize Django behavior&lt;/li&gt;
&lt;li&gt;Not using django.contrib.auth

&lt;ul&gt;
&lt;li&gt;reasons: writing a fb app - no auth needed&lt;/li&gt;
&lt;li&gt;no shoehorning needed - saves time - less overhead&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;skip the orm?

&lt;ul&gt;
&lt;li&gt;legacy dbs&lt;/li&gt;
&lt;li&gt;non standard or db (or non-relational database)&lt;/li&gt;
&lt;li&gt;no database&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;wsgi middleware has some cool shit

&lt;ul&gt;
&lt;li&gt;repose.bitblt: autoscales images&lt;/li&gt;
&lt;li&gt;repose.squeeze: will concat js/css on the fly based on statistical analysis&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;non standard Django based apps

&lt;ul&gt;
&lt;li&gt;YARDBird - IRCBot framework&lt;/li&gt;
&lt;li&gt;djng micro framework&lt;/li&gt;
&lt;li&gt;Jngo- singlefile cms&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;using admin in a nonstandard way is hard/impossible coupled with ORM and auth&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;Real-time web and other Buzzwords - Chris Wanstrath&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;more than just getting your rss feeds faster&lt;/li&gt;
&lt;li&gt;push vs. pull&lt;/li&gt;
&lt;li&gt;1 persisting connection vs polling&lt;/li&gt;
&lt;li&gt;comet/flash-xml/or html5 web socket&lt;/li&gt;
&lt;li&gt;orbitted - open source python comet server&lt;/li&gt;
&lt;li&gt;zeddicus - does the business logic&lt;/li&gt;
&lt;li&gt;orbitted has its own js libs - its a simple port/socket thing for your server code to deal with - not request/response.&lt;/li&gt;
&lt;li&gt;all connections are persisting browser/orbitted orbitted/zeddicus&lt;/li&gt;
&lt;li&gt;You can even use orbitted to connect straight to IRC and write a client in JS&lt;/li&gt;
&lt;li&gt;Jetty also is good for comet&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Also:
* see webhooks
* see pubsubhubub&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://www.slideshare.net/nowells/djangocon-09-presentation-pluggable-applications&quot;&gt;Pluggable, Reusable Django Apps: A Use Case and Proposed Solution&lt;/a&gt; - Shawn Rider and Nowell Strite&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;PBS moved from perl to django - build a lot of reusable apps&lt;/li&gt;
&lt;li&gt;convincing your superiors

&lt;ul&gt;
&lt;li&gt;need a good story -&lt;/li&gt;
&lt;li&gt;existing base of python helped&lt;/li&gt;
&lt;li&gt;With Django easy to do things right without doing things slow&lt;/li&gt;
&lt;li&gt;be really good...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;built a lot of apps to be very reusable, and pluggable based on requirements PBS had&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Day 3&lt;/h3&gt;

&lt;h4&gt;&lt;a href=&quot;http://www.slideshare.net/twleung/djangocon-2009-keynote&quot;&gt;Keynote&lt;/a&gt; - Ted Leung - Sun&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Django jobs are a growing market&lt;/li&gt;
&lt;li&gt;Preferred by startups&lt;/li&gt;
&lt;li&gt;Bespin/wave - cool&lt;/li&gt;
&lt;li&gt;APIs are big... still&lt;/li&gt;
&lt;li&gt;Physically impossible to create purely server-side interactions that are usable enough - rely on rest/comet/ajax/etc to bridge gap&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;&lt;a href=&quot;http://immike.net/files/scaling_django_dc09.pdf&quot;&gt;Scaling Django&lt;/a&gt; Mike Malone&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;MM from Pownce (now sixapart)&lt;/li&gt;
&lt;li&gt;Slides started out as &quot;Building Scalable Web Applications&quot;&lt;/li&gt;
&lt;li&gt;Django didn't get in the way too much when it came to scaling&lt;/li&gt;
&lt;li&gt;Django had tons of caching support&lt;/li&gt;
&lt;li&gt;Cached objects by hand (memcached) and object ID lists&lt;/li&gt;
&lt;li&gt;Use memache for sessions too&lt;/li&gt;
&lt;li&gt;use signals to signal cache invalidation&lt;/li&gt;
&lt;li&gt;race conditions...&lt;/li&gt;
&lt;li&gt;Queue shit... gearman, rabbit mq, etc.&lt;/li&gt;
&lt;li&gt;Memecached incr/decr operators are awesome&lt;/li&gt;
&lt;li&gt;See gh/mmalone/django-caching&lt;/li&gt;
&lt;li&gt;See gh:.../django-multidb&lt;/li&gt;
&lt;li&gt;to combat slavelag use a memcache key to alternate between master or slave&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;&lt;a href=&quot;http://heisel.org/blog/2009/09/11/gearman/&quot;&gt;Gearman - working later&lt;/a&gt; - Chris Heisel&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Gearman - a work later alt to rabbit mq&lt;/li&gt;
&lt;li&gt;Makes the most sense for something like cesium, with a bazillion worker &lt;strike&gt;bees&lt;/strike&gt; foxes feeding off a single queue&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Also at the con, I talked to someone about rebuilding large apps... and they took a PHP app and used URL rewriting to and a lot of PHP/Python glue code to build a seamless transitory app.  The rule is, all new functionality was done up in python while the old app was in maintenance mode.&lt;/p&gt;

&lt;p&gt;More talks &lt;a href=&quot;http://djangocon.pbworks.com/Slides&quot;&gt;here&lt;/a&gt;!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Snow Leopard for Macports and Mysql users</title>
   <link href="http://davedash.com/2009/09/02/snow-leopard-for-macports-and-mysql-users/"/>
   <updated>2009-09-02T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/09/02/snow-leopard-for-macports-and-mysql-users</id>
   <content type="html">&lt;p&gt;I use mysql and macports on OSX and both were broken when I upgraded to Snow Leopard.&lt;/p&gt;

&lt;p&gt;Mysql was a quick fix:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ln -s /usr/local/mysql-5.1.35-osx10.5-x86 /usr/local/mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(you're installed version might be different).  It turns out a symlink was removed during the Snow Leopard upgrade.&lt;/p&gt;

&lt;p&gt;As for MacPorts, I had to install Xcode from the Snow Leopard CD, install the Snow Leopard version of MacPorts and then follow &lt;a href=&quot;http://trac.macports.org/wiki/Migration&quot;&gt;this migration guide&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fun with HTML5, Blockchalk, Bookmarklets and Google Maps</title>
   <link href="http://davedash.com/2009/09/01/fun-with-html5-blockchalk-bookmarklets-and-google-maps/"/>
   <updated>2009-09-01T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/09/01/fun-with-html5-blockchalk-bookmarklets-and-google-maps</id>
   <content type="html">&lt;p&gt;I've been filing away neat things that I've learned.  Like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firefox supports GeoLocation (which varies in accuracy, but is really accurate for me)&lt;/li&gt;
&lt;li&gt;Stephen Hood released the &lt;a href=&quot;http://blockchalk.com/developers&quot;&gt;Blockchalk API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://twitter.com/joshu/status/3679085168&quot;&gt;Google Maps lets you use GeoRSS feeds as a term&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This solves the problem I had with BlockChalk, which is I wanted a way that I could see what's going on near where I am - and I don't have an iPhone.&lt;/p&gt;

&lt;p&gt;So I wrote two bookmarklets:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;javascript:navigator.geolocation.getCurrentPosition(function(p){window.location='http://maps.google.com/maps?q=http://blockchalk.com/api/v0.6/chalks/'+p.coords.latitude+','+p.coords.longitude;})&quot;&gt;Blockchalk Me&lt;/a&gt; which will list Blockchalk listings near you&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;javascript:c=gApplication.getMap().getCenter();window.location=%22http://maps.google.com/maps?q=http://blockchalk.com/api/v0.6/chalks/%22+c.lat()+%22,%22+c.lng()&quot;&gt;Blockchalk this Google Map&lt;/a&gt; which only works if Google Maps is open.  It will load Blockchalks that are near the center of the open Google Map.&lt;/p&gt;

&lt;p&gt;Unfortunately Blockchalk doesn't have a lot of data yet, and will return no results if there's nothing within a mile radius.  Hopefully a radius parameter will be included for the API call.&lt;/p&gt;

&lt;p&gt;So there's no guarantees on the first bookmarklet, but the second bookmarklet should yield nice results for &lt;a href=&quot;http://maps.google.com/maps?q=37.74339,-122.428924&quot;&gt;this location&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enjoy.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>git svn rebase... forever?</title>
   <link href="http://davedash.com/2009/08/12/git-svn-rebase-forever/"/>
   <updated>2009-08-12T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/08/12/git-svn-rebase-forever</id>
   <content type="html">&lt;p&gt;While working on &lt;a href=&quot;http://addons.mozilla.org/&quot;&gt;addons.mozilla.org&lt;/a&gt; I ran into an issue of &lt;code&gt;git svn rebase&lt;/code&gt; continually asking me to merge a file, over and over.&lt;/p&gt;

&lt;p&gt;I had a branch open for a bug.  In that branch I wrote a library.  While that bug was under review, I had to use that library in a new branch for another bug - and had to develop on it a bit.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git co -b bug1 master
$ vi libs/mylib.php # make the lib
$ git add .
$ git commit -m &quot;my new lib&quot;
$ git checkout -b bug2 master
$ git checkout bug1 libs/mylib.php # copies this file from one branch to the next
$ git commit -m &quot;lib copied over&quot;
$ vi libs/mylib.php # hack on the lib 
$ git commit -m &quot;awesomized lib&quot;
$ git svn dcommit # push it up
$ git checkout bug1
$ git svn rebase #... oh shit
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So the rebase was happening.  This is git trying to merge your changes in bug1 and bug2 and play them together in realtime nicely, asking you each step of the way to merge things manually.  I thought something weird was happening since &quot;libs/mylib.php&quot; kept needing manual merging.  Then I noticed that git is applying a series of patches, and that eventually this will resolve and your site will be rebased.&lt;/p&gt;

&lt;p&gt;Don't lose hope, &lt;code&gt;git svn rebase&lt;/code&gt; will finish.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Have unique descriptive page titles</title>
   <link href="http://davedash.com/2009/07/31/have-unique-descriptive-page-titles/"/>
   <updated>2009-07-31T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/07/31/have-unique-descriptive-page-titles</id>
   <content type="html">&lt;div style=&quot;float:right&quot;&gt;&lt;a href=&quot;http://www.flickr.com/photos/44124375866@N01/3764074726&quot; title=&quot;View 'Sphinx - Free open-source SQL full-text search engine - (Build 20090715083437)' on Flickr.com&quot;&gt;&lt;div style=&quot;text-align:center;&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3588/3764074726_0c02ffd18c.jpg&quot; alt=&quot;Sphinx - Free open-source SQL full-text search engine - (Build 20090715083437)&quot; border=&quot;0&quot; width=&quot;483&quot; height=&quot;338&quot; /&gt;&lt;/div&gt;&lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;One of my internet pet-peeves is people using the same page title for every page on their web site.  Take a look at &lt;a href=&quot;http://www.google.com/search?hl=en&amp;amp;q=+site:www.sphinxsearch.com+sphinx+api+php&quot;&gt;this search for Sphinx&lt;/a&gt;.  As you can see virtually all the links for Sphinx are titled &quot;Sphinx - Free open-source SQL full-text search engine&quot; which blows for usability when it comes to searching, or even managing the various pages you might have open in your web browser.&lt;/p&gt;

&lt;p&gt;To get an idea of the page I want I need to look at the abstract which may or may not give me a clue.  Even the forum posts which usually have subjects, have their &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; set to the site-wide default.&lt;/p&gt;

&lt;p&gt;&lt;!--more--&gt;
The first step in solving this, is identifying you have a problem in the first place.  So I wrote &lt;a href=&quot;http://github.com/davedash/Title-Variance/tree&quot;&gt;a tool&lt;/a&gt; in python to determine how unique the page titles you have are:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% python measure.py sphinxsearch.com
1050 titles found for sphinxsearch.com
483 unique titles found for sphinxsearch.com
46% of the pages on sphinxsearch.com have unique titles
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is fairly telling.  It means over half the pages on sphinxsearch.com have a generic title.&lt;/p&gt;

&lt;p&gt;This site faired a bit better:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;% python measure.py spindrop.us
988 titles found for spindrop.us
822 unique titles found for spindrop.us
83% of the pages on spindrop.us have unique titles
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So please, think about people trying to use the information on your site.  Design your templates in such a way that you can come up with unique titles.&lt;/p&gt;

&lt;p&gt;Feel free to expand on this tool, it could easily output the offending pages or titles.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Comprehensive list of international dialing codes</title>
   <link href="http://davedash.com/2009/07/01/list-of-comprehensive-international-dialing-codes/"/>
   <updated>2009-07-01T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/07/01/list-of-comprehensive-international-dialing-codes</id>
   <content type="html">&lt;p&gt;I get bored with mundane tasks.  So I create little adventures for myself.  I had to create a list of countries and country codes to use on the &lt;a href=&quot;http://mozilla.com/mobile&quot;&gt;Firefox mobile home page&lt;/a&gt;.  The first few lists were incomplete, so I made my own by parsing a list provided by the International Telecommunication Union.  I stripped it down to simple forms of the country names and removed codes that are very rare (satellite phones).&lt;/p&gt;

&lt;p&gt;Well this could be a boring task for most people, so I placed it on [github][http://github.com/davedash/International-Dialing-Codes/].  Feel free to use this in your own projects, I even include a perl one-liner in the README to convert this into a drop down HTML list.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Question: Building a Better Search Engine</title>
   <link href="http://davedash.com/2009/06/18/question-building-a-better-search-engine/"/>
   <updated>2009-06-18T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/06/18/question-building-a-better-search-engine</id>
   <content type="html">&lt;p&gt;So I finally have one of those jobs where I can tell people almost every little detail about what I'm doing and I'm encouraged to talk to people on the intar-webs and solicit opinions.&lt;/p&gt;

&lt;p&gt;Uh - this is more or less how I've operated at previous jobs, just now I can be overt about it.&lt;/p&gt;

&lt;p&gt;So my &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=498999&quot;&gt;new task&lt;/a&gt; is to work on improving the &lt;a href=&quot;http://addons.mozilla.org&quot;&gt;addons.mozilla.org&lt;/a&gt; search engine.  I've built various &quot;search engines&quot; over time in PHP, powered by Lucene and most recently in python using an inverted index.&lt;/p&gt;

&lt;p&gt;One tool that I've been looking at briefly is &lt;a href=&quot;http://sphinxsearch.com/&quot;&gt;Sphinx&lt;/a&gt;.  While my record count is low (5-10K), Sphinx basically bakes in a lot of the things I would want in a search engine.  Indexing, merging, etc.&lt;/p&gt;

&lt;p&gt;Since I'm fairly new to the add-ons team I'm still understanding the basics of what we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast automated indexing of addons for Firefox, Thunderbird and any other Mozilla product&lt;/li&gt;
&lt;li&gt;Quick result sets&lt;/li&gt;
&lt;li&gt;Easy deployability&lt;/li&gt;
&lt;li&gt;Extendible&lt;/li&gt;
&lt;li&gt;Customized ranking&lt;/li&gt;
&lt;li&gt;Filtering (e.g. by Firefox version, etc).&lt;/li&gt;
&lt;li&gt;Basics: Stemming and stop-words&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Whether it's Sphinx, Lucene or some home grown solution, I have all that to support.  But this should be fairly straight forward.  What are people's thoughts?&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>
 

</feed>
