<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Geek at Play</title>
	<atom:link href="http://www.kylev.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kylev.com</link>
	<description>kylev in text form</description>
	<lastBuildDate>Tue, 15 Feb 2011 03:19:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.4</generator>
		<item>
		<title>Mongo Mapper and hybrid deployments: a first hack</title>
		<link>http://www.kylev.com/2011/02/14/mongo-mapper-and-hybrid-deployments-a-first-hack/</link>
		<comments>http://www.kylev.com/2011/02/14/mongo-mapper-and-hybrid-deployments-a-first-hack/#comments</comments>
		<pubDate>Tue, 15 Feb 2011 01:31:40 +0000</pubDate>
		<dc:creator>kylev</dc:creator>
				<category><![CDATA[Geekdom]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.kylev.com/?p=527</guid>
		<description><![CDATA[At work we&#8217;re using RoR atop MySQL to build our core web application. As with many companies, we&#8217;re realizing that certain types of scaling problems may be better solved in the NoSQL world. While looking into MongoDB, I&#8217;ve found it somewhat surprising that the two dominant Rails-ready adapters (mongo_mapper and Mongoid) don&#8217;t really answer the [...]]]></description>
			<content:encoded><![CDATA[<p>At work we&#8217;re using RoR atop <a href="http://mysql.com/">MySQL</a> to build our core web application.  As with many companies, we&#8217;re realizing that certain types of scaling problems may be better solved in the NoSQL world.  While looking into <a href="http://www.mongodb.org/">MongoDB</a>, I&#8217;ve found it somewhat surprising that the two dominant Rails-ready adapters (<a href="http://mongomapper.com/documentation/">mongo_mapper</a> and <a href="http://mongoid.org/">Mongoid</a>) don&#8217;t really answer the question of hybrid deployments.  In fact, much of the &#8220;getting started&#8221; documentation includes a section on ripping out ActiveRecord (since you obviously won&#8217;t need it now that you&#8217;re playing with a new NoSQL data store).</p>
<p>Similarly, there are few, if any, stories of people migrating just parts of their schema into MongoDB.  Either people aren&#8217;t doing this or nobody is blogging about it.  I found several conversations about people just abandoning the idea and converting wholesale to MongoDB.  Given the 40-minute time span between some of these postings, these are either the greatest coders ever or they&#8217;re converting toys/demos/explorations rather than years-old applications with dozens of tables and tens of thousands of regular users.</p>
<p>As I started to work on things, it became clear that the document oriented nature of MongoDB was going to necessitate some changes in how we do things.  Gone (in some ways) are a number of the easy and familiar ActiveRecord methods for associations between records.  This goes double for a system with some parts in a relational database and other parts in a document store.  Rather than just typing <code>belongs_to</code> and moving on, you end up having to write your own accessors and mutators over and over again.</p>
<p>This, of course, is silly.  I&#8217;ve only been coding Ruby for a little while but it was clear that I should be able to <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a> this up a little.  Plus <code>mongo_mapper</code> (which I&#8217;m currently tentatively useing) provides plugins as a way to provide core functionality, making it easy to extend.</p>
<p>I&#8217;m still not great at Ruby, Rails, or some of the idioms that are standard to development with this world, but it didn&#8217;t take me long to write something that provides <code>belongs_to_ar</code>, a convenience variation to a <code>key</code> that creates a new key field and automatically handles loading/storing references to ActiveRecord (the objects still in your relational database).</p>
<pre class="brush:rb">
module MongoAdapt
  module ExternalKey

    def self.included(model)
      model.plugin MongoAdapt::ExternalKey
    end

    module ClassMethods
      def belongs_to_ar(name, *args)
        key :"#{name}_id", Integer
        create_link_methods_for(name)
      end

      private
        def create_link_methods_for(name)
          # See MongoMapper::Plugin::Keys
          class_name = name.to_s.classify
          key_name = :"#{name.to_s}_id"
          accessors_module.module_eval <<-end_eval
            def #{name}
              #{class_name}.find(read_key(:#{key_name}))
            end

            def #{name}=(value)
              write_key(:#{key_name}, value.id)
            end

            def #{name}?
              read_key(:#{key_name}).present?
            end
          end_eval

          include accessors_module
        end
    end
  end
end

MongoMapper::Document.append_inclusions(MongoAdapt::ExternalKey)
</pre>
<p>With this loaded, I can now do <code>belongs_to_ar :user</code> on a <code>MongoMapper::Document</code> and get a <code>user_id</code> field in the underlying document as well as <code>user</code> and <code>user=</code> methods that operate with <code>User</code> objects.  This, of course, only handles a single direction for the relationship (going from a Mongo Mapper document to a ActiveRecord object).</p>
<p>I imagine I'll refine this a bit further and post some more about the challenges of a hybrid deployment as I go along.  For one thing, it needs a more Ruby-ish (what the hell is the equivalent term to python-ic?) name.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kylev.com/2011/02/14/mongo-mapper-and-hybrid-deployments-a-first-hack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stupid Ruby tricks</title>
		<link>http://www.kylev.com/2011/01/20/stupid-ruby-tricks/</link>
		<comments>http://www.kylev.com/2011/01/20/stupid-ruby-tricks/#comments</comments>
		<pubDate>Thu, 20 Jan 2011 08:42:43 +0000</pubDate>
		<dc:creator>kylev</dc:creator>
				<category><![CDATA[Geekdom]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.kylev.com/?p=522</guid>
		<description><![CDATA[Over at work, I&#8217;m rapidly getting up to speed on Ruby and Rails. It&#8217;s fun and a little wacky (and, not to mention, very fast-paced for us right now). This snipped cracked me up when I saw Jared use it while debugging. class Object def wtf! raise (self.respond_to?(:pretty_inspect) ? self.pretty_inspect : self.inspect) end end Totally [...]]]></description>
			<content:encoded><![CDATA[<p>Over at work, I&#8217;m rapidly getting up to speed on <a href="http://www.ruby-lang.org/">Ruby</a> and <a href="http://rubyonrails.org/">Rails</a>.  It&#8217;s fun and a little wacky (and, not to mention, very fast-paced for us right now).  This snipped cracked me up when I saw <a href="https://github.com/deadlyicon">Jared</a> use it while debugging.</p>
<pre class="brush:rb">
class Object
  def wtf!
    raise (self.respond_to?(:pretty_inspect) ? self.pretty_inspect : self.inspect)
  end
end
</pre>
<p>Totally unnecessary, but man is it fun to type <code>request.wtf!</code> when doing initial debugging on a controller.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kylev.com/2011/01/20/stupid-ruby-tricks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>In support of BYOBW 2010</title>
		<link>http://www.kylev.com/2010/03/12/in-support-of-byobw-2010/</link>
		<comments>http://www.kylev.com/2010/03/12/in-support-of-byobw-2010/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 07:01:47 +0000</pubDate>
		<dc:creator>kylev</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[politics]]></category>
		<category><![CDATA[sf]]></category>

		<guid isPermaLink="false">http://www.kylev.com/?p=518</guid>
		<description><![CDATA[Easter is fast approaching and that can mean only one thing: a few people are trying to block the Bring Your Own Big Wheel event that has happened for the last few years on my street. This year, several people have undertaken the work required to make this a legal, permitted, and insured event for [...]]]></description>
			<content:encoded><![CDATA[<p>Easter is fast approaching and that can mean only one thing: a few people are trying to block the <a href="http://www.jonbrumit.com/byobw.html">Bring Your Own Big Wheel</a> event that has happened for the last few years on my street.  This year, several people have undertaken the work required to make this a legal, permitted, and insured event for the whole family.  There&#8217;s a permit hearing coming up and here is the letter I&#8217;m filing in support of the event.</p>
<blockquote><p>My name is Kyle VanderBeek and I reside at 8xx Vermont Street, the last turn on the curvy portion of Vermont Street in Potrero Hill.  I am writing this letter to express my support for the Bring Your Own Big Wheel (BYOBW) event being considered for April 4, 2010. </p>
<p>I moved into my current apartment just before the BYOBW event in 2008.  When I heard it was happening, I was incredibly pleased and decided to turn it into an opportunity to gather with my friends.  These events transform an otherwise normal Sunday into a time of celebration and community.  I get to make food, be a host, and join my friends on the balcony to watch the spectacle.  Many of us also choose to participate in what is truly a uniquely San Francisco experience; one that is family-friendly, joyous, and wacky. </p>
<p>I have enjoyed BYOBW for the last two years, and am encouraged by the additional organizational efforts being put forth this year (including more portable restroom facilities and monitors along the course).  It has always been a low impact event, and I anticipate that being true this year as well. </p>
<p>As a directly-impacted neighbor, I urge the City of San Francisco to allow this annual event to continue and by doing so support the right of the people to assemble and be silly. </p>
<p>Thank you.</p></blockquote>
<p>I really hope everything goes well.  I can&#8217;t wait to throw a party!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kylev.com/2010/03/12/in-support-of-byobw-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Finding my first Python reference cycle</title>
		<link>http://www.kylev.com/2009/11/03/finding-my-first-python-reference-cycle/</link>
		<comments>http://www.kylev.com/2009/11/03/finding-my-first-python-reference-cycle/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 19:31:34 +0000</pubDate>
		<dc:creator>kylev</dc:creator>
				<category><![CDATA[Geekdom]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.kylev.com/?p=479</guid>
		<description><![CDATA[I&#8217;ve worked in Python for nearly six years now and, up to this point, I&#8217;ve not had to deal with the king of memory-related gotchas: the reference cycle. Simply put, a reference cycle happens when two or more objects create a cyclic directed graph in their path of references (ok, not that simple). The simplest [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve worked in Python for nearly six years now and, up to this point, I&#8217;ve not had to deal with the king of memory-related gotchas: the reference cycle.  Simply put, a reference cycle happens when two or more objects create a cyclic directed graph in their path of references (ok, not that simple).  The simplest form is the &#8220;I point to you, you point to me, neither of our reference counts get to zero&#8221; scenario.</p>
<p>Usually, this isn&#8217;t a big deal.  Although objects don&#8217;t get immediately collected when dereferenced, the garbage collector will eventually notice that there is some wasted memory, do the more expensive cycle detection work, and free the objects.  In many scenarios like single-run scripts, cron jobs, or low-load applications you&#8217;ll never notice; Python does it&#8217;s job, keeps things clean, and stays out of your way.  If, however, you&#8217;re writing a high performance internet server intended to handle the ever increasing demands of the modern Internet, you just might be screwed.  That GC work will cost you desired though-put and scalability.  In the worst case, the GC won&#8217;t be invoked in time and you&#8217;ll hemorrhage memory (or at least gobble it up in competition with other things your system might need to do).  I this case, initial numbers left us with a customer-detectable throughput degradation when a particular security feature was enabled.</p>
<p>Without further ado, here is the distilled pattern that ran us into trouble.</p>
<pre class="brush:py">
class Filter:
    def __init__(self, callback):
        self._callback = callback

    def update(self, data):
        """Override and call parent."""
        self._callback(data)

class AddLF(Filter):
    def update(self, data):
        data = data + '\n'
        Filter.update(self, data)

class AddCRLF(Filter):
    def update(self, data):
        data = data + '\r\n'
        Filter.update(self, data)

class Foo:
    def __init__(self, dos_mode=False):
        if dos_mode:
            self._filter = AddCRLF(self.the_callback)
        else:
            self._filter = AddLF(self.the_callback)
        self._filtered_data = list()

    def update(self, data):
        self._filter.update(data)

    def the_callback(self, data):
        self._filtered_data.append(data)

    def all_data(self):
        return ''.join(self._filtered_data)
</pre>
<p>At a glance, this isn&#8217;t an unreasonable design pattern.  If you&#8217;re writing a cross platform tool, or something that needs to listen on a socket and account for variations and flaws in protocol implementations, passing the input through a filter to clean it up is reasonable.  It&#8217;s even somewhat pythonic in that a call-back is used, allowing for various patterns of code re-use and subclassing in both the filters and the consumer.</p>
<p>The usage pattern is something like this: for each chunk of data you receive, call <code>update()</code>, the main class hands the data off to the filter, the filter does its thing, and uses the callback to pass the data back up.</p>
<pre class="brush:py">
# Many of you will recognize this pattern from crypto digests
f = Foo()
f.update('asdf')
f.update('jkl;')
print f.all_data()
f = None
# At this point ref-counting could have reclaimed the object
</pre>
<p>Pay attention to that last line: when we assign <code>f = None</code>, under normal circumstances the reference count would hit zero, and all objects should be collected.  Here this is not the case!</p>
<p>Once I realized this region of code was the likely culprit, I started playing with the <code><a href="http://docs.python.org/library/gc.html">gc</a></code> module and its debugging abilities.  Most importantly, using the <code>gc.DEBUG_SAVEALL</code> setting causes the garbage collector to (instead of completing collection) store all unreachable objects in a list named <code>gc.garbage</code>.  This can be examined for hints.</p>
<pre class="brush:py">
import gc, pprint

gc.set_debug(gc.DEBUG_SAVEALL)
print gc.get_count()
print gc.collect()
pprint.pprint(gc.garbage)
</pre>
<p>Here is the output from that single object creation.</p>
<pre class="brush:text">
(249, 5, 0)
6
[{'_filter': &lt;__main__.AddLF instance at 0x7f23ec3261b8&gt;,
  '_filtered_data': ['asdf\n', 'jkl;\n']},
 &lt;__main__.Foo instance at 0x7f23ec326170&gt;,
 &lt;bound method Foo.the_callback of &lt;__main__.Foo instance at 0x7f23ec326170&gt;&gt;,
 {'_callback': &lt;bound method Foo.the_callback of &lt;__main__.Foo instance at 0x7f23ec326170&gt;&gt;},
 &lt;__main__.AddLF instance at 0x7f23ec3261b8&gt;,
 ['asdf\n', 'jkl;\n']]
</pre>
<p>You might be able to see the loop already.  We have, left over, a <code>Foo</code> instance, an <code>AddLF</code> instance (which we know is stored as a member variable of <code>Foo</code>), and (most importantly) a reference to a <em>bound method</em> on <code>Foo</code>.  This <em>bound method</em> holds a reference back to the <code>Foo</code> instance, completing the cycle.</p>
<p>What the original designer of this code probably didn&#8217;t realize is that passing that callback when instantiating a Filter would create that loop (via the bound instance method, which has a reference to the instance).  After a minor refactoring, I&#8217;ve gotten rid of the cycle and reference counts hit zero when the last external reference to a <code>Foo</code> object is eliminated.  Most importantly all the related data is freed as well; in this case <code>Foo._filtered_data</code> (which could grow to be very large) will get freed up as well.</p>
<p>This anti-pattern is only one step away from the simplest case reference cycle, but it had real consequences.  With it gone, memory is managed far more efficiently and this feature is usable in a demanding, high-performance environment.</p>
<p><em>I do not host comments due to spam and abuse.  <a href="http://www.reddit.com/r/Python/comments/a0lnu/finding_my_first_python_reference_cycle/">Discuss this post at reddit</a></em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kylev.com/2009/11/03/finding-my-first-python-reference-cycle/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>My first time being censored</title>
		<link>http://www.kylev.com/2009/09/17/my-first-time-being-censored/</link>
		<comments>http://www.kylev.com/2009/09/17/my-first-time-being-censored/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 17:43:15 +0000</pubDate>
		<dc:creator>kylev</dc:creator>
				<category><![CDATA[Day in the Life]]></category>
		<category><![CDATA[ethics]]></category>
		<category><![CDATA[health]]></category>
		<category><![CDATA[skeptic]]></category>

		<guid isPermaLink="false">http://www.kylev.com/?p=464</guid>
		<description><![CDATA[I&#8217;m not terribly active on the &#8220;public&#8221; Internet. I have my blog, which I suspect is mostly read by my friends and a few seekers of Python knowledge. I belong to a forum here or comment on a favorite blog there. I use Facebook quite a bit to keep up with friends and pass things [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m not terribly active on the &#8220;public&#8221; Internet.  I have my blog, which I suspect is mostly read by my friends and a few seekers of Python knowledge.  I belong to a forum here or comment on a favorite blog there.  I use Facebook quite a bit to keep up with friends and pass things I&#8217;ve found among my social circle.  I just don&#8217;t bother much with public discussions since they seem to devolve into nonsense and I just don&#8217;t see the point in playing that game.  I don&#8217;t even allow comments on this blog since I don&#8217;t see the need to host other people&#8217;s idiocy or vitriol.  About the only place you&#8217;d find me with any sort of regularity is <a href="http://www.reddit.com/">reddit</a>, but even that is sporadic.</p>
<p>I&#8217;m even a fairly quiet <a href="http://www.jref.org/">skeptic</a>, preferring to share what I&#8217;m learning with those around me rather than engaging in public text-based shouting matches.  The events of this past weekend started out that way: an old friend of mine from massage school, Sam, posted a link to Examiner.com that <a href="http://www.examiner.com/x-6258-Huntsville-Natural-Parenting-Examiner~y2009m9d8-New-study-finds-home-birth-as-safe-as-hospital-birth">erroniously claimed that home birth was proven as safe as hospital birth</a>.  Since many medical studies are badly reported, I checked the article.</p>
<p>I immediately recognized the <a href="http://www.cmaj.ca/cgi/rapidpdf/cmaj.081869">study from the University of BC</a> in Canada.  I&#8217;d already read it, and it had been similarly misrepresented elsewhere.  It&#8217;s not that the study&#8217;s conclusions are false, it&#8217;s that they are narrow.  Home birth has similar infant mortality rates only in Canada where a single type of certification exists: the Nurse Midwife.  This is a college-educated position with clinic hours, lots of training, and a great deal of time spent doing both hospital and home births.  They&#8217;re full-on nurses.  That&#8217;s not the case in the US where we have several different types of midwives, some with surprisingly little training (and potentially zero clinic hours).  The Skeptical OB <a href="http://skepticalob.blogspot.com/2009/09/new-canadian-study-is-bad-news-for.html">is where I&#8217;d seen the study before, and she covers it well</a>.  The bottom line is that these lesser trained midwives have an infant mortality rate triple that of the highly trained Canadian midwives.</p>
<p>So it&#8217;s fair to say that the result isn&#8217;t intended to be assumed in the general case, right?  I recognized the over-zealous rhetoric of someone who really wants to believe that all things natural are automatically better.  The author on Examiner.com was calling herself the &#8220;natural parenting examiner&#8221;, so that&#8217;s to be expected.  But it doesn&#8217;t excuse misreporting a study, especially since the original authors specifically warn against over-generalizing the result beyond its intended scope.</p>
<p>So I commented.  I asked her to cite her sources (she had not linked, a clue that she might be getting her information third-hand).  I provided a link to the Skeptical OB coverage.  I was polite and brief.</p>
<p>But then curiosity got the best of me.  Having spent a considerable amount of time reading all sides of various health issues, I suspected I was reading the work of another enthusiastic but careless advocate.  So I clicked on <a href="http://www.examiner.com/x-6258-Huntsville-Natural-Parenting-Examiner">her bio</a> and found this:</p>
<blockquote><p>Katie Drinkard is a self-proclaimed natural parenting guru who has done extensive research on natural pregnancy and parenting. Katie presents vital information in a personal manner while providing the latest research on natural parenting topics &#8211; ranging from birth through the childhood years.</p></blockquote>
<p>Right.  Well, that&#8217;s not exactly a stellar CV.  Lack of formal training certainly doesn&#8217;t make one wrong (remember, I&#8217;m a software engineer commenting on health issues), but dropping words like &#8220;guru&#8221; has always unnerved me.  I already suspected what I was going to find when I clicked on her other articles, but I had to be sure.</p>
<p>Naturally, one title that jumped out at me was &#8220;Swine Flu vaccine contains diseased flesh of African Monkeys&#8221;.  No, <a href="http://www.examiner.com/x-6258-Huntsville-Natural-Parenting-Examiner~y2009m8d6-Swine-Flu-vaccine-contains-diseased-flesh-of-African-monkeys">I&#8217;m not kidding</a>, she actually wrote this.  Surely she was just being hyperbolic!  Nope.  Another predictive sense was tingling in my brain as I read this gem of a final paragraph:</p>
<blockquote><p>Scientists create the Swine Flu vaccine (and other vaccines) by injecting monkeys with the virus and allowing the disease to take over.  Later, the monkey is then killed and its diseased organs are used to make the ingredients of vaccines given to the public.</p></blockquote>
<p>Oh, <a href="http://plognark.com/?q=node/1129">the stupid, it burns</a>!  I just knew this sort of wrong-headed nonsense could only come from a single source: Mike Adams at Natural News.  Sure enough, in seconds I&#8217;d found his article making the same <a href="http://www.naturalnews.com/026779_swine_flu_patents_vaccines.html">bogus claim</a>.</p>
<p>What makes it bogus?  In the process of seeking the &#8220;truth&#8221; in the text of a <a href="http://www.patentstorm.us/patents/5911998/claims.html">vaccine patent</a>, Mr. Adams (not a doctor in any sense) inferred from the line &#8220;producing said virus using a cell line isolated from the kidney of an African Green Monkey&#8221; that there must exist a warehouse of angry, sick monkeys being fed into a meat grinder.  Well, that&#8217;s not the case.  Anyone who has spent more than an hour actually trying to understand vaccines will key on the words &#8220;cell line&#8221; and know that they&#8217;re referring to some laboratory-grade line of perpetually grown cells that can be used as a growth medium.  Sure enough, again within seconds, I&#8217;d found that there is a widely used line named &#8220;<a href="http://en.wikipedia.org/wiki/Vero_cell">Vero</a>&#8221; that was isolated from African Green Monkey kidney epithelial cells <em>way back in 1962</em>.</p>
<p>So I made my way back to the Examiner.com article and assured the author that there was no monkey holocaust.  I quickly pointed out how she was in error, and provided an explanation of cell lines and how they&#8217;re used.  Four or five sentences and I was done.</p>
<p>A day later, both of my comments were gone.  They appear to have been deleted.  Granted, there is no way I can prove this to anyone since I don&#8217;t have access to the site&#8217;s history or databases. I can, however, say that Ms. Drinkard <em>did</em> update her birthing post using the link I provided. I suppose that&#8217;s something, but she didn&#8217;t correct or clarify anything.</p>
<p>I&#8217;m disappointed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kylev.com/2009/09/17/my-first-time-being-censored/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Love/Hate and Good Wood Mods</title>
		<link>http://www.kylev.com/2009/07/29/lovehate-and-good-wood-mods/</link>
		<comments>http://www.kylev.com/2009/07/29/lovehate-and-good-wood-mods/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 07:25:05 +0000</pubDate>
		<dc:creator>kylev</dc:creator>
				<category><![CDATA[Geekdom]]></category>
		<category><![CDATA[gaming]]></category>
		<category><![CDATA[rock band]]></category>

		<guid isPermaLink="false">http://www.kylev.com/?p=452</guid>
		<description><![CDATA[I play too much Rock Band. My music game affliction started back with the original Guitar Hero on the PS/2. I was doing the mega-geek rounds around Fry&#8217;s one day and saw it on the demo stand. I played a single song and knew this was something I wanted at home. Mitch had the PS/2 [...]]]></description>
			<content:encoded><![CDATA[<p>I play too much Rock Band.  My music game affliction started back with the original Guitar Hero on the PS/2.  I was doing the mega-geek rounds around Fry&#8217;s one day and saw it on the demo stand.  I played a single song and knew this was something I wanted at home.  Mitch had the PS/2 already, so I went for it.  We played for hours and he quickly started kicking my ass.  But, damn, it was fun to get awarded points and stars for being good at not actually playing music.</p>
<p>Fast forward a couple of years, an update to an Xbox 360, and a few finger strains battling through &#8220;Rein in Blood&#8221;, and I was still having fun.  I&#8217;m not great at it (I&#8217;m really not even a full-fledged &#8220;Hard&#8221; player with the guitar), but who cares?  I get better here and there, and keep enjoying myself.  I picked up Rock Band and drooled over the DLC, still content playing the guitar.  But, oh, the temptation.  I&#8217;d tried the drums elsewhere.  I wanted them&#8230;</p>
<p>Eventually I gave in and bought the Rock Band drum kit and started wailing away trying to teach myself a new skill.  Even though it had never really waned, my interest was renewed.  Bit by bit I got my hands and foot to do the right things in the right order.  Granted, having moved into an apartment, I had to get my drum fix when the downstairs neighbor was out.  I was like a fiend, sneaking a hit whenever I could.</p>
<p>Sadly, my enthusiasm took a toll on the drum kit (as many people have found).  After seeing them used by <a href="http://www.youtube.com/user/azuritereaction">YouTube drum stud azuritereaction</a>, I chose and ordered a set of <a href="http://www.goodwoodmods.com/">Good Wood Mods</a> (their first, extremely home-made variant).</p>
<p>In April (after a long wait) they arrived.  I giggled at the simple packing material.  I installed them.  I played them.  I loved them!  Immediately I realized why several of the best players use Good Wood Mods: they&#8217;re insanely fast.  Compared to the plastic-backed gum rubber pads, they&#8217;re a dream to play and take far less effort.  If you stay relaxed, you can play entire songs on &#8220;Expert&#8221; while barely moving your wrists.  The bounce you feel in the sticks is much less jarring and closer to that of a real drum head.  There&#8217;s none of that dead thud at all.  And, most importantly, they&#8217;re quiet.  Very quiet.</p>
<p>Since I work at a place that also <em>loves</em> Rock Band (and houses a 360), I couldn&#8217;t wait to show the guys.  Only two days into owning the kit, I brought it into work.  As we gathered in our game room at the end of the day, several guys lined up to give them a whirl.  They got rave reviews.  Rave, I say!  Everyone agreed with me that they are a huge leap forward over the stock heads.</p>
<p>Then it all came unraveled.  One of the people who loves playing the game but still plays stiffly (and hits hard) sat down.  Part way through his first song, bang, the blue pad tanked.  It became intermittent and only registered some of the strikes.  Damnit!  I took the set home to test it a little more and, bang, the yellow pad suffered the same fate.  Damnit again!  Fortunately, I&#8217;m a geek (as are the makers, which is awesome).  I broke out the soldering iron, exchanged some emails with the guys who make them, dismantled the heads, and fixed the broken connections (just solder welds on the piezo sensors).</p>
<p>Sadly, this hasn&#8217;t been an isolated issue.  I trust my repairs, but I&#8217;ve had to do or re-do this same sort of fix on all but one of the heads.  There is something fundamentally flawed in the way their design works.  I suspect it&#8217;s the combination of foam inserts and floating piezo mounts that result in friction at the edge of the wire&#8217;s jacket, creating a tugging movement that strains the braided wire.  I fully expect to do this repair again, though I&#8217;m trying various applications of glue as protective covering at the edge of the weld.</p>
<p>Now, the big question&#8230; would I recommend these to other people?  In three words: Yes and No.  I absolutely love playing these over the standard pads.  However, their initial build quality was questionable and I continue to have to make repairs (usually with a couple of months of playing in between).  However, the guys that make them have scaled up and found a manufacturing partner.  Apparently, gone is the questionable-but-endearing use of plywood, varied screws, and slices of PVC pipe.  If you buy a set now, I suspect you&#8217;ll get a fundamentally similar but massively revised product built to higher standards.  If you play a lot and have a few spare dollars, go for it.  I&#8217;m even eying a second set.</p>
<p>If you&#8217;re curious, I also took <a href="http://picasaweb.google.com/vanderbeek/GoodWoodInstall#">few pictures of my Good Woods Mod install and repairs</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kylev.com/2009/07/29/lovehate-and-good-wood-mods/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Start your Python project with optparse and logging</title>
		<link>http://www.kylev.com/2009/07/01/start-your-python-project-with-optparse-and-logging/</link>
		<comments>http://www.kylev.com/2009/07/01/start-your-python-project-with-optparse-and-logging/#comments</comments>
		<pubDate>Wed, 01 Jul 2009 21:15:04 +0000</pubDate>
		<dc:creator>kylev</dc:creator>
				<category><![CDATA[Geekdom]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.kylev.com/?p=432</guid>
		<description><![CDATA[Python continues to be my favorite language to hack in. It&#8217;s useful for tasks big and small and has the advantage of being more readable and maintainable than a lot of other scripting languages. I remember when, having learned the basics of Python, I decided to rewrite my home-built CD-to-MP3 script suite from its perl [...]]]></description>
			<content:encoded><![CDATA[<p>Python continues to be my favorite language to hack in.  It&#8217;s useful for tasks big and small and has the advantage of being more readable and maintainable than a lot of other scripting languages.  I remember when, having learned the basics of Python, I decided to rewrite my home-built CD-to-MP3 script suite from its perl incarnation (perl was my previous favorite language for system programming projects).  I knocked that project out in only about 2 hours, including a major redesign made easy by Python&#8217;s object syntax and built in &#8220;pickle&#8221; for serialization.</p>
<p>Since then, I&#8217;ve usually chosen Python for a variety of system programming tasks.  This includes things like making backups, deploying software, configuration file templating, web site scraping, health monitoring, and some bigger data crunching/graphing.  Time after time, these quick projects (often at work) turned into something bigger.  Eventually they get rolled into a product or adopted by the production operations group as standard kit.</p>
<p>At some point I realized that there was something that I was doing that made this transition from &#8220;quick hack&#8221; to &#8220;standard tool&#8221; easy: I always start my projects with <code><a href="http://docs.python.org/library/logging.html">logging</a></code> and <code><a href="http://docs.python.org/library/optparse.html">optparse</a></code> in place from day zero.  During development, this means that I don&#8217;t have to scatter <code>print</code>-style debugging statements throughout the code, I can just use <code>logging.debug()</code> and turn them on and off at will (via command line flags).  Once deployed or passed on, it means other people using it can immediately start interacting with my script just like other familiar Unix utilities.</p>
<p>So, here is a variation on what my typical python script starts out with.</p>
<pre class="brush:py">#!/usr/bin/python

import logging

def foo():
    """These will only get output if you turn up verbosity."""
    logging.debug("This is debug.")
    logging.info("This is info.")

def bar():
    """These will all be output a default logging levels."""
    logging.warn("Warning!  Things are getting scary.")
    logging.error("Uh-oh, something is wrong.")
    try:
        raise Exception("ZOMG tacos.")
    except:
        logging.exception("Just like error, but with a traceback.")

if '__main__' == __name__:
    # Late import, in case this project becomes a library, never to be run as main again.
    import optparse

    # Populate our options, -h/--help is already there for you.
    optp = optparse.OptionParser()
    optp.add_option('-v', '--verbose', dest='verbose', action='count',
                    help="Increase verbosity (specify multiple times for more)")
    # Parse the arguments (defaults to parsing sys.argv).
    opts, args = optp.parse_args()

    # Here would be a good place to check what came in on the command line and
    # call optp.error("Useful message") to exit if all it not well.

    log_level = logging.WARNING # default
    if opts.verbose == 1:
        log_level = logging.INFO
    elif opts.verbose >= 2:
        log_level = logging.DEBUG

    # Set up basic configuration, out to stderr with a reasonable default format.
    logging.basicConfig(level=log_level)

    # Do some actual work.
    foo()
    bar()</pre>
<p>This is obviously a pretty minimal setup, but it achieves what most people need.  You get option parsing and checking along with usage information.  You get warnings and errors spat out to <code>sys.stderr</code> (leaving <code>sys.stdout</code> for actual program output).  You can specify <code>-v</code> to crank up verbosity.</p>
<p>More than once, I&#8217;ve had a pager-frazzled sysadmin ask me how the heck to use the new tool.  I get to reply, &#8220;Just run it with <code>--help</code>, it has full usage instructions built in.&#8221;  This makes sysadmins happy; really happy.  It means they don&#8217;t have to remember odd semantics or dig around for the how-to page on the internal wiki at 3:00am when they need to use it.  Culturally, there is almost nothing more valuable than a sysadmin who has had success with your code, and nothing worse than one that has had trouble with it.  To me, the first step in granting a sysadmin that sort of success is to make your code act like everything else in <code>/usr/bin</code> and that&#8217;s why I&#8217;ll continue starting my projects in this manner.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kylev.com/2009/07/01/start-your-python-project-with-optparse-and-logging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Caching WordPress content to appease Google Page Speed</title>
		<link>http://www.kylev.com/2009/06/08/caching-wordpress-content-to-appease-google-page-speed/</link>
		<comments>http://www.kylev.com/2009/06/08/caching-wordpress-content-to-appease-google-page-speed/#comments</comments>
		<pubDate>Mon, 08 Jun 2009 22:41:25 +0000</pubDate>
		<dc:creator>kylev</dc:creator>
				<category><![CDATA[Geekdom]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.kylev.com/?p=418</guid>
		<description><![CDATA[I installed the new Google Page Speed plug-in for Firebug (under Firefox) and played with it a little. I&#8217;m impressed. It takes a number of ideas from the similarly awesome YSlow plug-in and goes a few steps further, plus adds a cleaner UI. Of course, I found a couple of really obvious things I could [...]]]></description>
			<content:encoded><![CDATA[<p>I installed the new <a href="http://code.google.com/speed/page-speed/">Google Page Speed</a> plug-in for <a href="https://addons.mozilla.org/en-US/firefox/addon/1843">Firebug</a> (under Firefox) and played with it a little.  I&#8217;m impressed.  It takes a number of ideas from the similarly awesome <a href="http://developer.yahoo.com/yslow/">YSlow</a> plug-in and goes a few steps further, plus adds a cleaner UI.  Of course, I found a couple of really obvious things I could fix.</p>
<p>One of the easiest things is to make sure that your static content is cache-friendly.  It&#8217;s one of those simple tricks that really does have an impact both on the number of bits you have to serve and on the perceived speed of your pages.  Sadly, it gets left out of a lot of CMS/Blog systems (including WordPress).  To speed things up, I created an <a href="http://httpd.apache.org/">Apache</a> <code>.htaccess</code> file with the following:</p>
<pre class="brush:plain">&lt;FilesMatch "\.(gif|jpe?g|png|css|js)$"&gt;
ExpiresActive On
ExpiresDefault "access plus 2 months"
Header set Cache-Control "max-age=5184000, public"
&lt;/FilesMatch&gt;</pre>
<p>For my purposes, I put this particular set of directives in <code>wordpress/wp-content/.htaccess</code> which means that all my theme and plug-in resources (including images, JavaScript, and CSS) get an <code>Expires</code> header 2 months into the future.  It also includes a matching 2-month <code>Cache-Control</code> &#8220;public&#8221; header to let caches know that shared object caching is fine.  With this, both web caches and the browser cache are far more likely to use the copy of these resources they have laying around.</p>
<p>Your mileage may vary (YMMV), but this is good placement for my particular purposes.  It may be safe to put these directives all the way at the top of your document root.  As with any caching, be prepared to pay some mild penalty whenever these resources actually do change; you&#8217;re ceding precise control over when a new version gets served up in order to gain performance (a trade-off you&#8217;ll have to weigh).  Granted, there are cache-busting strategies (such as versioned file names) that you can use to get around this, too.</p>
<p>The other thing that impresses me about Page Speed is that it actually provides you with better versions of things you have, no extra software required!  If it notices you could have a better-compressed image or min-ified JavaScript file, it&#8217;ll tell you how much you could be saving and provide it for you at a single click.  Very slick.</p>
<p>Next I have to figure out if <a href="http://www.dreamhost.com/r.cgi?456958">DreamHost</a> can help me support gzip&#8217;ed content&#8230;</p>
<p><em>Update</em>: Bah!  I should have just poked around a little.  I found a page regarding <a href="http://ikeif.net/2008/10/15/enabling-gzip-compression-dreamhost/">turning on more <code>DEFLATE</code> functionality</a> from DreamHost&#8217;s Apache 2.2 setup.  They already automatically deflate several types, but this doesn&#8217;t include CSS or JavaScript.  It&#8217;s a pretty easy addition to the <code>.haccess</code> file I already have.</p>
<pre class="brush:plain"># gzip more stuff
&lt;IfModule mod_deflate.c&gt;
AddOutputFilterByType DEFLATE text/css application/x-javascript application/javascript
&lt;/IfModule&gt;</pre>
<p>Unlike the way I did the <code>Expires</code> headers above, this particular technique uses the content&#8217;s MIME type when choosing when to apply the <code>DEFLATE</code> output filter.  And just like that, I&#8217;ve got smaller content!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kylev.com/2009/06/08/caching-wordpress-content-to-appease-google-page-speed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A brief Python decorator primer</title>
		<link>http://www.kylev.com/2009/05/28/a-brief-python-decorator-primer/</link>
		<comments>http://www.kylev.com/2009/05/28/a-brief-python-decorator-primer/#comments</comments>
		<pubDate>Fri, 29 May 2009 02:37:34 +0000</pubDate>
		<dc:creator>kylev</dc:creator>
				<category><![CDATA[Geekdom]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.kylev.com/?p=405</guid>
		<description><![CDATA[My last post looked at easing a common database idiom using a decorator. Interestingly, the brief discussion on reddit regarding the post had a number of people remarking that the coverage of decorators was more interesting than the SQL-related bits. Curious, that. It seems I&#8217;m not alone in being occasionally puzzled by the way decorators [...]]]></description>
			<content:encoded><![CDATA[<p>My <a href="/2009/05/22/python-decorators-and-database-idioms/">last post looked at easing a common database idiom using a decorator</a>.  Interestingly, the brief <a href="http://www.reddit.com/r/Python/comments/8np00/python_decorators_and_database_idioms/">discussion on reddit regarding the post</a> had a number of people remarking that the coverage of decorators was more interesting than the SQL-related bits.  Curious, that.</p>
<p>It seems I&#8217;m not alone in being occasionally puzzled by the way decorators work.  It took me a little while to comprehend them.  I&#8217;m still not a huge fan of how they work, but I can see their utility and do use them when appropriate.  Almost without fail I end up heading over to <a href="http://www.python.org/dev/peps/pep-0318/">PEP-318</a> and puzzling over the variations.  The PEP isn&#8217;t terribly helpful since it is dominated by historical discussion rather than examples or instructions.</p>
<p>So let&#8217;s start with the basic no-argument decorator.  It doesn&#8217;t take any declarative arguments when decorating a function; you just type <code>@some_deco</code> without parenthesis when using it.</p>
<pre class="brush:python">def some_deco(f):
    def _inner(*args, **kwargs):
        print "Decorated!"
        return f(*args, **kwargs)

    return _inner

@some_deco
def some_func(a, b):
    return a + b

print some_func(1, 2)</pre>
<p>This will print out:</p>
<blockquote><pre>Decorated!
3</pre>
</blockquote>
</pre>
<p>According to the PEP, if you wrap <code>some_func</code> with <code>@some_deco</code>, it is the equivalent of <code>some_func = some_deco(some_func)</code>.  What it fails to call out is that this happens <em>at load time</em>.  What we're returning from the decorator function is a new function or callable that will be bound to the name <code>some_func</code> when this module is loaded.  Subsequent run-time calls to <code>some_func</code> are actually calling the <code>_inner</code> function we defined on the fly when the decorator was called.  Thanks to Python's scoping rules and closures, we have access to the passed <code>f</code> parameter from the inner function, so we can call it.</p>
<p>Lovely.  Now you have the power to tack on any sort of things you want to around a given function.  Print a log message before or after, spawn a thread, add some exception handling.  Whatever you want.</p>
<p>Things get a little more hairy if we want our decorators themselves to take parameters.  According to the PEP, if was want parameters on the decorator to take parameters it's the equivalent of <code>func = decomaker(argA, argB, ...)(func)</code>.  Again, this happens at load time, so it's worth staring at for a moment.  In plain English, this is saying that decomaker will be called with some arguments, and then the result of <em>that</em> will be called with a function reference.  This is key!  There are actually two invocations happening.  The first will need to return a callable that accepts a function as it's argument.  That will then be called, and the result bound to the name <code>func</code>, so it better be callable as well.  Let's try it.</p>
<pre class="brush:python">def log_wrap(message):
    """Print `message` each time the decorated function is called."""
    def _second(f):
        def _inner(*args, **kwargs):
            print message
            return f(*args, **kwargs) 

        # This is called second, so return a callable that takes arguments
        # like the first example.
        return _inner

    # This is called first, so we want to pass back our inner function that accepts
    # a function as argument
    return _second

@log_wrap("Called it!")
def func(a, b):
    return a + b

print func(1, 2)</pre>
<p>This will output:</p>
<blockquote><pre>Called it!
3</pre>
</blockquote>
<p>Ok, ok, that's not terribly useful, but it illustrates the point (and expands on the first example by being a parameterized version).  It requires that we construct two callable items inside our decorator, and that each will be called in turn during load time.  Let's quick dissect what happens at load time.  When python gets to the declaration of <code>func</code> with the decorator sitting on top of it, it calls the decorator function with its argument (in this case, the string "Called!").  What is returned is a function reference to <code>_second</code>.  Next, that just-returned reference to <code>_second</code> is invoked with a single argument: a function pointer to <code>func</code>, which is what we're actually trying to decorate.  The return value of <code>_second</code> is a reference to <code>_inner</code>, which will be bound to the name <code>func</code>, ready for run-time invocation.</p>
<p>Yeah, I'm a little dizzy, too.  But if you practice this a couple times, it'll start to make sense.  Again, the key to getting this second form working is to recognize that two calls are happening at load time and returning the appropriate callable references at the right time.</p>
<p>Once you have it down, use this new hammer when it serves you, remembering that not every problem is a nail.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kylev.com/2009/05/28/a-brief-python-decorator-primer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python, decorators, and database idioms</title>
		<link>http://www.kylev.com/2009/05/22/python-decorators-and-database-idioms/</link>
		<comments>http://www.kylev.com/2009/05/22/python-decorators-and-database-idioms/#comments</comments>
		<pubDate>Fri, 22 May 2009 20:04:43 +0000</pubDate>
		<dc:creator>kylev</dc:creator>
				<category><![CDATA[Geekdom]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.kylev.com/?p=397</guid>
		<description><![CDATA[Now that I&#8217;m a co-maintainer of the MySQL driver for Python I get to see a lot of confused people pop in on the support forums with some elementary problems. These seem to be mostly young developers who haven&#8217;t quite mastered the &#8220;start transaction, work with the database, commit&#8221; pattern that so many of us [...]]]></description>
			<content:encoded><![CDATA[<p>Now that I&#8217;m a co-maintainer of the <a href="https://sourceforge.net/projects/mysql-python/">MySQL driver for Python</a> I get to see a lot of confused people pop in on the support forums with some elementary problems.  These seem to be mostly young developers who haven&#8217;t quite mastered the &#8220;start transaction, work with the database, commit&#8221; pattern that so many of us have become used to after a few years.</p>
<p>I still find the overhead of doing that sort of thing repeatedly to be tiresome.  It doesn&#8217;t take long for your code to become a mess of try/except blocks, making code reading confusing and arduous.  To avoid this, I&#8217;ve been using a Python decorator to wrap my SQL functions.  It goes a little something like this (simplified form):</p>
<pre class="brush:py">def dbwrap(func):
    """Wrap a function in an idomatic SQL transaction.  The wrapped function
    should take a cursor as its first argument; other arguments will be
    preserved.
    """
    def new_func(conn, *args, **kwargs):
        cursor = conn.cursor()
        try:
            cursor.execute("BEGIN")
            retval = func(cursor, *args, **kwargs)
            cursor.execute("COMMIT")
        except:
            cursor.execute("ROLLBACK")
            raise
        finally:
            cursor.close()

        return retval

    # Tidy up the help()-visible docstrings to be nice
    new_func.__name__ = func.__name__
    new_func.__doc__ = func.__doc__

    return new_func

@dbwrap
def do_something(cursor, val1=1, val2=2):
    """Do that database thing."""
    cursor.execute("SELECT %s, %s", (val1, val2))
    return cursor.fetchall()

class SomeClass(object):
    def __init__(self):
        conn = MySQLdb.connect(db='test')
        self.instance_var = SomeClass.get_stuff(conn)
        print self.instance_var
        conn.close()

    @staticmethod
    @dbwrap
    def get_stuff(cursor):
        """Load something meaningful from the database."""
        cursor.execute("SELECT 'blah'")
        return cursor.fetchall()[0][0]

if '__main__' == __name__:
    conn = MySQLdb.connect(db='test')
    print do_something(conn)
    print do_something(conn, 3, 4)
    print do_something(conn, 5)
    print do_something(conn, val2=6)
    #help(do_something)

    s = SomeClass()
    #help(s)</pre>
<p>Now, there are obviously several additions you could make here.  You could add retry/reconnect logic, be a little more careful when closing the cursor (which can throw exceptions), or even attempt some deadlock recovery.  But I think this simple example shows how you can effectively use decorators to implement a useful DB interaction idiom on both functions and object static methods.</p>
<p>And, damn, if it doesn&#8217;t save a lot of typing.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kylev.com/2009/05/22/python-decorators-and-database-idioms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

