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

 <title>Dave Dash</title>
 <link href="http://davedash.com/atom.xml" rel="self"/>
 <link href="http://davedash.com/"/>
 <updated>2010-07-18T15:18:07-07:00</updated>
 <id>http://davedash.com/</id>
 <author>
   <name>Dave Dash</name>
   <email>dd+atom1@davedash.com</email>
 </author>

 
 <entry>
   <title>Predictable Unpredicatability: Weeks 5-7</title>
   <link href="http://davedash.com/2010/07/18/predictable-unpredicatability%3A-weeks-5-7/"/>
   <updated>2010-07-18T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/07/18/predictable-unpredicatability:-weeks-5-7</id>
   <content type="html">&lt;p&gt;Predictable unpredictability: Week 5-7&lt;/p&gt;

&lt;p&gt;I decided to cover three weeks at a time as things are becoming a bit more
stable.  As always, things have gotten considerably easier.  Most things
aren't worrying us.  Most days have been considerably easier.  There's still
tough days where I feel like I can't console him, but we're usually able to
figure things out.&lt;/p&gt;

&lt;p&gt;Right now the real fright is the &lt;a href=&quot;http://www.soundsofpertussis.com/&quot;&gt;Whooping cough&lt;/a&gt;.  Our pediatrician, who is
normally calm and relaxed about everything, was very freaked out about the
epidemic.&lt;/p&gt;

&lt;p&gt;Katie's doing a fantastic job, despite having considerable breastfeeding woes.&lt;/p&gt;

&lt;p&gt;We also have an issue with green stools, but Katie's been altering her diet so
we should see some new results.&lt;/p&gt;

&lt;p&gt;Here's some new things we've noticed halfway past the &lt;a href=&quot;http://en.wikipedia.org/wiki/Harvey_Karp&quot;&gt;4th trimester&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I put in a half-day in the office.&lt;/li&gt;
&lt;li&gt;Katie can still cook like a champ!&lt;/li&gt;
&lt;li&gt;Siddhartha smiles a lot, especially if you play games with him.&lt;/li&gt;
&lt;li&gt;His hands seem more coordinated.&lt;/li&gt;
&lt;li&gt;Often he wakes up without crying.&lt;/li&gt;
&lt;li&gt;He's slept 7+ hours on a number of occasions and we can count on at least 4
hours.&lt;/li&gt;
&lt;li&gt;He's over 10 lbs and 22 inches.&lt;/li&gt;
&lt;li&gt;He flails his arms less when he's nursing.&lt;/li&gt;
&lt;li&gt;We've been managing all on our own for over two weeks.&lt;/li&gt;
&lt;li&gt;Katie drove to somewhere with nobody in the back seat to soothe the baby.&lt;/li&gt;
&lt;li&gt;Katie's taken a bath and shower with him a few times.&lt;/li&gt;
&lt;li&gt;He sleeps in his swing for quite some time.&lt;/li&gt;
&lt;li&gt;We've gone out with him on a few occasions with no major troubles.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;object width=&quot;560&quot; height=&quot;340&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/nefrDc-pvX4&amp;amp;hl=en_US&amp;amp;fs=1?rel=0&amp;amp;hd=1&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/nefrDc-pvX4&amp;amp;hl=en_US&amp;amp;fs=1?rel=0&amp;amp;hd=1&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;560&quot; height=&quot;340&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&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://davedash.com/2010/07/08/the-python-textcluster-package/&quot;&gt;&lt;code&gt;textcluster&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://davedash.com/2010/07/08/the-python-textcluster-package/&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>On Buying a Thermometer</title>
   <link href="http://davedash.com/2010/07/05/on-buying-a-thermometer/"/>
   <updated>2010-07-05T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/07/05/on-buying-a-thermometer</id>
   <content type="html">&lt;p&gt;After talking to our doulas about thermometers, I decided it'd be best to get
an in-ear thermometer.  I didn't at first because I heard they were expensive -
but this is a device that I'll be using regularly for the foreseeable future.
Our doula has had her thermometer for 8 years.&lt;/p&gt;

&lt;p&gt;The other thing I like about the in-ear thermometer is it takes just a few
seconds.  I'm not really into holding a thermometer in my kids bum for a few
minutes.  Holding it in their armpit is less dangerous, but still slow.  The
in-ear thermometer works in a few seconds.&lt;/p&gt;

&lt;p&gt;It's apparently not accurate at a young age, but I'll be using this for years
to come.&lt;/p&gt;

&lt;p&gt;I found the &lt;a href=&quot;http://www.amazon.com/Braun-Thermoscan-Thermometer-ExacTemp-Technology/dp/B001FWXKMM&quot;&gt;Braun Thermoscan&lt;/a&gt; at Target.  Hopefully I can resist measuring
Sibi's temperature every day.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Siddhartha: Weeks 3 and 4</title>
   <link href="http://davedash.com/2010/06/27/siddhartha%3A-weeks-3-and-4/"/>
   <updated>2010-06-27T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/06/27/siddhartha:-weeks-3-and-4</id>
   <content type="html">&lt;p&gt;A week ago, I would have said &lt;a href=&quot;/2010/06/13/the-first-two-weeks:-what-nobody-tells-you/&quot;&gt;this is still hell&lt;/a&gt;.  However, since
Wednesday, I've started to feel a lot more at ease.&lt;/p&gt;

&lt;p&gt;I think a lot of what has changed is Katie and my attitudes.  Katie's been a
superstar at mothering and nursing Siddhartha.  While I work from home, she
does her best to do things without my help (although I don't mind getting her
some water or food while she's busy nursing).  After I finish work, I'm excited
to spend time with Siddhartha.  All the great feelings of being a dad that
people expect you to have right away... I probably just got all those feelings
in the last few days.&lt;/p&gt;

&lt;p&gt;So here's progress in the last two weeks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sibi is over 8 lbs.  He's clearly eating well, thanks to Katie.&lt;/li&gt;
&lt;li&gt;Nipple shield is no longer required for feeding.&lt;/li&gt;
&lt;li&gt;Sibi can pay more attention to us.  When he's not crying, sleeping or eating
he's a lot more fun.&lt;/li&gt;
&lt;li&gt;Sibi can track objects and you with his eyes.&lt;/li&gt;
&lt;li&gt;Sibi soothes quickly with Katie, even if it means just putting him on the
breast.&lt;/li&gt;
&lt;li&gt;Easier for me to deal when he fusses - I'm recognizing that its temporary.&lt;/li&gt;
&lt;li&gt;We've been able to take him out a little bit each day for walks or trips to
the store.&lt;/li&gt;
&lt;li&gt;Lately he gives us a fair amount of sleep.&lt;/li&gt;
&lt;li&gt;Our low days have been less bad than previous low days..&lt;/li&gt;
&lt;li&gt;I got to go into the office for a bit.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;We've no longer got Katie's mom to help us, and in some ways it's like the
training wheels have come off.  The adjustment was painful, like ripping a
bandaid off, but we're managing.  My mom has been in town and has
helped somewhat in terms of food and giving Sibi infant massages, but we've
been trying hard to do baby stuff on our own.  It's paying off.  We're a lot
more confident.&lt;/p&gt;

&lt;div&gt;
&lt;object width=&quot;560&quot; height=&quot;340&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/RK8UayJ_c-w&amp;amp;hl=en_US&amp;amp;fs=1?rel=0&amp;amp;hd=1&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/RK8UayJ_c-w&amp;amp;hl=en_US&amp;amp;fs=1?rel=0&amp;amp;hd=1&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;560&quot; height=&quot;340&quot;&gt;&lt;/embed&gt;&lt;/object&gt;

&lt;/div&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>The first two weeks: what nobody tells you</title>
   <link href="http://davedash.com/2010/06/13/the-first-two-weeks%3A-what-nobody-tells-you/"/>
   <updated>2010-06-13T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/06/13/the-first-two-weeks:-what-nobody-tells-you</id>
   <content type="html">&lt;p&gt;This is hell.&lt;/p&gt;

&lt;p&gt;Apparently we are through the worst of it.  Or we're just used to the sleep
deprivation.  I expected lack of sleep and I expected crying, but not so
intense.  Every parent we've run into assures us that this goes away and that
it gets better.  Some even say that this is just the &quot;forth trimester&quot; and once
they pass three months the clouds will make way for the sunlight.&lt;/p&gt;

&lt;p&gt;Time couldn't move quickly enough.&lt;/p&gt;

&lt;p&gt;I do know that things have been getting better.  Here's some improvements in
the last two weeks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sibi is at (or possibly above) his birth weight after having lost a great
deal of weight (more than the acceptable 10%).&lt;/li&gt;
&lt;li&gt;Sibi can be exclusively breast-fed.  At the hospital they supplemented with
formula until Katie's milk came in.&lt;/li&gt;
&lt;li&gt;Sibi can feed directly on the breast, rather than via bottle.  This is thanks
to the lactation consultants at Good Samaritan.&lt;/li&gt;
&lt;li&gt;We no longer need to use a syringe during the feeding process.  Previously
feeding required &lt;em&gt;both&lt;/em&gt; Katie, myself, a syringe and a flailing baby.&lt;/li&gt;
&lt;li&gt;Sibi is calm when he goes to the breast.  Before he would flail and fight it.&lt;/li&gt;
&lt;li&gt;We can now watch movies while he nurses.  Before we hadn't quite mastered the
skill of feeding him.&lt;/li&gt;
&lt;li&gt;Katie is now able to get a passable amount of sleep.  Her OB told her she was
sleep deprived a few days after Siddhartha was born.&lt;/li&gt;
&lt;li&gt;I am able to get a reasonable amount of sleep.&lt;/li&gt;
&lt;li&gt;We can usually tolerate his crying better and in some cases console him.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Lucky for us, Katie's mom has been helping us quite a bit while we adjust.
We're still dealing with a lot of mystery and unknowns and its scary and pushes
us quite a bit.  His new thing is crying inconsolably at night until he's
nursing again.  Hoping it's a growth spurt and I'm hoping that we see some
quality of life improvements in the next few weeks.&lt;/p&gt;

&lt;p&gt;I'm nervous about returning to work.  I'm hoping that my mom who arrives on
Friday when Katie's mom leaves can find ways to console him as well.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>On the Labor and Delivery of our Son</title>
   <link href="http://davedash.com/2010/06/06/on-the-labor-and-delivery-of-our-son/"/>
   <updated>2010-06-06T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/06/06/on-the-labor-and-delivery-of-our-son</id>
   <content type="html">&lt;p&gt;Here's my subjective account of Katie's labor.  I don't have exact times and
details, but our doulas have it on record somewhere.  Most of the links are to
my twitter updates.&lt;/p&gt;

&lt;h3&gt;Friday at the OB&lt;/h3&gt;

&lt;p&gt;Many of my coworkers wished me that my paternity leave would start by the end
of the weekend.  I did too...&lt;/p&gt;

&lt;p&gt;Friday May 29th we found out that &lt;a href=&quot;http://twitter.com/dave_dash/status/14939523682&quot;&gt;Katie needed to be induced&lt;/a&gt;.  The fluid
levels in her amniotic sac were very low.  Dr. Woo strongly suggested that we
immediately go home, get our things and go to the hospital.  I was excited, but
not thrilled that there would be an induction.&lt;/p&gt;

&lt;p&gt;We headed home, and I alerted our doulas en route.  We gave ourselves 20
minutes to wrap up everything and &lt;a href=&quot;http://twitter.com/dave_dash/status/14943394243&quot;&gt;we were on our way&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Hurry up and wait&lt;/h3&gt;

&lt;p&gt;Lucille Packard Children's Hospital's Labor and Delivery ward was booked solid,
so we were put in a closet sized room and told to wait for a while.  It was
quite cozy with our two doulas.  Katie and I hadn't eaten for a while so I
decided to get us some &lt;a href=&quot;http://twitter.com/dave_dash/status/14955508787&quot;&gt;food from Thaiphoon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When I got back I learned that Katie would be under observation while she had
&lt;a href=&quot;http://twitter.com/dave_dash/status/14966292642&quot;&gt;a cervidil induction&lt;/a&gt;.  Unfortunately, &lt;a href=&quot;http://twitter.com/dave_dash/status/14955583891&quot;&gt;we were stuck in the tiny
room&lt;/a&gt; and I was sleeping on the floor.  Our nurse moved us into a &lt;a href=&quot;http://twitter.com/dave_dash/status/14958530441&quot;&gt;much
larger room&lt;/a&gt; and I was able to sleep comfortably once I ignored my
&lt;a href=&quot;http://twitter.com/dave_dash/status/14966228924&quot;&gt;nasty headache&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;The &quot;pit&quot;&lt;/h3&gt;

&lt;p&gt;The next morning we made a little progress with the cervidil.  However, we
needed more to get Katie into active labor, so we were asked to try pitocin.&lt;/p&gt;

&lt;p&gt;Katie was well-read on pitocin and to her, pitocin made the following scenario
likely:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;pitocin -&amp;gt; epidural -&amp;gt; c-section
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Katie and I decided that pitocin would be the best option, despite the possible
side-effects.  We just asked that they introduce it slowly and increment it
slowly.  This eventually &lt;a href=&quot;http://twitter.com/dave_dash/status/14996486309&quot;&gt;caused Katie's water to break&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately, we had the nurse who thought she knew what was &quot;best&quot;.  At
some point she had discretely kicked up the pit-level a bit high.  This lead to
Katie getting painful, rapid contractions too early.&lt;/p&gt;

&lt;h3&gt;Transition&lt;/h3&gt;

&lt;p&gt;These rapid contractions transitioned Katie into a more intense stage of labor,
but they started around 2cm -- far too early.&lt;/p&gt;

&lt;p&gt;Each contraction brought enough physical pain (10 on the scale from 1-10) even
the doulas and myself couldn't ease the pain.  This wasn't normal.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://twitter.com/dave_dash/status/15010643919&quot;&gt;We opted for an epidural&lt;/a&gt;.  The doulas had to leave for that, and Katie,
who was shaking, had to be restrained in order for her to be hooked up.  Once
she was on it, all was well.&lt;/p&gt;

&lt;h3&gt;OMG WTF BBQ&lt;/h3&gt;

&lt;p&gt;Until it wasn't.  The fetal heart rate went down quite a bit.  Several nurses
and our anesthesiologist arrived, brought Katie on all fours and got the fetal
heart rate back up.  Except for the fact that Katie could still feel her
contractions in the left side of her behind, everything was fine.&lt;/p&gt;

&lt;p&gt;The doulas came by and checked on us before deciding to catch some shut-eye in
the waiting area.&lt;/p&gt;

&lt;p&gt;Before we went to sleep, we decided we should have the anesthesiologist adjust
the epidural line.  He adjusted it and all was well.&lt;/p&gt;

&lt;h3&gt;Everything happens so fast&lt;/h3&gt;

&lt;p&gt;Until everything repeated itself.   All of a sudden the OB, anesthesiologist,
nurses were all in our room getting Katie on all fours again.  The OB wasn't
comfortable with the baby's heart rate so she had everyone move to the
operating room.  I called our doulas, letting them know &quot;stuff is happening.&quot;
I was told to hold back by a certain nurse and then she said she'd get me into
scrubs.&lt;/p&gt;

&lt;p&gt;A nurse told me to get in scrubs and the doulas were to pack up our room.  When
I got into scrubs, the nurse said I couldn't go into the room, since they
decided to operate (meaning C-Section).  I waited for a few minutes and the
nurse told me to come with her -- my son was delivered:&lt;/p&gt;

&lt;p&gt;
    &lt;object width=&quot;560&quot; height=&quot;340&quot;&gt;
        &lt;param name=&quot;movie&quot;
            value=&quot;http://www.youtube.com/v/d_OTgGuctdk&amp;hl=en_US&amp;fs=1&amp;rel=0&amp;color1=0x3a3a3a&amp;color2=0x999999&quot;&gt;&lt;/param&gt;
        &lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;
        &lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;
        &lt;embed src=&quot;http://www.youtube.com/v/d_OTgGuctdk&amp;hl=en_US&amp;fs=1&amp;rel=0&amp;color1=0x3a3a3a&amp;color2=0x999999&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;560&quot; height=&quot;340&quot;&gt;&lt;/embed&gt;
    &lt;/object&gt;
&lt;/p&gt;


&lt;p&gt;My son was born at 9:59PM on May 29th 2010.  He had a healthy 9/10 APGAR score,
and looked wonderful.  For the first time in my life, I cried.&lt;/p&gt;

&lt;h3&gt;Recovery&lt;/h3&gt;

&lt;p&gt;Amazingly, after all of this, Katie was fine.  She recovered and we spent a few
frantic nights in the hospital getting used to the fact that we were new
parents.  With the help of good friends and family we've made it over a week.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Introducing...</title>
   <link href="http://davedash.com/2010/05/29/introducing/"/>
   <updated>2010-05-29T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/05/29/introducing</id>
   <content type="html">&lt;p&gt;Siddhartha Bonn Dash&lt;/p&gt;

&lt;p&gt;7 lbs 2 oz, 19 and 3/4 in&lt;/p&gt;

&lt;p&gt;9:59 pm 29 May 2010&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>No, the Baby Has Not Arrived -- an FAQ</title>
   <link href="http://davedash.com/2010/05/27/no%2C-the-baby-has-not-arrived----an-faq/"/>
   <updated>2010-05-27T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/05/27/no,-the-baby-has-not-arrived----an-faq</id>
   <content type="html">&lt;p&gt;People tend to ask me the same questions, so I figure I can answer some basics
here.&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;When is the baby due?&lt;/dt&gt;
&lt;dd&gt;
  Two days ago (25 May).  Due-dates, however, are 40 weeks after &lt;acronym
  title=&quot;Last Menstrual Period&quot;&gt;LMP&lt;/acronym&gt; and statistically there's less
  than 5% chance of a delivery on that exact day.  There is, however, a 90%
  likelyhood that it will happen within two weeks of that date.
  &lt;a href=&quot;http://en.wikipedia.org/wiki/Pregnant#Duration&quot;&gt;[1]&lt;/a&gt;
&lt;/dd&gt;

&lt;dt&gt;Is it a boy or a girl?&lt;/dt&gt;
&lt;dd&gt;Boy.&lt;/dd&gt;

&lt;dt&gt;What's his name?&lt;/dt&gt;
&lt;dd&gt;You'll find out during the birth announcement.&lt;/dd&gt;

&lt;dt&gt;Should I call you to find out if the baby is born?&lt;/dt&gt;

&lt;dd&gt;
    No, that's a terrible idea.  Katie and I both hate the phone even when
    there &lt;em&gt;isn't&lt;/em&gt; a child on the way.  We hate it more when we're trying
    to relax before the baby is born.  If you absolutely need to get in touch
    with us, try text or email.
&lt;/dd&gt;

&lt;dt&gt;Is there anything we can do?&lt;/dt&gt;

&lt;dd&gt;
    &lt;dl&gt;
        &lt;dt&gt;Before the birth:&lt;/dt&gt;
        &lt;dd&gt;Play with our cat, he's needy and needs more attention than anyone
        can give him.&lt;/dd&gt;
        &lt;dt&gt;After the birth:&lt;/dt&gt;
        &lt;dd&gt;Email me if you are serious, there's plenty.&lt;/dd&gt;
    &lt;/dl&gt;
&lt;/dd&gt;
&lt;dt&gt;How is Katie feeling?&lt;/dt&gt;
&lt;dd&gt;
    Tired - but &lt;a href=&quot;http://katiebonn.com/&quot;&gt;she blogs&lt;/a&gt; in more detail.
&lt;/dd&gt;

&lt;dt&gt;Are you nervous?&lt;/dt&gt;

&lt;dd&gt;
    No.  I am not terribly excited about the sleep disruption, but I'll
    manage.
&lt;/dd&gt;

&lt;dt&gt;Excited?&lt;/dt&gt;

&lt;dd&gt;
    Yes.  I'm excited.  Think of every cliché thing about new dads -- that's
    what I have.
&lt;/dd&gt;

&lt;/dl&gt;

</content>
 </entry>
 
 <entry>
   <title>Back to My Pre-California Weight</title>
   <link href="http://davedash.com/2010/05/23/back-to-my-pre-california-weight/"/>
   <updated>2010-05-23T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/05/23/back-to-my-pre-california-weight</id>
   <content type="html">&lt;p&gt;About a month back I hit a milestone, I went down to my pre-California weight.&lt;/p&gt;

&lt;p&gt;Here's a chart of my weight since August 2007, a few months before I moved to
California.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/images/2010/05/23/weight.jpg&quot; alt=&quot;Weight chart&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here are the events:&lt;/p&gt;

&lt;ol class=&quot;ualpha&quot;&gt;
    &lt;li&gt;Move from Minneapolis to SF Bay&lt;/li&gt;
    &lt;li&gt;Visit Minneapolis&lt;/li&gt;
    &lt;li&gt;Visit Minneapolis&lt;/li&gt;
    &lt;li&gt;Leaving Yahoo!&lt;/li&gt;
    &lt;li&gt;Move to San José&lt;/li&gt;
    &lt;li&gt;Try iChange&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;The Basics&lt;/h3&gt;

&lt;p&gt;There's nothing shocking.  The more I ate and less I exercised, the more I
gained weight.  Travel was an easy way to gain weight because I never checked
in regularly.  Moving to a condo with an awesome gym made regular exercise a
breeze.&lt;/p&gt;

&lt;p&gt;I tried out &lt;a href=&quot;http://ichange.com/&quot;&gt;iChange&lt;/a&gt; which offered one-on-one monitoring.  That got me
eating healthier food, so it put most of my calories to good use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sugar and saturated fats were all but eliminated from my diet and slowly
reintroduced when I could moderate them.&lt;/li&gt;
&lt;li&gt;Counting calories helped reset my internal calorie tracker.  I still don't
do it enough, so I try to simply eat better.&lt;/li&gt;
&lt;li&gt;Water tastes better the more I drink it.  I drink a lot of soda still, but
there are days when I can completely avoid it.&lt;/li&gt;
&lt;li&gt;Exercising a lot is nice.  I get to eat more.  Exercising early works best
for me.&lt;/li&gt;
&lt;li&gt;Eating more whole grains felt better.  The food was flavorful.&lt;/li&gt;
&lt;li&gt;Balanced meals were tricky, though eating more fruit and vegetables made me
less hungry for higher calorie items.&lt;/li&gt;
&lt;li&gt;I had to start by doing &lt;em&gt;everything&lt;/em&gt;: eating better, exercising, etc.
Doing one thing at a time was a failure.  There were no shortcuts at the
beginning.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Now I stay pretty much on track with losing weight.  The days I gain a bit of
weight, I understand why, and I am usually able to resolve it quickly.
Therefore weight loss is no longer stressful.&lt;/p&gt;

&lt;p&gt;So with about 10lbs less of weight from the beginning of this year, I can sling
on a Moby-wrap with my son (when he decides to be born) and it'll feel like
nothing.&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>Alphabetical sorting in Sphinx</title>
   <link href="http://davedash.com/2010/04/21/alphabetical-sorting-in-sphinx/"/>
   <updated>2010-04-21T00:00:00-07:00</updated>
   <id>http://davedash.com/2010/04/21/alphabetical-sorting-in-sphinx</id>
   <content type="html">&lt;p&gt;Sphinx 0.9.9 is great at searching full text, but treating actual strings as attributes takes some work.&lt;/p&gt;

&lt;p&gt;Initially I employed the strategy of indexing my full text fields &lt;em&gt;and&lt;/em&gt; storing them as attributes.  E.g.:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sql_query = SELECT name, name AS name_ord FROM documents
sql_attr_str2ordinal = name_ord
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This stores each attribute in lexical order.  Meaning if your name's are Apple, Aardvark, Button, Choco-room they would be given the ordinal 2, 1, 3, 4 respectively.&lt;/p&gt;

&lt;p&gt;However, this is case-insensitive.  So trying this approach:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sql_query = SELECT name, UPPER(name) AS name_ord FROM documents
sql_attr_str2ordinal = name_ord
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Will allow for case-insensitive alphabetical sorting in Sphinx.&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>Advice for people seeking a mortgage </title>
   <link href="http://davedash.com/2010/02/28/advice-for-people-seeking-a-mortgage/"/>
   <updated>2010-02-28T00:00:00-08:00</updated>
   <id>http://davedash.com/2010/02/28/advice-for-people-seeking-a-mortgage</id>
   <content type="html">&lt;p&gt;So Katie and I decided to buy our first home (a condo) in California last year.  From our first house (in Minneapolis) the lessons we learned was to have your 20% saved up ahead of time before taking the plunge.  We're fans of traditional 30-year loans (or 15 year loans if you can swing it) as they are fairly predictable and 20% will buy your way out of mortgage insurance.&lt;/p&gt;

&lt;p&gt;20% seems like a lot, and it is, but that seemed to be the least of our problems.  Here's some more advice:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Maintain a separate account for funding your laon.&lt;/strong&gt;  Have a separate account for funding your loan.  Temporarily have your paychecks go there, have your gift money go there, stock sales, etc.  This way you can build up your 20% without having to worry about miscellaneous income.  E.g. I had some small amounts of money enter my account due to expenses that I filed with my employer.  I had to paper-trail those.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Get your funding in advance.&lt;/strong&gt; If you can have the aforementioned account fully funded with your 20% a few months before you seek a loan, you could save a lot of trouble.  Our mortgage officer seemed to only care about 2 months of history.  However, this is hard since in a down economy having a large chunk of change just sitting there isn't always a great idea.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Link your accounts.&lt;/strong&gt; Link all your accounts to the source account for your mortgage.  If you have stocks, savings or other checking accounts make sure that you can quickly transfer money into your source account.  Closing costs, interest rates and other seemingly minor details can force you to quickly sell something (like stock) and fund an account.  I didn't have my accounts linked, and I think I managed on funding from an unlinked source at the last minute.  It was very tense.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Know your transfer times.&lt;/strong&gt; I'd give everything about a week to clear.  It usually takes a few days, but every now and then it takes much longer for money to clear out of one account and into another.  Keep a calendar open.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Have everything ready to go a few weeks early.&lt;/strong&gt; The tenseness of waiting for banks and fiduciary firms to get their acts together will give you endless migraines.  Also, if everything is ready in advance, you may get your closing date moved up.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Paper trail everything.&lt;/strong&gt; If you don't need the money to make closing, don't put it in your source account.  If you do need the money, show a paper trail.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Have your loan officer make a schedule for you.&lt;/strong&gt; Our loan officer was horrible since we had no idea what needed to be done when.  So we would frantically get things together for her, and realize it was all for naught.  Once you have a desired closing date, tell them to give you deadlines for having things.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;While I wish I had this advice when I bought our place, we did manage to get all our ducks in a row and close without delay.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Retrieving elements in a specific order in Django and mySQL</title>
   <link href="http://davedash.com/2010/02/11/retrieving-elements-in-a-specific-order-in-django-and-mysql/"/>
   <updated>2010-02-11T00:00:00-08:00</updated>
   <id>http://davedash.com/2010/02/11/retrieving-elements-in-a-specific-order-in-django-and-mysql</id>
   <content type="html">&lt;p&gt;If you have a list of ordered ids and you want to turn them into an ordered result set you can use &lt;code&gt;FIELD()&lt;/code&gt; in mysql:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SELECT * FROM addons
ORDER BY FIELD(id, 3, 5, 9, 1);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a handy trick if you use an external search engine which gives you an ordered list of ids and you want to pull out entire row sets.&lt;/p&gt;

&lt;p&gt;We do this in &lt;a href=&quot;http://github.com/jbalogh/zamboni&quot;&gt;addons.mozilla.org&lt;/a&gt; using the Django ORM like so:&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/301162.js&quot;&gt;&lt;/script&gt;


&lt;p&gt;&lt;a href=&quot;http://github.com/jbalogh/zamboni/commit/a0166108e8a62f386b4310cab0ceb3502575d520#L1R219&quot;&gt;The code in action&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>Django: Model Inheritance or Related Tables wrt AMO</title>
   <link href="http://davedash.com/2009/12/15/django-model-inheritance-or-related-tables-wrt-amo/"/>
   <updated>2009-12-15T00:00:00-08:00</updated>
   <id>http://davedash.com/2009/12/15/django-model-inheritance-or-related-tables-wrt-amo</id>
   <content type="html">&lt;p&gt;When I attended DjangoCon this year, I lamented that our flagship web property was difficult to test, and not fun to develop.  I figured DjangoCon was a way to placate me, and Django might mean something for some of the smaller projects at Mozilla.  However, Wil Clouser, our lead web developer, &lt;a href=&quot;http://micropipes.com/blog/2009/11/17/amo-development-changes-in-2010/&quot;&gt;announced development changes&lt;/a&gt; for &lt;a href=&quot;http://addons.mozilla.org&quot;&gt;addons.mozilla.org&lt;/a&gt; (AMO) that says we'll be moving to Django.&lt;/p&gt;

&lt;p&gt;Wil was open to Django and knew that's what we in the dev team wanted.  Jeff spawned our foray into a new AMO with &lt;a href=&quot;http://github.com/jbalogh/zamboni&quot;&gt;Zamboni&lt;/a&gt;.  I've been working on some grunt-work tasks inside and outside of Django.&lt;/p&gt;

&lt;p&gt;One of those tasks is building a transparent layer in Django to keep users logged in from our PHP-based site.  That kind of problem almost immediately forces you to ask one of the most fundamental questions you ask when using any framework:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;How much do I change my app, in order to accommodate the framework?&lt;/p&gt;&lt;/blockquote&gt;

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

&lt;p&gt;More specifically:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Should I use the &lt;code&gt;django.contrib.auth&lt;/code&gt; User module, and to what extent?&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The more we looked into what features of Django we might want to use, &lt;code&gt;django.contrib.auth&lt;/code&gt; was heavily tied into other things we wanted, so it made sense for us to use it.  The next question is whether we try the &lt;a href=&quot;http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/&quot;&gt;inheritance approach&lt;/a&gt; or do we treat our legacy users table as a sort of User Profile and utilize the User module using the &lt;a href=&quot;http://www.b-list.org/weblog/2007/feb/20/about-model-subclassing/&quot;&gt;related table approach&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Using model-inheritance seems real nice, because we can pretend that our legacy user is the same thing as a &lt;code&gt;djaango.contrib.auth&lt;/code&gt; User - but this isn't true:&lt;/p&gt;

&lt;p&gt;Looking at our &lt;code&gt;users&lt;/code&gt; table more closely:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql&amp;gt; explain users;
+-------------------------+---------------------+------+-----+---------------------+----------------+
| Field                   | Type                | Null | Key | Default             | Extra          |
+-------------------------+---------------------+------+-----+---------------------+----------------+
| id                      | int(11) unsigned    | NO   | PRI | NULL                | auto_increment |
| email                   | varchar(255)        | YES  | UNI | NULL                |                |
| password                | varchar(255)        | NO   |     |                     |                |
| firstname               | varchar(255)        | NO   |     |                     |                |
| lastname                | varchar(255)        | NO   |     |                     |                |
| nickname                | varchar(255)        | YES  | MUL | NULL                |                |
| bio                     | int(11) unsigned    | YES  | MUL | NULL                |                |
| emailhidden             | tinyint(1) unsigned | NO   |     | 0                   |                |
| sandboxshown            | tinyint(1) unsigned | NO   |     | 0                   |                |
| homepage                | varchar(255)        | YES  |     | NULL                |                |
| display_collections     | tinyint(1) unsigned | NO   |     | 0                   |                |
| display_collections_fav | tinyint(1) unsigned | NO   |     | 0                   |                |
| confirmationcode        | varchar(255)        | NO   |     |                     |                |
| resetcode               | varchar(255)        | NO   |     |                     |                |
| resetcode_expires       | datetime            | NO   |     | 0000-00-00 00:00:00 |                |
| notifycompat            | tinyint(1) unsigned | NO   | MUL | 1                   |                |
| notifyevents            | tinyint(1) unsigned | NO   | MUL | 1                   |                |
| deleted                 | tinyint(1)          | YES  |     | 0                   |                |
| created                 | datetime            | NO   | MUL | 0000-00-00 00:00:00 |                |
| modified                | datetime            | NO   |     | 0000-00-00 00:00:00 |                |
| notes                   | text                | YES  |     | NULL                |                |
| location                | varchar(255)        | NO   |     |                     |                |
| occupation              | varchar(255)        | NO   |     |                     |                |
| picture_type            | varchar(25)         | NO   |     |                     |                |
| averagerating           | varchar(255)        | YES  |     | NULL                |                |
+-------------------------+---------------------+------+-----+---------------------+----------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can very easily argue that this is a profile table, which happens to have credential information thrown in.&lt;/p&gt;

&lt;p&gt;I can see overtime, I'll just struggle to keep our legacy User to act like a Django User, whereas a UserProfile is fairly standard.&lt;/p&gt;

&lt;p&gt;Had I been writing this app from scratch, I would have chosen the UserProfile route.  This is extra data which takes up a lot of space, and changes far more often than user credentials.  Changing 4M+ rows sucks, by making users our UserProfile table, any changes to that table, don't tie up the table used for sign-ins.&lt;/p&gt;

&lt;p&gt;I'm curious what other people who port their apps to Django have done.&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>mySQL and the grand regexp retardedness with lettercasing</title>
   <link href="http://davedash.com/2009/09/19/mysql-and-the-grand-regexp-retardedness-with-lettercasing/"/>
   <updated>2009-09-19T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/09/19/mysql-and-the-grand-regexp-retardedness-with-lettercasing</id>
   <content type="html">&lt;p&gt;I wanted to find a list of Firefox addons that had smushed text in their title.  E.g. FireBug or StumbleUpon.  The normal porter stemming algorithm that Sphinx uses does not turn &quot;StumbleUpon&quot; into &quot;stumbl upon&quot; as it would with &quot;Stumble Upon&quot;.  I was hoping for, and unfortunately could not find a method to do a regular expression search/replace using mysql.  If I could, I could have Sphinx read &quot;StumbleUpon&quot; as &quot;Stumble Upon&quot; and all would be well (although in theory this would backfire).&lt;/p&gt;

&lt;p&gt;So my Plan B was to get a list of common smushed named addons (I'd say camelCase, but camelCase is different from SmushedText).  Naturally I used my exceptional skill at regular expressions to concoct this query:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql&amp;gt; SELECT name FROM translated_addons WHERE name REGEXP '[a-z][A-Z][a-z]' = 1 LIMIT 10;
+------------------------+
| name                   |
+------------------------+
| Orbit Grey             | 
| Phoenity               | 
| Pinball                | 
| Qute                   | 
| FirefoxModern          | 
| Adblock                | 
| Add Bookmark Here      | 
| All-in-One Gestures    | 
| Bookmarks Synchronizer | 
| Browser Uptime         | 
+------------------------+
10 rows in set (41.28 sec)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wait... none of these match.  I scratched my head for a bit and then thought, oh wait, mysql is case insenstivie maybe it's turning &lt;code&gt;[a-z][A-Z][a-z]&lt;/code&gt; into &lt;code&gt;[a-z][a-z][a-z]&lt;/code&gt; &amp;#8213; stupid, but consistent with mysql.  Then I pulled my other regexp card out of my sleve, character classes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql&amp;gt; SELECT name FROM translated_addons WHERE name REGEXP '[[:lower:]][[:upper:]][[:lower:]]' = 1 LIMIT 10;
+------------------------+
| name                   |
+------------------------+
| Orbit Grey             |
| Phoenity               |
| Pinball                |
| Qute                   |
| FirefoxModern          |
| Adblock                |
| Add Bookmark Here      |
| All-in-One Gestures    |
| Bookmarks Synchronizer |
| Browser Uptime         |
+------------------------+
10 rows in set (12.96 sec)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;No difference.  Time to pull out the &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.1/en/regexp.html&quot;&gt;mysql documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;REGEXP is not case sensitive, except when used with binary strings.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;ORLY?&lt;/p&gt;

&lt;p&gt;Case-insenstive regular expressions when looking for &lt;code&gt;[[:upper:]]&lt;/code&gt; or &lt;code&gt;[[:lower:]]&lt;/code&gt;?  Fine... I'll add some syntax to make you work right:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql&amp;gt; SELECT DISTINCT name FROM translated_addons WHERE name REGEXP BINARY '[[:lower:]][[:upper:]][[:lower:]]' = 1 LIMIT 10;
+---------------------------+
| name                      |
+---------------------------+
| FirefoxModern             |
| ChatZilla                 |
| ChromEdit                 |
| CuteMenus                 |
| DownloadWith              |
| easyGestures              |
| JavaScript Console Status |
| LinkVisitor               |
| OpenBook                  |
| QuickNote                 |
+---------------------------+
10 rows in set (9.68 sec)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's more like it!&lt;/p&gt;

&lt;p&gt;Unfortunately there's about 2609 addons matching this query and since I can't automatically fix these in mysql, I'll need to do some work:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1.  Create a new table for additional indexable data.
2.  Upon creation of any new addons with names that have SmushedText - store the &quot;un smushed text&quot;.
3.  Index this &quot;extras&quot; field in Sphinx.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Bug: &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=517699&quot;&gt;517699&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>Resolving Django dumpdata errors</title>
   <link href="http://davedash.com/2009/09/13/resolving-django-dumpdata-errors/"/>
   <updated>2009-09-13T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/09/13/resolving-django-dumpdata-errors</id>
   <content type="html">&lt;p&gt;Recently I recieved this wonderful piece of news when I ran &lt;code&gt;./manage.py dumpdata&lt;/code&gt; for the first time:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Error: Unable to serialize database: User matching query does not exist.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I knew this might not work out since I was dealing with a legacy database, but the resolution is quite simple.  First I had to narrow it down to which app was causing this.  Naturally I assumed it was one of the two apps I had, either &lt;code&gt;common&lt;/code&gt; or &lt;code&gt;restaurant&lt;/code&gt;.  So I ran: &lt;code&gt;./manage.py dumpdata common&lt;/code&gt; and &lt;code&gt;./manage.py dumpdata restaurant&lt;/code&gt;.  The latter had no problem whatsoever.&lt;/p&gt;

&lt;p&gt;This made sense, since my &lt;code&gt;common&lt;/code&gt; application was the only one that made any reference to a &lt;code&gt;User&lt;/code&gt;.  By looking in my &lt;code&gt;models.py&lt;/code&gt; for that application, I narrowed it down to my &lt;code&gt;Profile&lt;/code&gt; object.  Sure enough, commenting it out meant I could get my data.&lt;/p&gt;

&lt;p&gt;It ended up being a foreign key mismatch between the &lt;code&gt;profile&lt;/code&gt; and &lt;code&gt;user&lt;/code&gt; tables.  Since this is legacy data, this mismatch made sense.  A simple &lt;code&gt;SELECT id,userid FROM profile WHERE userid NOT IN (SELECT id FROM auth_user)&lt;/code&gt; gave me a list of bad profiles.  Removing them allowed me to create my Django fixtures.&lt;/p&gt;
</content>
 </entry>
 

</feed>

