Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1 lines (1 sloc) 168 KB
None{"body-raw": "<p>In part of my ongoing performance work in our CouchDB+Python application I&#8217;ve decided to sit down and profile JSON performance in the different open source libraries available for Python.</p>\n<p>I ran <a href=\"http://gist.github.com/239887\">this test</a> profiling <a href=\"http://docs.python.org/library/json.html\">json</a> (pure Python simplejson) available in Python stdlib, <a href=\"http://code.google.com/p/simplejson/\">simplejson</a> compiled with C speedups, <a href=\"http://pypi.python.org/pypi/python-cjson/\">cjson</a>, and <a href=\"http://code.google.com/p/jsonlib2/\">jsonlib2</a>, with a large JSON document. The test decodes and encodes a large JSON object 100 times. It then runs that test 100 times in each library in succession in order to find the average encode/decode time for each library and minimize other environmental factors that may occur. These numbers were taken on my MacBook Air running Mac OS X 1.6.1 with the default Python 2.6.</p>\n<p>The time represents in milliseconds how long it takes to encode/decode <a href=\"http://gist.github.com/239890\">this JSON object</a> 100 times.</p>\n<p><img src=\"http://www.mikealrogers.com/wp-content/uploads/2009/11/JSONPerf.001.png\" alt=\"JSONPerf\" title=\"JSONPerf\" width=\"614\" height=\"460\" class=\"aligncenter size-full wp-image-696\" /></p>\n<p>I honestly didn&#8217;t expect the stdlib json to be this far behind. </p>\n<p>Among the other C based libraries there isn&#8217;t a clear winner. cjson is the best decoder but the slowest encoder, simplejson compiled with C speedups is the fastest encoder but the slowest decoder while jsonlib2 is somewhere in the middle for both cases.</p>\n<p>Also, annoyingly, cjson doesn&#8217;t implement the same API as the other libraries (dump and load functions are named encode and decode) making it much more difficult for a library to include support for all available libraries. Now rather than just being able to add a user defined json module I&#8217;ll need to add support for user defined parsing and encoding functions to <a href=\"http://github.com/mikeal/couchdb-pythonviews\">couchdb-pythonviews</a>, <a href=\"http://github.com/mikeal/couchquery\">couchquery</a>, and <a href=\"http://github.com/mikeal/couchdb-wsgi\">couchdb-wsgi</a>.</p>", "timestamp": "2009-11-21T00:07:50.000005", "title": "JSON Performance in Python"}None{"body-raw": "<p>We&#8217;re gearing up for some heavy CouchDB usage in a new automation system and it has fallen upon me to do some performance benchmarking.</p>\n<p>The most important thing for us to figure out was whether or not the CentOS virtual machine we&#8217;re currently running CouchDB on is going to be enough even in the short term. Until today we&#8217;ve been running 0.9 and have encountered performance problems. </p>\n<p>Our main bottleneck is, and has always been, view generation and update performance. We tend to have medium to large size documents (jobs are relatively small but results from test runs can be incredibly large). </p>\n<p>View generation of large documents has typically been our biggest issue which we have previously mitigated by refreshing all views after any large write but that isn&#8217;t going to work for the amount of results that we plan on pouring in to the new system.</p>\n<p>Last weekend I wrote a <a href=\"http://github.com/mikeal/couchdb-pythonviews\">Python view server for CouchDB</a>. couchdb-python <a href=\"http://code.google.com/p/couchdb-python/source/browse/trunk/couchdb/view.py\">includes a view server</a> but in the past I&#8217;ve heard complaints about performance (although none recently). In addition, the view server in couchdb-python only supports map and reduce, which is only about 1/5 of the current view server spec which includes handlers for update, show, list, filter, and validate which provide the groundwork for CouchDB as an application platform. As of Sunday my view server passes <a href=\"http://github.com/mikeal/couchdb/blob/master/test/query_server_spec.rb\">all of the current CouchDB spec</a> and initial performance tests showed it faster than the JavaScript view server.</p>\n<p>Below are the performance graphs for CouchDB trunk running on a CentOS virtual machine. I&#8217;m using Python 2.6 with the default stdlib json library. The spidermonkey core is 1.7 (I don&#8217;t know what the status of using 1.8 with CouchDB is but as we&#8217;ll see below, this won&#8217;t improve performance too much for these tests).</p>\n<p>These graphs show view generation time for a given number of documents in a new database. The design doc I used had two views, one does emit(doc['type'],doc), the other emit(doc['_id'], 1). </p>\n<p>The graphs support zooming, mouseover and all kinds of <a href=\"http://code.google.com/p/flot/\">flot</a> goodness <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>\n<p>JavaScript is the yellow line. Python is the Blue line.</p>\n<p>\n\n \n \n \n #placeholder .button {\n position: absolute;\n cursor: pointer;\n }\n .message {\n padding-left: 50px;\n font-size: smaller;\n }\n \n <div id=\"placeholder\"></div>\n <p id=\"message-text\" class=\"message\"></p><div id=\"message\" class=\"message\"></div>\n <p>This is a test of moderately sized documents, what we normally expect the size of a job or build description. Each document is identical and fairly simple with a size of ~1,588 bytes.</p>\n <div id=\"placeholder2\"></div>\n <p id=\"message-text2\" class=\"message\"></p><div id=\"message2\" class=\"message\"></div>\n <p>These documents were incredibly large, they were taken from a full fennec mochitest run. Each document is identical and while large it consists mostly of small sized JSON objects inside a much larger JSON object coming in at ~139,096 bytes.</p>\n &ndash;&ndash;<div id=\"tooltip\"></div>&ndash;&ndash;\n</p>\n<p>I had also intended to chart the reduce performance with a simple sum operation but all the results were sub-second regardless of the amount of documents I threw at it with Python being only a little faster than JavaScript.</p>\n<p>The nearly identical reduce time tells me that the actual code processing time inside the view functions are hardly different which means that the large difference in performance during view generation is most likely due to JSON serialization time. This also explains why larger documents cause an even greater difference in performance between Python and JavaScript.</p>\n<h3>Improving Performance</h3>\n<p>The Python view server is already as optimized as I can imagine for processing time inside the views. Since CouchDB doesn&#8217;t provide a way for the view server to support it&#8217;s own concurrency we&#8217;ve basically hit the wall here on what Python can provide. If we increased the complexity of the view functions I think that Python would start to show better than Spidermonkey 1.7, but 1.8 with traceing enabled would likely bridge that gap, possibly even showing JavaScript faster than Python.</p>\n<p>The big problem is JSON serialization. We can make Python faster by compiling simplejson with C speedups. But using the C based JSON parser in newer versions of Spidermonkey requires some other changes to CouchDB since there are differences in the encoding of <strong>undefined</strong>.</p>\n<p>At the end of the day though, this all looks great. CouchDB trunk (pre-0.11) is going to run fast enough for what we need right now even on a virtual machine and if we start to see view generation bottlenecks on views that aren&#8217;t hit as often and have to update a large number of documents we can just move those views to Python and the performance should be back down to sub-second.</p>", "timestamp": "2009-11-05T02:13:35.000003", "title": "CouchDB View Performance (Python vs JavaScript)"}None{"body-raw": "<p>Last weekend I put together some pretty useful code that converts [CouchDB's external process](http://wiki.apache.org/couchdb/ExternalProcesses) JSON request/responses to a WSGI compliant interface.</p>\n<p>This means you should be able to run any modern Python web framework in an external process <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>\n<p>The simplest example:</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>#!/usr/bin/python</span>\n<span>import</span> couchdb_wsgi\n&nbsp;\n<span>def</span> application<span>&#40;</span>environ, start_response<span>&#41;</span>:\n start_response<span>&#40;</span><span>'200 Ok'</span>, <span>&#91;</span><span>&#40;</span><span>'content-type'</span>, <span>'text/plain'</span><span>&#41;</span><span>&#93;</span><span>&#41;</span>\n <span>return</span> <span>&#91;</span><span>'Hello World'</span><span>&#93;</span>\n&nbsp;\ncouchdb_wsgi.<span>CouchDBWSGIHandler</span><span>&#40;</span>application<span>&#41;</span>.<span>run</span><span>&#40;</span><span>&#41;</span></pre></div></div>\n\n<p>But a far more interesting example is running a django app <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>#!/usr/bin/python</span>\n<span>import</span> <span>os</span>, <span>sys</span>\n<span>import</span> couchdb_wsgi\n&nbsp;\ndjango_project = <span>os</span>.<span>path</span>.<span>join</span><span>&#40;</span><span>os</span>.<span>path</span>.<span>dirname</span><span>&#40;</span>__file__<span>&#41;</span>, <span>'mysite'</span><span>&#41;</span>\n<span>sys</span>.<span>path</span>.<span>append</span><span>&#40;</span>django_project<span>&#41;</span>\n<span>os</span>.<span>environ</span><span>&#91;</span><span>'DJANGO_SETTINGS_MODULE'</span><span>&#93;</span> = <span>'mysite.settings'</span>\n&nbsp;\n<span>import</span> django.<span>core</span>.<span>handlers</span>.<span>wsgi</span>\n&nbsp;\napplication = django.<span>core</span>.<span>handlers</span>.<span>wsgi</span>.<span>WSGIHandler</span><span>&#40;</span><span>&#41;</span>\n&nbsp;\ncouchdb_wsgi.<span>CouchDBWSGIHandler</span><span>&#40;</span>application<span>&#41;</span>.<span>run</span><span>&#40;</span><span>&#41;</span></pre></div></div>\n\n<p>All the code is [up on github](http://github.com/mikeal/couchdb-wsgi) and I&#8217;ve written up some solid [Sphinx docs that are up on gh-pages](http://mikeal.github.com/couchdb-wsgi/). I also pushed an [initial release to PyPI](http://pypi.python.org/pypi/couchdb-wsgi).</p>", "timestamp": "2009-10-29T05:47:56.000003", "title": "Introducing\u2026 couchdb-wsgi"}None{"body-raw": "<p>I have started objecting to the description of a contributor as a &#8220;volunteer&#8221;. </p>\n<p>Volunteers are people who give their time/effort to an institution or group at some cost to them for little benefit in return. They usually do this as a labor of love, and therefor the argument can be made they receive some kind of emotional satisfaction from the exchange but it&#8217;s fundamentally categorized as a one way exchange where the volunteer is **giving** and the institution or group is **taking**.</p>\n<p>Open source contributions are not market transactions. In a market there is a producer and a consumer, the transactions between them are to the benefit of either the producer or the consumer or both. Producer makes something, consumer evaluates the product and decides to give capital to the producer. Volunteer is a term used to describe an actor that is working for the benefit of the producer without reciprocal benefit to themselves to the extent that they benefit the producer.</p>\n<p>Capital is the driving force in a market, it&#8217;s what enables the transactions. Workers are paid for contributions to product so that institutions can enable transactions where consumers are given a product in return for more capital. Capital is certainly a factor in open source, but it&#8217;s auxiliary. Capital may drive one side of the transaction, an actor paid to contribute to a product or consumption of a product used by the consumer to generate capital, but it does not drive each side of the transaction.</p>\n<p>Contributors are not driven by a need to benefit a particular producer and are rarely driven by capital. In fact I can&#8217;t think of a way to describe open source contributions in terms of a market. In open source there is the **product**. The product exists almost as it&#8217;s own entity outside of the producers that created it or the consumers that use it. Because if it&#8217;s transparency and it&#8217;s ease of access and manipulation it cannot be viewed as a unit in a transaction within a market. Instead, all interactions need to be described in **relation to the product**. Contributors, institutions and individuals, that take part in production and those that take part in consumption take part in transactions with the **product**. This is an open source community, a group of actors taking part in transactions with a product.</p>\n<p>The communities that thrive are the ones that remove barriers to these transactions and create tools that enable new transactions for more diverse contributions to the product. The transactions are not one-way, each transaction is two-way, benefiting both the product and the actor.</p>\n<p>Rather than capital, mutual benefit seems to drive open source transactions. The product and the actor benefit from every transaction, with only a small portion of those transactions seeing capital as the benefit. The notion of a volunteer simply doesn&#8217;t exist in this model because there are rarely, if ever, transactions that only benefit a product at a cost to the actor. Actors **must** to be motivated and products are not &#8220;owned&#8221; in the traditional sense of ownership since their production is taken on by a community motivated by mutual benefit which tears down the relationship traditional market producers have with products.</p>\n<p>Tools that are built to enable one sided transactions to a product usually fail because actors aren&#8217;t motivated by transactions that aren&#8217;t mutually beneficial.</p>\n<p>A quick look at Firefox shows a very broad and diverse number of tools that enable mutually beneficial transactions. Although we often think about the new kinds of contributions that additions to Firefox itself will enable like [Personas](http://www.getpersonas.com/) or [Jetpack](https://jetpack.mozillalabs.com/) we also have a variety of tools that enable non-code contributions. Everything from that little button that reports a crash (benefits the product&#8217;s stability and improves your browser experience) to [SUMO](http://support.mozilla.com/en-US/kb/) (users seek resolution to support issues while providing the product with immeasurable usage feedback and bugs) are examples of tools that enable new transactions with the product that are mutually beneficial to the product and the actor.</p>\n<p>One of my favorite things about working at Mozilla is being able to think about new kinds of contributions and how to enable them. There are few products with such a large and diverse ecosystem of users so the opportunities for new contribution is uniquely large so long as we create tools that are mutually beneficial.</p>", "timestamp": "2009-08-05T20:55:32.000002", "title": "Mutual Benefit"}None{"body-raw": "<p>Let&#8217;s say there is this market called &#8220;web content creators&#8221; and we are trying to sell them a product, a font. We want to sell them something that is going help make their web content a little better. </p>\n<p>A really good way to sell them something would be to compare the dollar value of our product to the increased dollar value that will be added to their final product. Damn, their final product is free. Scratch that.</p>\n<p>Since there is some labor and tools cost to creating their product we could compare our superior *professionally* created product to all the other tools they are using. Hrm&#8230;. it turns out all the tools and technologies used to create web content are pretty impressive and at a very low cost if not completely free.</p>\n<p>Alright, let&#8217;s just hope these guys really like fonts. Let&#8217;s research the price of fonts of comparative quality and price our fonts below theirs. Uh oh, it turns out there are a lot of great quality free fonts to choose from already and it&#8217;s increasing every day.</p>\n<p>In this market creating a font once and selling it a number of times does not seem like a smart business model. Maybe an alternative business model is more suited to this market.</p>\n<p>There **are** other business models for individual font creators. The amount of people that **can** use newly created fonts is now increasing exponentially. Surely the creation of new custom fonts will still get some business as long as you&#8217;re willing to give them the font in an open format they can use anywhere.</p>\n<p>Maybe the revenues aren&#8217;t enough to sustain an office and a half a dozen employees but it&#8217;s certainly enough for freelance font creators. I know a few web content creators that would love a one-on-one relationship with a font author and would pay a decent stipend for a custom tailored font.</p>\n<p>Font creators will be fine. Font creation is sure to increase. But maybe the institutions that used to house font creation, &#8220;the foundries&#8221;, don&#8217;t have a sustainable model in this market.</p>", "timestamp": "2009-07-22T00:58:14.000002", "title": "Economics of web fonts"}None{"body-raw": "<p>I&#8217;m about to go on a tear so it&#8217;s worth saying that all of what I&#8217;m writing are my own opinions and in no way whatsoever reflect the opinions or policies of my employer.</p>\n<p>Any new technology can have a side effect of making an entire industry irrelevant. Every time an industry is on the brink they try to plead for their own survival. Their tone and message is predictable, &#8220;you&#8217;ll miss our profession when it&#8217;s gone&#8221;. But of course, the profession never disappears only the institutions that used to enable it which are no longer relevant. These Institutions cannot survive in a new world so they scream to save their business model and claim that their profession is what is at risk.</p>\n<p>I love journalism, and music, and I&#8217;m a total font geek but I just can&#8217;t stand newspapers, record labels, and these god forsaken font [\"foundries\"](http://blog.mozilla.com/rob-sayre/2009/07/19/broken-record/).</p>\n<p>Let me get this straight. Your business model is to create fonts, **once**, and then license them on a per-use basis. I can&#8217;t be the first one to tell you **THAT ISN&#8217;T GONNA FUCKING WORK ANYMORE**.</p>\n<p>@font-face has the side effect of invalidating your whole business model by driving demand for ubiquitous free and open fonts. I&#8217;m sorry. I wish it didn&#8217;t have to be this way. The world is cruel, and you&#8217;re fucked. </p>\n<p>Print publications bought your fonts because they had fairly high production costs already and adding a little on top wasn&#8217;t going to break them. But this is the web, content is ubiquitous and free so the tools to create it have to be ubiquitous and free as well. </p>\n<p>To steal a little from [Clay Shirky](http://www.shirky.com/), your industry is now going to suffer from mass-amatuerization. Font creation will not die with the foundries, there is going to be more font creation than there ever has been in human history, it&#8217;s just going to be open and free. The cost of producing a font is nearly zero. There is labor involved but the tools are ubiquitous and mostly free while distribution is a non-issue. Now that **anyone** can create a font and quality is determined solely by the creators talent, and we can actually **use** open fonts in the web content we create, it is safe to expect an explosion in the creation of fonts.</p>\n<p>There is no technology that can save your business model because it pre-dates the web. The web changed the world you live in and you don&#8217;t get to change it back. If you don&#8217;t believe me you should have a chat with some former stock photographers.</p>", "timestamp": "2009-07-20T21:44:57", "title": "Dead Font Walkin\u2019"}None{"body-raw": "<p>I&#8217;m not lucky enough to get to choose one source control manager and use it exclusively. On a daily basis I use git, svn, and hg. Every week or so I also use bzr. Luckily, I no longer have to touch darcs.</p>\n<p>I haven&#8217;t dug in to the internals of these tools enough to say which one has the superior technical merits although I will say that I&#8217;ve never seen a git conflict resolution interface even across unbelievably hairy merges.</p>\n<p>I write a lot of small libraries and a couple big ones. I care far more about the social effects and contribution workflows a tool provides than any other features. There are different public web applications that try and provide infrastructure for the social effects of DCVS and after months of working with different approaches I have to say that GitHub is the winner by a mile.</p>\n<p>At the end of the day there are two factors that make GitHub such a clear winner. The first is zero friction publishing. The second is the democratizing effect of scraping any notion of a &#8220;central&#8221; repository.</p>\n<p>Nearly a year ago i hit the Google Code project limit and had to call in some favors to get the limit pushed up for my account. I have to push lots of small libraries so having a simple and seamless publishing of repositories has made my life much easier. The fact that I can just push my repository and worry about turning that repo on GitHub into a &#8220;project&#8221; later, instead of the other way around, means that I have no reason **not** to publish every little thing I do.</p>\n<p>The second and more controversial feature of GitHub, and possibly of git itself, is that there is never a clear central repository. There is my repository, and your repository, and every other **person&#8217;s** repository. This throws off FLOSS projects that have always relied on a &#8220;committer&#8221; hierarchy to manage the influx of work in to a project. Nearly every book on community driven open source focuses on the creation of a class of contributors with special write permissions to the repository. There has been a huge discussion on how to translate that process to DCVS and some tools, in particular hg, make it fairly easy to simulate older workflows with a central repository. </p>\n<p>After living with GitHub for a while and seeing the potential for new collaboration I think the answer to translating the &#8220;committer&#8221; model to DCVS is to **not translate it at all**. GitHub makes **everyone** a committer and that enables a new class of contribution that the old model totally excluded.</p>\n<p>Since code can travel seamlessly through different developer&#8217;s repositories each change takes on a life of it&#8217;s own. People who made what they thought were small changes for their own personal use easily share them with other developers and those changes can move around repositories hopefully making it in to an official release. New contributors don&#8217;t have to worry about this giant wall of process behind getting a patch in, they simply write the patch and push it, send pull requests to other relevant contributors and module owners eventually getting those changes pushed up in to the repository that gets packaged and distributed.</p>\n<p>Someone is always going to be responsible for releasing a product, someone owns the keys to the distribution mechanisms, so I find the notion that some amount of authority over the project&#8217;s direction is lost by not centralizing the repository to be exaggerated. Although there is some authority that is lost to the previously defined class of committers the democratization of write permissions encourages a bigger class of lost contribution that is excluded by the laborious process of patches in bugs and the required upstream process to get the work committed. This also means that a number of contributors can live with changesets for an extended period of time before they get packaged in a release which increases confidence in large changesets that many projects reject outright for fear of instability.</p>\n<p>GitHub solves the social problems of open source collaboration by taking a much more anarchist approach to the contribution process and while this is certainly shaking the foundation of traditional contribution models I&#8217;m loving it <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>", "timestamp": "2009-07-20T19:10:56", "title": "GitHub is the winner"}None{"body-raw": "<p>We have a lot of great operating systems out there but they were all created before the web and high performance 3D gaming. To try and move technology forward I am announcing the Duke Nukem Operating System.</p>\n<p>Duke Nukem OS is a lightweight high performance open source operating system. The first release, codename &#8220;Forever&#8221;, is due out in late 2010. A promotional comic book will accompany the release and to insure it is available by the delivery date I plan to hire [Kevin Smith](http://en.wikipedia.org/wiki/Kevin_Smith) and [Alex Ross](http://en.wikipedia.org/wiki/Alex_Ross) to write and illustrate it.</p>\n<p>Although no screenshots, specifications, or source code will be available until release consider this a call to action for the open source community to get involved in the project.</p>\n<p>This new operating system will be built on the Linux kernel but I will be throwing out the bloated window managers Linux is currently known for and building a next generating interface. I&#8217;ll be using XULRunner, the Mozilla runtime used to create Firefox, as the basis for this window manager but the tools to develop applications are exclusively web3.0 &#8220;semantic web&#8221; standards. [RDFa](http://www.w3.org/TR/xhtml-rdfa-primer/), a next generation semantic markup language known for it&#8217;s simplicity and rapid rate of adoption, will be the primary language for building in this next generation operating system.</p>\n<p>More updates in the future.</p>", "timestamp": "2009-07-15T17:55:58.000002", "title": "Duke Nukem OS"}None{"body-raw": "<p>I&#8217;m in London for the next few days and would love to grab a drink with any community members be you Mozilla, CouchDB, Python, Windmill, JavaScript or just plain old coffee, whisky or beer geeks <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>", "timestamp": "2009-07-02T13:55:51.000003", "title": "Up for a Pint?"}None{"body-raw": "<p>I&#8217;m getting all packed up and leaving Sunday for [EuroPython](http://www.europython.eu/) in Birmingham, UK.</p>\n<p>This will be my first time at EuroPython and my first time in Europe!</p>\n<p>I&#8217;ll be giving two talks, one on [Windmill](http://www.getwindmill.com) and one about [CouchDB](http://couchdb.apache.org/) and Python. The Windmill talk will be more or less the talk that I gave at [Open Source Bridge](http://opensourcebridge.org/) last week, which went very well. This is the first time I&#8217;ll be talking about CouchDB, the most exciting new technology on the web. The talk will mostly be about breaking our old data modeling habits that we developed to deal with SQL and what libraries and tools are available for interacting with CouchDB in Python.</p>\n<p>I will also be in London for a few extra days after the conference so anyone interested in a meetup should ping me.</p>", "timestamp": "2009-06-26T23:35:49.000004", "title": "Heading to EuroPython"}None{"body-raw": "<p>I&#8217;ll be leaving tomorrow morning for [Open Source Bridge](http://opensourcebridge.org/) in Portland, Oregon.</p>\n<p>I&#8217;m putting together a new [Windmill talk](http://opensourcebridge.org/sessions/36) that tries to incorporate all the feedback we&#8217;ve received over the last year of speaking which I&#8217;ll be presenting on Thursday.</p>\n<p>Mozilla is also a [sponsoring](http://opensourcebridge.org/sponsors/) the conference and there is going to be some great [Firefox related sprints in the hacker lounge](http://opensourcebridge.org/wiki/Hacker_Lounge). Dietrich is also giving what sounds like an awesome talk on extending Firefox called [Firefox Switchblade](http://opensourcebridge.org/sessions/251).</p>\n<p>Hope to see you all there!</p>\n<p>PS. I&#8217;ll also be at EuroPython and the Community Leadership Summit, more on those later <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>", "timestamp": "2009-06-16T01:07:37.000001", "title": "Conference Season Begins"}None{"body-raw": "<p>I had some fun this weekend with Python, &lt;video&gt;, CouchDB and Brett Gaylor&#8217;s [RiP: A Remix Manifesto](http://www.ripremix.com). In just a few hours I was able to crank out a little [annotations remix](http://ripannotations.pythonesque.org) which allows anyone to add annotations to the film that are displayed as people view it.</p>\n<p>I&#8217;m hosting it on my little mac mini (currently hidden in a data-center) so hopefully it doesn&#8217;t fall over pushing so much video <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>\n<p>I&#8217;ve posted all the code up on [github](http://github.com/mikeal/ripannotations/tree/master). The more I use &lt;video&gt; and CouchDB the more excited I get about the future of web applications. This entire project was done in little chunks of spare time over the weekend and most of that was me messing around with styling. To get the data stored, queried, and displayed took less than 2 hours.</p>\n<p>Hope you all enjoy the annotations remix and if you haven&#8217;t already go and pay what you want for a terrific copy of [RiP: A Remix Manifesto](http://www.ripremix.com). It&#8217;s worth it.</p>", "timestamp": "2009-05-13T23:25:34.000002", "title": "RiP: Annotations Remix"}None{"body-raw": "<p>The Rails community seems to be on the verge of imploding, not necessarily because of a [particular event](http://www.ultrasaurus.com/sarahblog/2009/04/gender-and-sex-at-gogaruco/) but because of the [response by Rails leadership](http://afreshcup.com/2009/04/28/a-painful-decision/) to the event and their lack of meaningful reflection on why this happened.</p>\n<p>This event has been well commented on, so I won&#8217;t go in to all the details, but unsurprisingly the best comments I&#8217;ve read so far have come from women, in particular [Audrey Eschright](http://dyepot-teapot.com/2009/04/25/dear-fellow-rubyists/). It&#8217;s good to see meaningful discussion in that community but I think the proposed solution of increased &#8220;professionalism&#8221; is counterproductive and generating an even more hostile response from [Rails leadership](http://loudthinking.com/posts/39-im-an-r-rated-individual).</p>\n<p>Professionalism doesn&#8217;t have a good history of promoting equality. After segregation &#8220;professional&#8221; was one of many code words for &#8220;white male&#8221; and even after many years when non-white males began entering the work force the idea of professionalism served to strip people of their culture and identity to better fit in to a white male dominated environment. For those of us in open source, and especially those who have left traditional corporations, we identify &#8220;professionalism&#8221; as the way corporations turn people in to plastic dolls in suites that can talk to other plastic dolls from other corporations at trade shows without getting &#8220;off message&#8221;. Luckily, we aren&#8217;t talking about a corporation here, we&#8217;re talking about a community and community isn&#8217;t about professionals it&#8217;s about people.</p>\n<p>I think people see professionalism as a solution to this problem because it provides a way for us to change people&#8217;s conduct that we disagree with without actually changing people or how they think they should conduct themselves in a community. The real problem here is that some **people** think it&#8217;s just fine to engage in public conduct that knowingly excludes people and doesn&#8217;t help include or encourage any new participation. </p>\n<p>When news of this little outburst broke I have to say I wasn&#8217;t surprised that it happened in the Rails community. All tech communities have a low number of female participants, this is something nobody is great at yet, but for some time now Rails has been the worst offender. In the early days Rails was promoted by DHH in what, at the time, sounded like a great strategy: Attack dominant technologies (Java) and piss people off that use them long enough to check out your stuff. This strategy generated huge buzz and lead to one of the fastest adoptions of a new technology I&#8217;ve ever seen and it&#8217;s worth noting that the technology was actually so good that people could go from being a pissed off Java developer to a Rails developer in a relatively short amount of time.</p>\n<p>But the biggest problem with DHH&#8217;s strategy was that it was hostile and it intentionally excluded a large number of people who were invested in the old technology and couldn&#8217;t get over being pissed off at DHH. The first thing DHH will say is &#8220;well, we don&#8217;t want or care about those people&#8221;, and he&#8217;s right, Rails doesn&#8217;t need those people. But when you, as the leader of a project, are hostile and partake in action that **intentionally excludes people**, regardless of who those people are, it creates an environment where others see no need to alter their behavior not to exclude people. </p>\n<p>I&#8217;m really disheartened by [DHH's \"I'm an R rated individual\" post](http://www.loudthinking.com/posts/39-im-an-r-rated-individual), because it&#8217;s not that he&#8217;s wrong, he&#8217;s actually right, he should be able to be an individual in the community he&#8217;s built, but if he doesn&#8217;t intentionally curb some of his behavior he&#8217;s going to encourage exaggerations of the worst parts of his personality by the example he sets. It&#8217;s great that DHH loves Louis C.K and his dick jokes, but that doesn&#8217;t mean he would intentionally start a keynote with them, he knows better, and that&#8217;s what makes the difference and that&#8217;s what is so wrong with Matt&#8217;s talk, he knew before he went up there that this would make a lot of people uncomfortable and discourage participation from women and he did it anyway.</p>\n<p>In order to lead an inclusive community you have to encourage participation and allow everyone to be individuals. If you treat everyone with respect, no matter who they are and no matter what they do, others will conduct themselves the same way. It&#8217;s always easier to respond to hostility with hostility but all you&#8217;re doing is creating an environment where hostility is the norm and it&#8217;s alright to exclude people.</p>\n<p>The kind of communities we want are not impossible, in fact we get closer and closer every day. I&#8217;m lucky enough to be at [#moz09](http://search.twitter.com/search?q=%23moz09) this week, and I&#8217;m looking around at over 200 people from different cultures from around the world none of which seem to be trying to hide who they are or where they came from for some notion of &#8220;professionalism&#8221; and everyone treats each other with respect and every day we gather more participation from a broader set of individuals. We aren&#8217;t perfect, we&#8217;re never where we want to be, but we should be confident we&#8217;re going in the right direction.</p>", "timestamp": "2009-04-29T17:57:02.000002", "title": "Professionals or People"}None{"body-raw": "<p>I&#8217;ve been writing some automated tests for the new &lt;video&gt; work in Firefox 3.5 and it&#8217;s been incredibly fun. I spent some time in the trenches at Real Networks and dealt with accessing embedded video in the browser so I really appreciate how much nicer &lt;video&gt; is than embedded players like Real and Flash.</p>\n<p>People talk a lot about embedded plugins being *&#8221;stuck in a box&#8221;* and while this is partially true I don&#8217;t think it&#8217;s descriptive enough. Embedded players like RealPlayer and Flash open up methods that can be called from javascript, so you do have some ways of interacting with the box, but it&#8217;s limited to somewhat rigid pre-defined interfaces. It&#8217;s also worth noting that using these interfaces just doesn&#8217;t **feel** like web development the way doing regular JavaScript and DOM feels. It&#8217;s not dynamic and you&#8217;re limited to only doing **what the plugin authors have already thought of**. The beautiful thing about the browser as a platform is that it enables usage far beyond what the original creators have intended.</p>\n<p>Using &lt;video&gt; **feels** like the web. You resize it by setting size attributes the same way you would an interface node. You seek by setting the currentTime attribute, you can listen for the time changes to create your own interface by adding a listener for &#8220;timeupdate&#8221; events. You can write interfaces around &lt;video&gt; without switching contexts because it&#8217;s not a foreign technology jammed in to the browser. Here is some javascript that implements a few video controls.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"javascript\"><span>var</span> v <span>=</span> document.<span>getElementById</span><span>&#40;</span><span>&quot;v1&quot;</span><span>&#41;</span><span>;</span>\ndocument.<span>getElementById</span><span>&#40;</span><span>&quot;playDiv&quot;</span><span>&#41;</span>.<span>onclick</span> <span>=</span> <span>function</span><span>&#40;</span>e<span>&#41;</span> <span>&#123;</span>v.<span>play</span><span>&#40;</span><span>&#41;</span><span>&#125;</span>\ndocument.<span>getElementById</span><span>&#40;</span><span>&quot;pauseDiv&quot;</span><span>&#41;</span>.<span>onclick</span> <span>=</span> <span>function</span><span>&#40;</span>e<span>&#41;</span> <span>&#123;</span>v.<span>pause</span><span>&#40;</span><span>&#41;</span><span>&#125;</span>\ndocument.<span>getElementById</span><span>&#40;</span><span>&quot;reloadDiv&quot;</span><span>&#41;</span>.<span>onclick</span> <span>=</span> <span>function</span><span>&#40;</span>e<span>&#41;</span> <span>&#123;</span>v.<span>load</span><span>&#40;</span><span>&#41;</span><span>&#125;</span>\ndocument.<span>getElementById</span><span>&#40;</span><span>&quot;seekDiv&quot;</span><span>&#41;</span>.<span>onclick</span> <span>=</span> <span>function</span><span>&#40;</span>e<span>&#41;</span> <span>&#123;</span>\n v.<span>currentTime</span> <span>=</span> document.<span>getElementById</span><span>&#40;</span><span>'seekField'</span><span>&#41;</span>.<span>value</span><span>;</span>\n <span>&#125;</span></pre></div></div>\n\n<p>Isn&#8217;t that beautiful! Maybe I&#8217;m overly excited because I&#8217;ve had to deal with this using older technologies but this just **feels** good, and if it feels good then I know people are going to get excited about it and build cool stuff.</p>", "timestamp": "2009-04-28T18:29:59.000001", "title": "<video> just feels good"}None{"body-raw": "<p>I&#8217;ve started stewing over [Garrett Murray](http://log.maniacalrage.net/)&#8217;s post on [negative user reviews for his Ego application](http://log.maniacalrage.net/post/98510137/a-little-over-a-week-and-a-half-ago-google) for iPhone that recently showed some breakage when Google Analytics changed up. What started to really upset me was one of his closing paragraphs.</p>\n<blockquote><p>\nThis kind of thing continually reinforces something I\u2019ve thought about a lot since the App store was released, which sounds horrible to say but it might be true: Apple is creating an ecosystem of the kind of customers I don\u2019t want. With the ridiculous approval process leaving bugfixes to take over a week to show up, with prices being driven down to nothing by farting apps\u2026 it just feels hostile to me. While I have plenty of great customers who have been raving about the app, all it takes is one little issue and it all comes crashing down.\n</p>\n</blockquote>\n<p>It&#8217;s no longer acceptable for consumer applications to &#8220;blame the user&#8221;. Sure, many people still do it, but if a blog post like this just blamed individual users for their complaints without this closing paragraph it wouldn&#8217;t be gaining so much steam and I probably never would have read about it. Instead Garrett blames the *community* of users, and by extension Apple for process that encourages this kind of community.</p>\n<p>The first rule of community leadership in open source is simple; **&#8221;Don&#8217;t be an asshole.&#8221;**. While simple, sometimes it&#8217;s the hardest rule to follow. Many people in the community can be difficult, some of them downright hostile, but you can&#8217;t be hostile back and you can&#8217;t be an asshole. When you&#8217;re hostile or an asshole in your community you give license to the community to do the same. You cultivate the behavior that antagonized you in the first place. This is the rule when trying to lead contributors and I have to assume it&#8217;s the rule when trying to lead users and posts like this violate the rule by blaming users for their own expectations and then dismissing them altogether.</p>\n<p>He tries to deflect attention to Apple since they are the gate keeper. Dismissing the bulk of your user community due to the gate keeper is logic that is so convenient you know it has to be flawed. The truth is **most** platforms have some kind of gate keeper, this is the world that we live in, but your complaints about your users have nothing to do with Apple.</p>\n<p>iFart is 1 dollar but you&#8217;re giving it way too much credit if you think that&#8217;s why iPhone users have lower price expectations. You know what else is 1 dollar, Ocarina. Applications and games like Ocarina are larger triumphs of creativity than they are of engineering time. Not to say they are easy, or simple, but they are priced cheaply because the creators are confident in their product and because they didn&#8217;t spend a year developing it. This is where iPhone users have cultivated their expectations about interface, graceful failure, and low prices, because of your competitors not because of the gate keeper.</p>\n<p>But even if all the user community&#8217;s expectations and demeanor is Apple&#8217;s fault, even if your users are cheap and vicious and given way too big a soap box, it&#8217;s still your fault. </p>\n<p>As an example. Firefox get&#8217;s requests for features from Windows users to make certain things be &#8220;more like Windows&#8221;. If you look at the Firefox interface over 3 operating systems you&#8217;ll notice that the preferences menu item moves around based on which platform it&#8217;s on. The truth is, if you designed an interface from the ground up in some ideal world there would be one place that is best to put the preferences item, but that&#8217;s not the world we live in, we live in a world of expectations from user communities. The easiest thing to do is to say &#8220;we don&#8217;t need those users&#8221; or &#8220;those users are stupid and don&#8217;t understand proper design&#8221; but it&#8217;s not the **right** thing to do because it&#8217;s not what **they** want.</p>\n<p>What your users are really saying with those complaints is that this failure frustrated them to the point of opening up iTunes and writing a complaint, not just that something broke. You could have failed more gracefully, you could have presented them with a button that opened a support web page with more detailed information and assurances that it was being resolved. Then after some time the bad reviews would get swallowed up by the positive ones you mentioned. But now you don&#8217;t have to do anything because you&#8217;ve convinced yourself that you did nothing wrong and it&#8217;s just a bunch of users you don&#8217;t want complaining about something they are too dumb to understand.</p>\n<p>I hope some day Garrett finds his perfect user community with expectations that match his own. I&#8217;ll stick to working on products for everyone else, listen to their feedback seriously and try to improve them.</p>", "timestamp": "2009-04-23T20:10:28.000003", "title": "Can\u2019t blame the user? Blame the user community!"}None{"body-raw": "<p>So much good stuff landed in Windmill over the last few weeks that we decided to push another major release.</p>\n<p>The biggest new features are:</p>\n<p>* [django management command](http://trac.getwindmill.com/wiki/WindmillAndDjango) for running windmill tests ([Jacob](http://jacobian.org/) said the existing django support wasn&#8217;t good enough and I agreed so I wrote this during the PyCon Sprints)<br />\n* new [nose plugin](http://trac.getwindmill.com/wiki/BookChapter-5-RunningTests#RunningTestsfromNose)<br />\n* cygwin support contributed by [Simon Law](http://sfllaw.livejournal.com/) (he went and wrote an implemenation of [winreg for cygwin](http://pypi.python.org/pypi/cygwinreg) to get this to work).</p>\n<p>There were also some really good bug fixes that landed:</p>\n<p>* much better unicode handling and serialization (adam)<br />\n* fix for POST to foreign domains ([Anthony Lenton](http://anthony.lenton.com.ar))<br />\n* continued improvements to click simulation (adam)</p>\n<p>The release is [up on PyPI](http://cheeseshop.python.org/pypi/windmill) and you can install/update with:</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"shell\">$ easy_install -U windmill</pre></div></div>\n\n<p>For anyone interesting in working **on** windmill we&#8217;re having a Sprint in #windmill on irc.freenode.net tomorrow April 8th, 2008 for pretty much all day. We&#8217;re going to be improving the unittests for Windmill itself.</p>\n<p>The next planned major release will be 1.2 which will include the much anticipated SSL support, courtesy of some great work being done by Anthony.</p>", "timestamp": "2009-04-08T01:34:09.000002", "title": "Windmill 1.1 (the PyCon release)"}None{"body-raw": "<p>The video from [PyCon of the Functional Test Tools Panel](http://pycon.blip.tv/file/1947342/) has been making the rounds and one comment in particular that seems to be gaining some traction is a comment [Jason Huggins](http://twitter.com/jhuggins) made about test recorders being &#8220;evil&#8221;. I didn&#8217;t comment about it while I was on the panel because I have mixed experiences with recorders in the tools I work on and some of those experiences have left me feeling the same way.</p>\n<p>I agree with Jason that recorders that generate code with the expectation that you will be able to **just run** that code as a test are definitely *evil*. Aside from just **not working** most of the time they create false expectations about test tools. But, I disagree that they can&#8217;t be implemented in a way that is useful and side steps a lot of those false expectations. **Note: On twitter Jason has added that he agrees with my disagreement probably for the same reasons I&#8217;ll highlight below.**</p>\n<p>Looking at two tools I&#8217;m still an active developer on, [Windmill](http://www.getwindmill.com) and [mozmill](http://code.google.com/p/mozmill), both have a recorder but one I find highly successful and the other I&#8217;ve struggled greatly with.</p>\n<p><img src=\"http://www.mikealrogers.com/wp-content/uploads/2009/04/picture-3-263x300.png\" alt=\"picture-3\" title=\"picture-3\" width=\"263\" height=\"300\" class=\"alignleft size-medium wp-image-533\" /></p>\n<p>The recorder in the Windmill IDE is phenomenal and almost entirely due to the work that [Adam](http://www.adamchristian.com/) has put in to it. The entire test authoring UI in Windmill is *action* based meaning there is a series of interface simulations you can do with a single variable (an element lookup or in some cases a string to eval). Each action is a cell that can be moved around and new actions added above or below. The same UI is leveraged for running and debugging tests, each cell shows green or red if a test has passed or failed.</p>\n<p>The reason I like this UI and similarly simple UI&#8217;s like [FireUnit's UI](http://www.mikealrogers.com/archives/327) is that they leverage the relative simplicity of the test APIs. There is no code in the Windmill IDE, just actions, so when you record a set of actions they don&#8217;t show you code just the actions **as you interact with the page**. </p>\n<p>Now look at the mozmill UI. Mozmill suffers from some additional necessary complexity. In mozmill we have to test multiple windows, which requires a more complex API and some required setup steps. Mozmill can&#8217;t have the same action&#8221; based UI because we have two additional variables to every UI interaction, the window (which usually requires an additional API to pull out) and the document (also requiring an additional API for easy access). Removing the complexity of the API from the UI would only cause more confusion so Mozmill just has a code editor (all tests in mozmill are in javascript, there is no other supported language).</p>\n<p><img src=\"http://www.mikealrogers.com/wp-content/uploads/2009/04/picture-4.png\" alt=\"picture-4\" title=\"picture-4\" width=\"900\" height=\"400\" class=\"alignleft size-full wp-image-538\" /></p>\n<p>I have to admit, I was pretty shocked by the kinds of feature requests we got after we implemented a recorder in mozmill. Windmill has a few orders of magnitude more users than mozmill and we got far more feature requests that bordered on *&#8221;magic&#8221;* in mozmill. Not mention that during the initial usage we got a complaint or bug report almost every time a recorded test didn&#8217;t play back and pass without any additional work. It wasn&#8217;t until today that I started to understand why we saw such a big difference in expectations.</p>\n<p>One problem is that when you take a bunch of opaque background recorder magic and then just serialize it all to code it creates a context switch for the user. They didn&#8217;t watch the actions come in as they were being recorded so they have no idea where they came from and they stop and look at the code. Instead of a series of small steps, each interaction with the page creating a line of code, the user thinks of this as two steps; do stuff, test is written. This makes a lot of users disjointed from the editing process.</p>\n<p>Another problem with generating code is that it&#8217;s expected to be valid. If a failure occurs the only thing to do is to show the exception information. The exception information highlights the line that has failed. Generated code is always hairy and difficult to understand so you just stare at it and are at loss as to how you should fix it. But the code isn&#8217;t where to look to fix this problem, the **page** is where you look to figure out what went wrong. The fact that you&#8217;ve gone from the exception information back to the code makes it less likely for you to move your attention **again** back to the page. This is where placement is a key factor as well and, if you can, you should also try to place the product side by side with the test interface.</p>\n<p><img src=\"http://www.mikealrogers.com/wp-content/uploads/2009/04/picture-6.png\" alt=\"picture-6\" title=\"picture-6\" width=\"457\" height=\"241\" class=\"aligncenter size-full wp-image-547\" /></p>\n<p>With Windmill there is an entirely different workflow than mozmill. You record actions and they pop up in the IDE as you create them. Since the actions are created as you interact with the page it&#8217;s more transparent as to where they came from. Then you just play back the actions and as they run the editable tabs go red or green. This keeps the focus failure on the action without moving attention from code to exceptions and and allows you to watch the page as the passes and failures occur. Once a failure occurs it&#8217;s a little more likely now that you&#8217;ll see the cell go red before some ajax request finished rendering the piece of UI you tried to click on. Then, hopefully, you will intuitively add an action above the click that waits for the element to get rendered.</p>\n<p>The mile high view of both recorders doesn&#8217;t make them seem much different. You *can* do the same set of tasks with each, but a series of small differences reduces the chances that you&#8217;ll fall off the intended pattern of use, which is to record a set of actions and use it as an outline to create fully working test. Those small differences also create entirely different expectations from your users. </p>\n<p>The funny thing is, Adam and I have never thought about it this way. All we ever tried to do was keep things simple and keep the test creation, editing, running and debugging workflows integrated and this is just a happy side effect <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>", "timestamp": "2009-04-05T22:36:05.000006", "title": "On Test Recorders"}None{"body-raw": "<p>Just in time for PyCon we&#8217;re releasing [Windmill 1.0](http://www.getwindmill.com/archives/412). It&#8217;s been almost 3 years of development and I&#8217;m both excited and relieved to have something we&#8217;re comfortable calling 1.0.</p>\n<p>The latest RCs have seen bigger improvements than we thought would make it. A new wave of contributions has given us some great new features in Django support and test serialization and [Adam](http://www.adamchristian.com) has done some great UI work as well.</p>\n<p>Big thanks to everyone who contributed to the release and I hope to see many of you at PyCon. Adam is doing a [talk on windmill](http://us.pycon.org/2009/conference/schedule/event/9/) which I&#8217;ll be helping out with and Adam and I will also be on a [functional testing tools panel](http://us.pycon.org/2009/conference/schedule/event/88/) which should be a lot of fun. And if you&#8217;re staying around for the sprint days of the conference we&#8217;ll be leading a [windmill sprint](http://us.pycon.org/2009/sprints/projects/windmill/).</p>", "timestamp": "2009-03-26T04:36:11.000003", "title": "Windmill 1.0!"}None{"body-raw": "<p>First of all, NO, I didn&#8217;t write another web application framework for Python. </p>\n<p>[webenv](http://github.com/mikeal/webenv/tree/master) is a small abstraction on top of WSGI providing simple request, response and application abstractions. It was developed as part of windmill2 where I decided to make a bunch of the common operations I was dealing with all the time using raw WSGI and make them simpler. I also wanted to use **@property** for most of the request helpers so that they would be lazy loaded and only take a performance hit when you needed them, initially as part of the performance goals for windmill2.</p>\n<p>I know that [paste](http://pythonpaste.org) has a lot of this already but that seemed like a bit too much for what we needed.</p>\n<p>I also need to write fast and simple REST applications with the least amount of boilerplate so there is a *RestApplication* class that helps with that.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>class</span> MyApplication<span>&#40;</span>RestApplication<span>&#41;</span>:\n <span>def</span> GET<span>&#40;</span><span>self</span>, request, section=<span>None</span>, <span>user</span>=<span>None</span><span>&#41;</span>:\n <span>if</span> section <span>is</span> <span>None</span>:\n <span>return</span> FileResponse<span>&#40;</span><span>&quot;index.html&quot;</span><span>&#41;</span>\n <span>if</span> section == <span>&quot;info&quot;</span>:\n <span>if</span> <span>user</span> <span>is</span> <span>None</span>:\n <span>return</span> HtmlResponse<span>&#40;</span>get_all_users_page<span>&#40;</span><span>&#41;</span><span>&#41;</span>\n <span>else</span>:\n <span>return</span> HtmlResponse<span>&#40;</span>get_user_page<span>&#40;</span>username=<span>user</span><span>&#41;</span><span>&#41;</span>\n <span># More code for handling other requests.</span>\n&nbsp;\napplication = MyApplication<span>&#40;</span><span>&#41;</span>\napplication.<span>add_namespace</span><span>&#40;</span><span>&quot;css&quot;</span>, FileServerApplication<span>&#40;</span><span>&quot;/var/www/mysite/css&quot;</span><span>&#41;</span><span>&#41;</span>\napplication.<span>add_namespace</span><span>&#40;</span><span>&quot;images&quot;</span>, FileServerApplication<span>&#40;</span><span>&quot;/var/www/mysite/images&quot;</span><span>&#41;</span><span>&#41;</span></pre></div></div>\n\n<p>I didn&#8217;t think I would need to release it before windmill2 but I&#8217;ve found it so nice that some of the other projects I&#8217;ve been working on already depend on it. I only took a few hours to clean it up and document it with pretty [Sphinx docs](http://webenv.pythonesque.org).</p>\n<pre lang=\"bash\">\n$ easy_install webenv\n</pre>", "timestamp": "2009-03-24T22:19:00.000001", "title": "Introducing\u2026 webenv"}None{"body-raw": "<p>You don&#8217;t have to be a geek to suffer from information overload these days. Average users are hammered with too much data from too many sources and are seeking new ways to automate some of their manual workflows and creating their own contextual filters to help then deal with an overwhelming flood of information.</p>\n<p>Feeds are an obvious and helpful tool in helping *normal* people automate the tasks of keeping up with information streams. Many users are finding ways to use feeds to **follow** a particular site or person and using new tools and services that work better for them than the traditional big RSS Readers. Personally, I think Firefox3 has the best workflows for integrating with any of these tools. Let&#8217;s work through the subscribe workflow for my blog.</p>\n<p><img src=\"http://www.mikealrogers.com/wp-content/uploads/2009/03/picture-11.png\" alt=\"picture-11\" title=\"Feed Button Close In\" width=\"198\" height=\"145\" class=\"aligncenter size-full wp-image-492\" /></p>\n<p>* Click on the feed button.</p>\n<p><img src=\"http://www.mikealrogers.com/wp-content/uploads/2009/03/picture-2.png\" alt=\"Subscribe Page\" title=\"Subscribe Page\" width=\"461\" height=\"245\" class=\"aligncenter size-full wp-image-493\" /></p>\n<p>* Select or configure your client and click subscribe.</p>\n<p>This is a very simple workflow and it makes web based tools first class citizens where previous versions of Firefox and other browsers only support desktop client subscriptions. You don&#8217;t need to make a lot of decisions or know anything about the feed technology or protocols behind the scenes.</p>\n<p>But the workflow for my blog is an ideal scenario where only one rel=&#8221;alternate&#8221; feed has been parsed from the page. This workflow becomes more complicated when multiple rel=&#8221;alternate&#8221; links are in the page.</p>\n<p><img src=\"http://www.mikealrogers.com/wp-content/uploads/2009/03/picture-3.png\" alt=\"picture-3\" title=\"picture-3\" width=\"428\" height=\"149\" class=\"aligncenter size-full wp-image-494\" /></p>\n<p>Is this really necessary? 90% of the people who click this want to follow new posts and nothing else. More importantly what feed would **you** like people to subscribe to? You can make a decision here to push people in the direction you would like and somewhere else on the page you can offer them these more complicated options if they are seeking out alternate subscriptions.</p>\n<p><img src=\"http://www.mikealrogers.com/wp-content/uploads/2009/03/picture-4.png\" alt=\"picture-4\" title=\"picture-4\" width=\"294\" height=\"103\" class=\"aligncenter size-full wp-image-495\" /></p>\n<p>This is terrible. You&#8217;re basically undercutting all the work browser vendors have done to let users start to integrate feeds in to their workflows without understanding feed protocols.</p>\n<p>If we want to encourage adoption of these technologies we have to help eliminate this kind of extra confusion from basic user workflows. Feeds aren&#8217;t just being used in traditionally feed readers now, those readers de-contextualize the information so that power users can burn through information quicker. New tools are enabling users to use feeds to &#8220;follow&#8221; a site, they way they might follow someone on twitter. These unnecessary subscription options discourage that kind of adoption because it presents choices that fall outside of the bounds of that workflow.</p>", "timestamp": "2009-03-12T19:00:47.000003", "title": "Multiple feed rels are a bad idea"}None{"body-raw": "<p>We are now, at this very moment, witnessing the mass failure of traditional institutions. This isn&#8217;t unique in history, many societies and cultures have evolved to make the primary institutions of society irrelevant. This particular moment is probably only unique in the sheer number of institutions that seem to be failing all at once.</p>\n<p>First the music industry, then newspapers, and now film and television all seem to be following the same pattern. They continue to produce the same quality and, in most cases, quantity of a familiar product which each in their own way help define and shape the majority of modern culture. But what was highly successful yesterday is today a failing business. This is not because of changes in their products but changes in the world around them. The social contract by which these institutions had flourished has changed, and only those able to change their institutions to fit the new social contract will continue to thrive in the new world.</p>\n<p>One institution that seems to be relatively untouched in the new world is higher education. The free flow of information has changed so dramatically in such a short time it&#8217;s interesting that relatively small institutional changes have allowed higher education to maintain the same place and importance in society. Higher education is prohibitively expensive for the vast majority of citizens, and it&#8217;s mired with barriers to entry that make it unattainable for many. These are the same kinds of barriers that destroyed the music and newspaper businesses when they were forced to compete with much lower barriers to entry and relatively free alternatives.</p>\n<p>Objectively, there is nothing you can learn in higher education that you cannot learn on your own given enough motivation and access to information with the exception of some advanced scientific fields that require access to incredibly expensive equipment. So what is it that continues to proliferate higher education over individual initiative? </p>\n<p>We can argue that the quality and prestige of professional educators is what continues to help institutions thrive, but we would have to ignore the reality of the newspaper industry which is failing under competition not from a new professional class but from mass amateurization. I have tried for a long time to find something that institutions of higher education are doing that separates them from any other institution or class of professionals that would account for their relative success today and found nothing. This makes me re-examine the social contract under which they operate and question whether it has really changed as much as I thought.</p>\n<p>In the last 20 years, as information has become more accessible and the possibility for self education has increased, most fields have actually **increased** their formal education requirements. This means that at the same time higher education has become more expensive and more barriers have been placed to acceptance, the relative **importance** of a certification that states nothing more than the holder has completed no less than 4 years in a formal institution of education and spent tens, sometimes hundreds, of thousands of dollars has increased. A college certification does not relate directly to the competency of the applicant in any way when compared to another applicant with related experience.</p>\n<p>Higher education is aware of it&#8217;s relative inadequacy at vocational training compared to real world experience. The best schools all stress the importance of internships. The best computer science schools all **require** a certain amount of internship experience in order to complete their degree, mixing formal education along with real world experience. With this in mind, I don&#8217;t mean to say that a degree from a good school is not an indicator of competency, to do so I would have to ignore the high caliber of interns we enjoy at Mozilla. What I do mean to say is that formal education as a **requirement** of employment is to say that such a degree is of greater importance than comparative experience, which I have to disagree with.</p>\n<p>Think about it this way; would you hire a candidate with a degree from a prestigious college over a candidate with experience in a prestigious open source project?</p>\n<p>In open source we&#8217;re able to see the entirety of relevant experience if an applicant has previous experience in open source. We can see email conversations, IRC logs, and commits. We can evaluate an applicants communication skills as well as their practical programming experience. The rest of the computer industry has to hunt down references and go through very lengthy interviews in order to get a much smaller understanding of an applicant and it&#8217;s no surprise that they tend to rely much more often on formal education experience in selecting applicants. But looking towards the future, as more work becomes collaborative, more work becomes public, and the barriers to taking on previously professionalized tasks are removed, is it unreasonable to expect other fields to start to have the same advantages we have in open source?</p>\n<p>If more people are able to learn whatever they want, make public their works, and improve over time through peer reviews in larger communities, employers will begin to rely more on relevant public work as an indicator of professional competency instead of formal degrees. In fact, it&#8217;s reasonable to expect higher education institutions to start to adapt to this **before** employers do, insuring that graduating students have a collection of impressive public works to make them look competitive compared to graduates of other competing schools. As this part of the social contract changes is it reasonable to expect higher education to being to suffer from the same challenges as the music, news, film and television industries?</p>", "timestamp": "2009-03-11T20:40:27.000002", "title": "Education as an Institution"}None{"body-raw": "<p>Today we finished up a much anticipated MozMill 1.1 release.</p>\n<p>The UI has been totally re-worked by <a href=\"http://www.adamchristian.com\">Adam</a> based mainly of design session feedback. We ditched the old xul UI and are just using html loaded via chrome url, this made development an order of magnitude easier and allowed us to use a great syntax highlighting library for the editor that we could never quite get working in xul. </p>\n<p>The release also has lots of new features like automatically binding the mozmill window to the side of a test window and editing of multiple tests at once. A whole slew of bugfixes made it in, mostly logged by <a href=\"http://www.hskupin.info/\">Henrik</a>, including fixes to mulit-window recording. </p>\n<p>At the suggestion of <a href=\"http://weblogs.mozillazine.org/dmose/\">Dan Mosedale</a> we also added new asynchronous test support for more unittesting capabilities. Documentation is still on it&#8217;s way but you can refer to the <a href=\"http://code.google.com/p/mozmill/source/browse/trunk/test/test_unit.js\">mozmill unittest</a> for now.</p>\n<p>MozMill can be downloaded a few ways, the extension is available on <a href=\"http://mozmill.googlecode.com/files/mozmill-1.1.xpi\">google code downloads</a> or the Python package can be installed via <a href=\"http://pypi.python.org/pypi/mozmill\">PyPI</a></p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"shell\">$ easy_install -U mozmill</pre></div></div>\n\n<p><a href=\"http://cmtalbert.wordpress.com/\">Clint</a> also just finished up a big round of new <a href=\"http://quality.mozilla.org/mozmill-docs\">end user docs and API documentation cleanup and reformatting on QMO.</a></p>", "timestamp": "2009-03-05T23:51:50.000003", "title": "MozMill 1.1 Released"}None{"body-raw": "<p>I finally started using [Sphinx](http://sphinx.pocoo.org/) for documenting a few of the libraries I&#8217;m working on. Using reStructured text can be a real pain but once you bite the bullet you get docs that look amazing and match the style of all the [new Python docs](http://docs.python.org/).</p>\n<p>If you&#8217;re using svn you can just set mime-type properties on files and most svn hosts will serve the raw files out as that mime-type. This means that you can just checkin the built html docs and serve them up google code and the like without a whole lot of extra effort the way [simplejson has](http://simplejson.googlecode.com/svn/tags/simplejson-2.0.9/docs/index.html).</p>\n<p>After lots of googling I&#8217;ve failed to find any way to get [github](http://github.com) to do something similiar. git doesn&#8217;t support any kind of per file metadata and I can&#8217;t find any other way to get it to serve the static content properly on github. All out of options, I decided to just clone the repo to my server and add a cron job to pull down and merge changes every 5 minutes from the public github repo. Then I just serve up the static content on apache, you can see the end result at [http://windmill2.pythonesque.org](http://windmill2.pythonesque.org). </p>\n<p>I haven&#8217;t done much with this domain yet and hosting other open source Sphinx docs wouldn&#8217;t be difficult at all. If anyone needs some hosting just comment or email me with checkout instructions and the subdomain you want and add it to my server.</p>", "timestamp": "2009-03-01T20:29:32.000006", "title": "Need Sphinx Hosting?"}None{"body-raw": "<p>I know that a lot of my fellow Python developers like a nice whisky. But I wonder if any are big enough whisky geeks to know that on one of the last PyCon 2009 nights, <a href=\"http://www.maltadvocate.com/docs/whiskyfest/chicago/default.aspx\">WhiskyFest will be happening in Chicago</a>.</p>\n<p>Not only will those of us who decide to attend the sprints happen to be in Chicago on the night of WhiskyFest, it&#8217;s in the <a href=\"http://www.maltadvocate.com/docs/whiskyfest/chicago/faq.aspx#whereiswhiskyfest\">SAME HOTEL AS PYCON</a>!</p>\n<p>There is really no reason for all of you attending the sprints not to pick up a ticket and enjoy some great whisky with me for a few hours on the night of April 1st <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>\n<p>Having attended WhiskyFest San Francisco previously I can tell you that the <a href=\"http://www.maltadvocate.com/docs/whiskyfest/chicago/whisky_list.aspx\">official list of whiskys</a> is only a portion of all the delicious whisky available to try. It&#8217;s more than worth the ticket price, I guarantee it. And it&#8217;s happening from 6:30 to 9:30 which means it is happening in between code time and bar meetup time.</p>", "timestamp": "2009-02-21T18:17:24.000005", "title": "WhiskyFest Chicago"}None{"body-raw": "<p><img class=\"size-full wp-image-434 alignright\" title=\"pushmarks\" src=\"http://www.mikealrogers.com/wp-content/uploads/2009/02/pushmarks.png\" alt=\"pushmarks\" width=\"76\" height=\"72\" /></p>\n<p>I used to be really in to public bookmark services like delicious and magnolia. Then Firefox3 was released and the new bookmarks UI combined with the awesomebar was just much easier to use than any of the sharing extensions.</p>\n<p>I never took the time to sit down and write a simple sync/push extension because I\u00a0just figured that someone else would do it <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>\n<p>It&#8217;s been a year now, it&#8217;s time for PushMarks.\u00a0<a href=\"https://addons.mozilla.org/en-US/firefox/addon/10806/\">https://addons.mozilla.org/en-US/firefox/addon/10806/</a></p>\n<p>PushMarks is a simple firefox extension that pushes new bookmarks to your delicious account (more services coming). You can also initiate a &#8220;sync&#8221; which will go through all your local bookmarks and push them to delicious and also make sure any bookmarks you have on delicious are in your local bookmarks.</p>\n<p>If you do a big sync, please be patient. It takes a while for all the bookmarks to get up to delicious because I have to throttle the connections for fear of being locked out of the delicious API.</p>\n<p>Of course it&#8217;s all open source and up on github\u00a0<a href=\"http://github.com/mikeal/pushmarks/tree/master\">http://github.com/mikeal/pushmarks/tree/master</a> .</p>", "timestamp": "2009-02-19T06:31:42.000003", "title": "Introducing\u2026 PushMarks"}None{"body-raw": "<p><a href=\"http://www.amazon.com/gp/product/B001ACXHXE?ie=UTF8&tag=tracmostrecec-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=B001ACXHXE\"><img class=\"alignright size-full wp-image-421\" title=\"EyeFi Explore\" src=\"http://www.mikealrogers.com/wp-content/uploads/2009/02/card-explore-reflect.gif\" alt=\"EyeFi Explore\" width=\"86\" height=\"133\" /></a>A little while ago I bought a new camera. Unlike my previous still cameras this one was more of a portable point and shoot, which I&#8217;ll review in a later post.</p>\n<p>When I was shopping around for an SD card I stumbled upon the offerings from EyeFi. EyeFi makes SD cards that have built in wireless and EyeFi provides a web service that the card will upload the photos to and then send to your home computer and to your favorite photo sharing site (picasa, flickr, facebook, etc.).</p>\n<p>The newest offering, the <a href=\"http://www.amazon.com/gp/product/B001ACXHXE?ie=UTF8&tag=tracmostrecec-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=B001ACXHXE\">Explore</a>, is even more amazing. This card does automatic geotagging of all the pictures you take. The card doesn&#8217;t have a GPS in it, all it does is take the signal strength information of all the wireless networks it can find at the time you take a picture. This information is uploaded to their webservice when the photo gets pushed and that information is used to triangulate a fairly accurate geotag.</p>\n<p>I was skeptical of the card at first, it just seemed like it was doing too much in such a small package and it had to break somewhere. It doesn&#8217;t. It&#8217;s amazing.</p>\n<p>This card fully automates all the manual tasks that used to come with taking pictures. It automates the geotagging, and it automatically pushes all of my photos public to picasa. And as if that wasn&#8217;t enough, it also dumps all my photos to my <a href=\"http://www.amazon.com/gp/product/B001CZ9ZEE?ie=UTF8&tag=tracmostrecec-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=B001CZ9ZEE\">drobo</a> at home. All I have to do is turn the camera on when I get home and it connects to my local wireless network, or if I&#8217;m out and about near an open wireless network I can just turn it on for a while there. Done. No more connecting the USB to my mac mini at home and dumping pictures in to iPhoto and then uploading them to Picasa via some silly plugin. It&#8217;s all automated.</p>\n<p>This has completely changed the way I take and think about taking pictures. It&#8217;s turned taking pictures in to a fun and social activity that requires very little effort. I love it and anyone with a point and shoot should pick one up.</p>\n<p>I just can&#8217;t wait until the next conference I attend where my Picasa feed can be a nearly realtime photo stream of the conference <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>", "timestamp": "2009-02-15T20:12:34.000006", "title": "Product Review: EyeFi Explore"}None{"body-raw": "<p><a href=\"http://us.pycon.org/media/2009/public/pycon2009-vertical-smaller-75x170.png\"><img class=\"alignleft\" title=\"PyCon 2009\" src=\"http://us.pycon.org/media/2009/public/pycon2009-vertical-smaller-75x170.png\" alt=\"\" width=\"75\" height=\"170\" /></a>I&#8217;ll be attending PyCon this year (finally!).</p>\n<p>Somehow I haven&#8217;t attended the last 3 years that I tentatively planned to do so.\u00a0</p>\n<p>Windmill will be well represented. <a href=\"http://www.adamchristian.com\">Adam</a> and I will be on a <a href=\"http://us.pycon.org/2009/conference/talks/\">&#8220;Functional Testing Tools in Python&#8221;</a> panel, and Adam will be giving a full blown <a href=\"http://us.pycon.org/2009/conference/talks/?search=windmill\">Windmill talk</a>.</p>\n<p>There will also be a Windmill Sprint for anyone interested. If you want some hands on time figuring out how to test crazy webapp stuff we&#8217;ll be helping anyone who comes by the first few days of the Sprint. Our plan is to eventually transition the Sprint to working on the windmill2 codebase.</p>\n<p>Feel free to stop by the Sprint or grab me during the conference if you want to discuss any of the other projects I work on (<a href=\"http://code.google.com/p/mozmill\">mozmill</a>, <a href=\"http://code.google.com/p/jsbridge\">jsbridge</a>, <a href=\"http://code.google.com/p/pouch\">pouch</a>, <a href=\"http://www.mikealrogers.com/projects\">etc</a>) or if you want to discuss Mozilla testing and tools in general.</p>", "timestamp": "2009-02-15T05:59:01.000006", "title": "PyCon Chicago 2009"}None{"body-raw": "<p>I&#8217;m leading an effort with the Mozilla QA team to teach community members introductory Python programming skills. I&#8217;m trying out a different approach to teaching using large group code reviews and variable programming assignments that participants can plan based on their own interest.</p>\n<p>The lesson starts next monday and is all being organized through a Google Group. It is open to anyone who would like to participate so if you want to learn Python come <a href=\"http://groups.google.com/group/mozqa-team-python-learning\">on over</a>.</p>\n<p>I <a href=\"http://quality.mozilla.org/blogs/mozqa-python-learning-project\">posted about about the project on QMO</a> and you can see the <a href=\"http://groups.google.com/group/mozqa-team-python-learning/browse_thread/thread/2a28d6d4e6c2cdb2\">discussion surrounding the lesson outline on the Google Group</a>.</p>", "timestamp": "2009-02-03T22:06:26.000001", "title": "Want to Learn Python?"}None{"body-raw": "<p>I spent 2 hours tracking a bug yesterday caused by a bad habit I&#8217;ve realized I must break.</p>\n<p>In Python I tend to create base classes to derive common functionality, a good practice. I also tend to set default attributes on the class, like so.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>class</span> Plant<span>&#40;</span><span>object</span><span>&#41;</span>:\n species = <span>'not known'</span>\n&nbsp;\n<span>class</span> Kale<span>&#40;</span>Plant<span>&#41;</span>:\n species = <span>'brassica'</span>\n <span>def</span> <span>__init__</span><span>&#40;</span><span>self</span>, name<span>&#41;</span>: \n <span>self</span>.<span>name</span> = name</pre></div></div>\n\n<p>My intention is to create lots of Kale objects, some of them will be different varieties of Kale. The intention of the base class and even of the Kale class is to define some common methods and functionality more than it is to defined the data semantics which will be pre instance. </p>\n<p>At this point I realize something, there can be multiple species of different plants, so I change my code.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>class</span> Plant<span>&#40;</span><span>object</span><span>&#41;</span>:\n species = <span>&#91;</span><span>&#93;</span>\n&nbsp;\n<span>class</span> Kale<span>&#40;</span>Plant<span>&#41;</span>:\n species = <span>&#91;</span><span>'brassica'</span><span>&#93;</span>\n <span>def</span> <span>__init__</span><span>&#40;</span><span>self</span>, name<span>&#41;</span>:\n <span>self</span>.<span>name</span> = name</pre></div></div>\n\n<p>This looks kosher, but it&#8217;s not. The problem is that when I first modeled the data I was just initializing species so that it would always be set to something, the information was expected to change per instance. I was using the class to derive unique functionality, not define the data as a class inheritance hierarchy. But continuing to lazily initialize attributes per class which are really suppose to be per instance will end up biting me in the ass.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\">spear_kale = Kale<span>&#40;</span><span>&quot;Spear Kale&quot;</span><span>&#41;</span>\nkai_lan = Kale<span>&#40;</span><span>&quot;Kai-Lan&quot;</span><span>&#41;</span> <span># A chinese form of Brassica oleracea</span>\nkai_lan.<span>species</span>.<span>append</span><span>&#40;</span><span>&quot;Brassica oleracea&quot;</span><span>&#41;</span></pre></div></div>\n\n<p>You see the problem now. When species was a string new instances of Kale that changed it would change the reference to species for their instance to a new string. Now that it&#8217;s a list and we are using append we are appending instance information to the class attribute and spear_kale and any other new Kale instances will have the kai_lan species info attached to them. The initialization of the species list should have been done in __init__ because, once modified, it&#8217;s actually information that is per instance not per class.</p>\n<p>If I would have been using a list in the beginning I probably never would have created it as a class attribute. Since Plant doesn&#8217;t have an __init__ and it seemed like a good idea to default new subclasses to _something_ and I continued to use that pattern in defining the defaults all the way up until it bit me. </p>\n<p>This illustration is pretty straightforward, but today I was debugging an issue in a default added to a base class of a wsgi application class and it took me 2 hours to figure out why an attribute being accessed in one web server was actually pulling an attribute that should only be accessible from a different web server in the same Python. It was painful and as a result I&#8217;ll be much more diligent about defined defaults that are per instance in an __init__ upfront instead of being lazy.</p>", "timestamp": "2009-01-28T20:09:11.000002", "title": "Breaking a bad habit"}None{"body-raw": "<p>I was recently asked how to get unique lines from a text file in Python. The answer is so beautiful that I just had to post it.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\">unique_lines = <span>list</span><span>&#40;</span><span>set</span><span>&#40;</span><span>open</span><span>&#40;</span><span>'filename'</span>, <span>'r'</span><span>&#41;</span>.<span>read</span><span>&#40;</span><span>&#41;</span>.<span>splitlines</span><span>&#40;</span><span>&#41;</span><span>&#41;</span><span>&#41;</span></pre></div></div>", "timestamp": "2009-01-17T05:16:30.000005", "title": "Getting unique lines in a text file"}None{"body-raw": "<p>For as long as I can remember there has been a huge hole where \u201cAdvanced Python\u201d books should be. Recently Tarek Ziade published what I hope to be the first text to fill this hole with <a href=\"http://www.amazon.com/gp/product/184719494X?ie=UTF8&tag=tracmostrecec-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=184719494X\">Expert Python Programming</a> published by <a href=\"http://www.packtpub.com/expert-python-programming/book\">Packt</a>.</p>\n<p><a href=\"http://www.amazon.com/gp/product/184719494X?ie=UTF8&tag=tracmostrecec-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=184719494X\"><img class=\"size-medium wp-image-370 alignright\" title=\"Expert Python Programming\" src=\"http://www.mikealrogers.com/wp-content/uploads/2009/01/51wqdhfwcvl_sl160_.jpg\" alt=\"\" width=\"130\" height=\"160\" /></a></p>\n<p>The book starts off covering basic Python and tools installation (iPython, setuptools, etc). It quickly jumps to best practices which is a spring board for showing off many advanced Python features. By page 34 you\u2019re at list comprehensions, this is my kinda book <span>\u263a</span></p>\n<p>I like how the \u201cBest Practices\u201d subject naturally bleeds in to explanations of some Python internals and special class methods. Python is known as a \u201cone way to do something\u201d language but this is only true in the sense that there is always a \u201cbest\u201d way to do something. By understanding list comprehensions, iterators, decorators, MRO, etc, you can easily show why one way to do something is better than the next and the context in which each should be used.</p>\n<p>The book goes through great pains to try and explain the Python packaging and distribution process. At first I found the text to lack a clear linear line of process. It read like it was jumbled up, with each piece not really fitting in to the next and the whole thing felt very difficult and unintuitive. Then I realized it wasn\u2019t the text that was lacking, but the current state of Python packaging. The sad fact is that Python packaging, distribution, and dependency management is terrible and the only work which seems to be close to solving this very real problem Is what <a href=\"http://pip.openplans.org/\">Ian Bicking has been working on</a> which started to take shape after this book was finished.</p>\n<p>Certain sections of the book suffer from heavy selectivity. The version control section has a somewhat over simplified description of Centralized vs. Decentralized Version Control followed up with a short Mercurial tutorial. Why Mercurial? No clue. I use a half dozen version control systems on an almost daily basis and Mercurial is by no means the most popular.\u00a0</p>\n<p>The book succeeds when it teaches the reader about Python and shows why certain strategies and tools work better than others. It fails when it explains textbook development methodologies and describes tools by way of workflow in said methodologies.\u00a0</p>\n<p>The optimization section was great and, on it\u2019s own, worth the cover price. Lot\u2019s of tools I haven\u2019t used before and now I can\u2019t wait for someone to tell me some code is running slow enough that I need to dig in and use them <span>\u263a</span></p>\n<p>It\u2019s a good book and a must read for anyone who wants to be a better Python programmer. Like any book targeted at more advanced users you should be liberal about skipping sections based on your own expertise and at some points the book even encourages you to do so.</p>", "timestamp": "2009-01-11T03:10:19.000006", "title": "Book Review: Expert Python Programming"}None{"body-raw": "<p>Did Jon Stewart just kick every main stream journalist&#8217;s ass?</p>\n.cc_box a:hover .cc_home{background:url('http://www.comedycentral.com/comedycentral/video/assets/syndicated-logo-over.png') !important;}.cc_links a{color:#b9b9b9;text-decoration:none;}.cc_show a{color:#707070;text-decoration:none;}.cc_title a{color:#868686;text-decoration:none;}.cc_links a:hover{color:#67bee2;text-decoration:underline;}\n<div class=\"cc_box\">\n<div>\n<div class=\"cc_show\"><a href=\"http://www.thedailyshow.com/\" target=\"_blank\">The Daily Show With Jon Stewart</a><span>M &#8211; Th 11p / 10c</span></div>\n<div class=\"cc_title\"><a href=\"http://www.thedailyshow.com/video/index.jhtml?videoId=213380&title=strip-maul\" target=\"_blank\">Strip Maul</a></div>\n</div>\n<p></p>\n<div class=\"cc_links\">\n<div></div>\n<div></div>\n</div>\n<div></div>\n</div>\n<p></p>\n<p>But seriously, why has this invasion been completely unchallenged in the main stream media?</p>", "timestamp": "2009-01-07T06:13:52.000002", "title": "Strip Maul"}None{"body-raw": "<p><a href=\"http://www.amazon.com/Flip-Video-MinoHD-Camcorder-Minutes/dp/B001HSOFI2%3FSubscriptionId%3D02E5W5871AJF7PMMMS82%26tag%3Dtracmostrecec-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB001HSOFI2\"><img class=\"alignright\" src=\"http://ecx.images-amazon.com/images/I/41bTrFm6LpL._SL160_.jpg\" alt=\"\" width=\"160\" height=\"160\" /></a>I&#8217;ve now had 4 Flip Video cameras. I had the Flip Ultra, then the Flip Mino which fell out of my pocket while riding my bike which I replaced with another Mino that was then stolen along with my laptop and bag a few weeks later.</p>\n<p>At a certain point I figured I should just give up trying to own one. I hadn&#8217;t taken much video with any of them and throwing more money at it just seemed silly. With the holidays approaching I read about the\u00a0<a href=\"http://www.amazon.com/Flip-Video-MinoHD-Camcorder-Minutes/dp/B001HSOFI2%3FSubscriptionId%3D02E5W5871AJF7PMMMS82%26tag%3Dtracmostrecec-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB001HSOFI2\">new Flip Mino HD</a> I decided to give the whole thing one last go.</p>\n<p>The video quality is really good if you have good light but is a little worse than the old Mino in poor light. The quality is what you would expect from a quick point and shoot and the battery and hard drive seem to hold out for a little over an hour worth of video.\u00a0</p>\n<p>The Mino is pretty damn small for a video camera but it certainly looks big next to my iPhone.\u00a0It&#8217;s small enough to fit in that little extra pocket in my vintage Levis.\u00a0The only bad news is that the little metal ring on the back side of the Mino is a bit abrasive and will scratch that backside of your iPhone if it&#8217;s in the same pocket.</p>\n<p>Adam and I shot the video below to show his Dad how great the weather was even in November <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>\n<p><br />\n<a href=\"http://vimeo.com/2694871\">Adams Drive Take Three</a> from <a href=\"http://vimeo.com/mikeal\">mikeal</a> on <a href=\"http://vimeo.com\">Vimeo</a>.</p>\n<h3>Using in iMovie</h3>\n<p>iMovie thinks it can import directly from the camera, but it&#8217;s wrong. You need to use the &#8220;Import Movie&#8221; function to import the movies from the mounted Flip&#8217;s drive and create a new event.</p>\n<p>If you want to get the movies up on vimeo you should ignore the regular vimeo iMovie instructions as they are severely outdated. In the newest iMovie you&#8217;ll wanna go to Share -&gt; Export Using Quicktime. Then use <a href=\"http://www.vimeo.com/help/hd#hd_encoding\">these advanced video encoder settings</a>\u00a0and after that make sure you set the Size to 1280&#215;720.</p>", "timestamp": "2009-01-02T07:39:11.000004", "title": "Product Review: Flip Mino HD"}None{"body-raw": "<p>It was pretty hard to get work done yesterday. My feed reader was filled with stories of how Apple is pulling out of Macworld and my IM and email were bursting with people asking me what I think about <a href=\"http://fireunit.org/\">FireUnit</a>.</p>\n<p>I&#8217;m the co-author of two tools that overlap with FireUnit, <a href=\"http://www.getwindmill.com\">Windmill</a> and <a href=\"http://code.google.com/p/mozmill\">MozMill</a>. I say overlap and not &#8220;compete&#8221; because I think the tools differ enough in their goals that they don&#8217;t directly compete.</p>\n<p>FireUnit has some limitations. It&#8217;s an extension to Firebug which means it will only run on Firefox. It&#8217;s focused on providing a simple API for people who are competent JavaScript programmers. I think it&#8217;s safe to say that there is an emphasis on unittesting and not functional testing, and certainly an emphasis on testing content and not chrome.</p>\n<p>Something really great happens when you create a tool that embraces limitations instead of trying to be too much to too many people. You tend to be able to create better smaller purpose tools for a selection of people that have been beating themselves up trying to make tools with less limitations work for a smaller use case.</p>\n<h3>The API</h3>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"javascript\"><span>// Simple true-like/false-like testing</span>\nfireunit.<span>ok</span><span>&#40;</span> <span>true</span><span>,</span> <span>&quot;I'm going to pass!&quot;</span> <span>&#41;</span><span>;</span>\nfireunit.<span>ok</span><span>&#40;</span> <span>false</span><span>,</span> <span>&quot;I'm going to fail!&quot;</span> <span>&#41;</span><span>;</span>\n&nbsp;\n<span>// Compare two strings - shows a diff of the</span>\n<span>// results if they're different</span>\nfireunit.<span>compare</span><span>&#40;</span>\n <span>&quot;The lazy fox jumped over the log.&quot;</span><span>,</span>\n <span>&quot;The lazy brown fox jumped the log.&quot;</span><span>,</span>\n <span>&quot;Are these two strings the same?&quot;</span>\n<span>&#41;</span><span>;</span>\n&nbsp;\n<span>// Compare a string using a regular expression</span>\nfireunit.<span>reCompare</span><span>&#40;</span>\n <span>/The .* fox jumped the log./</span><span>,</span>\n <span>&quot;The lazy brown fox jumped the log.&quot;</span><span>,</span>\n <span>&quot;Compare a string using a RegExp.&quot;</span>\n<span>&#41;</span><span>;</span>\n&nbsp;\n<span>// Display the total results</span>\nfireunit.<span>testDone</span><span>&#40;</span><span>&#41;</span><span>;</span></pre></div></div>\n\n<p>This is the example from <a href=\"http://ejohn.org/blog/fireunit/\">John Resig&#8217;s post about FireUnit</a>. I think it illustrates how awesome the API is. I&#8217;ve always been a huge fan of this &#8220;ok&#8221; style API instead of the larger jUnit style API <a href=\"http://code.google.com/p/mozmill/wiki/JavascriptUnittestModule\">I keep being talked in to implementing</a>. Clearly FireUnit assumes it&#8217;s audience is JavaScript programmers that can write normal expressions to handle their pass/fail logic without the hand holding of a bigger API.</p>\n<p>The beauty of the comparison API you really don&#8217;t appreciate until you look at the UI.</p>\n<h3>Debugging</h3>\n<p>I&#8217;m most critical of tools that don&#8217;t provide sufficient debugging tools. The test debugging environment is even more important than the test authoring environment in the long run.</p>\n<p>There is no better tool for debugging the web than <a href=\"http://www.getfirebug.com/\">Firebug</a>. A big part of Windmill&#8217;s debugging strategy is it&#8217;s integration of <a href=\"http://www.mikealrogers.com/archives/168\">Firebug</a> and <a href=\"http://www.mikealrogers.com/archives/78\">Firebug Lite</a> because there is just no better tool in the world. Firebug ROCKS!</p>\n<p>FireUnit is built as an extension of Firebug, it&#8217;s integrated in a beautiful and intuitive way so they&#8217;ve totally dodged the need for any additional debugging work outside of creating a good UI for the test bits. I&#8217;m calling this out because I think as time goes on people aren&#8217;t going to talk about the debugging experience in FireUnit because they are so used to already using Firebug for debugging their regular development and won&#8217;t recognize how good they have it debugging their tests.</p>\n<h3>The UI</h3>\n<p>Another benefit of embracing limitations is that you trim down your feature set to only what is actually necessary. The upside to having a simple API is that you reduce the complexity of test data you need to represent in the UI. With all that going for it I expected the FireUnit UI to be pretty good but I was <strong>still</strong> blown away.<br />\n<img src=\"http://fireunit.org/fireunit-1.png\" alt=\"\" /></p>\n<p>Look at that comparison UI!</p>\n<h3>The Bad</h3>\n<p>Within the limitations described above FireUnit is great but as soon as you start to cross them you&#8217;ll be disappointed.</p>\n<p>Although they have some helper APIs for doing some functional testing it&#8217;s not a good functional testing tool. The tests are async which is a real pain for functional testing which is incredibly synchronous. But I think if you want to do functional testing multiple browser support is a big concern and will already preclude you from using FireUnit.</p>\n<p>Although you <em>can</em> test Chrome (Mozilla Chrome not Google Chrome) I wouldn&#8217;t venture outside of unittests. If you need to start getting at anonymous nodes and simulating events on them you&#8217;re gonna see your code get about 4 times larger than a typical mozmill test.</p>\n<p>Right now there doesn&#8217;t seem to be a way to run FireUnit tests in continuous integration (tinderbox, buildbot, hudson, etc). But this could easily be overcome using <a href=\"http://code.google.com/p/jsbridge\">jsbridge</a> and I&#8217;m happy to point the FireUnit guys in the right direction <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>\n<p>At the end of the day I think there is a huge need for a tool like FireUnit that just does what it does well and doesn&#8217;t try to be too much to too many people. A tool like this is guaranteed to make it&#8217;s users very happy and I think those users are currently unhappy with the existing set of automation tools that are trying to fill a larger feature set.</p>", "timestamp": "2008-12-19T00:37:06.000004", "title": "FireUnit first impressions"}None{"body-raw": "<p>One of the big questions we&#8217;ve been getting since we outlined how to write unittests in mozmill is how to serve out local files over HTTP. For quite a while I&#8217;ve had a port of mochitest&#8217;s js http server in the mozmill source tree but hadn&#8217;t written a nice API for you to be able to use it inside of your mozmill tests.</p>\n<p>Ideally what I wanted was an API that worked a lot like how the dependencies work, which could serve out local files relative to the tests location on the filesystem. This way we don&#8217;t rely on any Python end to tell use what to serve out and can handle starting and stopping the server inside of the framework in the extension without any extra work from the test author. I finished the implementation a few weeks back but just <a href=\"http://code.google.com/p/mozmill/wiki/MozMillTestBasics#Serving_local_test_files\">documented it today</a>.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"javascript\"><span>var</span> mozmill <span>=</span> <span>&#123;</span><span>&#125;</span><span>;</span> \nComponents.<span>utils</span>.<span>import</span><span>&#40;</span><span>'resource://mozmill/modules/mozmill.js'</span><span>,</span> mozmill<span>&#41;</span><span>;</span>\n<span>var</span> elementslib <span>=</span> <span>&#123;</span><span>&#125;</span><span>;</span> \nComponents.<span>utils</span>.<span>import</span><span>&#40;</span><span>'resource://mozmill/modules/elementslib.js'</span><span>,</span> elementslib<span>&#41;</span><span>;</span>\n&nbsp;\n<span>var</span> url <span>=</span> collector.<span>addHttpResource</span><span>&#40;</span><span>'./files'</span><span>&#41;</span><span>;</span>\n&nbsp;\n<span>var</span> setupModule <span>=</span> <span>function</span><span>&#40;</span>module<span>&#41;</span> <span>&#123;</span>\n module.<span>controller</span> <span>=</span> mozmill.<span>getBrowserController</span><span>&#40;</span><span>&#41;</span><span>;</span>\n<span>&#125;</span>\n&nbsp;\n<span>var</span> testFoo <span>=</span> <span>function</span><span>&#40;</span><span>&#41;</span><span>&#123;</span>\n controller.<span>open</span><span>&#40;</span>url<span>+</span><span>'index.html'</span><span>&#41;</span><span>;</span>\n<span>&#125;</span></pre></div></div>\n\n<p>This made it in before the last release so it&#8217;s available for use right away. Enjoy <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>", "timestamp": "2008-12-18T22:59:41.000003", "title": "MozMill HTTP Server API"}None{"body-raw": "<p>Everyday I wake up and wonder why I own such a large car. Don&#8217;t get me wrong, I love my car, it&#8217;s a black 2008 touring edition Prius with the full geek package (bluetooth, GPS, wireless key). But I really don&#8217;t drive it much.</p>\n<table>\n<tr>\n<td><a href=\"http://picasaweb.google.com/lh/photo/UMqc7vh5s439ey5FXJP16g\"><img src=\"http://lh6.ggpht.com/_khvmq56W610/STnIZX8_ldI/AAAAAAAAAwo/wu3PMAOyOio/s400/IMG_0101.JPG\" /></a></td>\n</tr>\n<tr>\n<td></td>\n</tr>\n</table>\n<p>Most days I ride my bike and when I go to San Francisco it&#8217;s just easier to take the Bart most of the time. I rarely fill my car with any additional passengers unless you count my dog. All said and done I&#8217;d say the car only leaves it&#8217;s parking spot about 3 days a week, and most of the drives are less than 50 miles total. Sure, once a quarter we have an onsite at Mozilla and I drive to Mountain View 4 days in a row, but other than that I don&#8217;t take many long trips.</p>\n<p>For the most part, my life doesn&#8217;t require such a large car. I do drive just a little too often to use a <a href=\"http://www.citycarshare.org/\">flex car</a>, but almost all my driving is short distance and with only one or two people in the car. If I had to rethink my purchase it would have been sufficient to buy a <a href=\"http://www.smartusa.com/smart-fortwo-pure.aspx\">smart car</a>.</p>\n<p>This is my transit story, but this is quickly becoming the transit story for many Americans. I know very few people that have decided to buy homes far from urban areas, and only one of them from my generation.</p>\n<h3>Thinking forward</h3>\n<p>The costs of commuting to work will only increase in the next 5 years. Gas prices seem lower now, but remember that there is only so much oil in the world and the closer we get to running out of it the more expensive it becomes.</p>\n<p>My generation never seemed to think of employment as having much permanence which underlined the need to live in a more urban area with greater chance of finding new employment. The current economic crisis is obviously increasing the lack of confidence in holding on to any current employment so there is very little incentive to move away from employment centers.</p>\n<p>The more people live in urban areas the less need they have for single commuter vehicles and the more fuel prices increase the smaller any single commuter vehicles will need to be. </p>\n<p>American cars are notoriously larger than they need to be. Vehicle efficiency is about size and weight just as much as it is about the fuel source. Yet all the plans for more environmentally friendly vehicles from the American automakers seem to be identical cars to their current line with electric/hybrid/flex fuel engines for higher prices. Meanwhile, a new set of companies is making inroads in alternate vehicles that are a closer match to our new transit patterns.</p>\n<p>Add to this the expansive transit plans of the Obama administration and you have far less need for vehicles even as large as a Japanese sedan. I know of only one small electric vehicle from a traditional automaker and that&#8217;s the Mini EV which is just now entering the public trial phase.</p>\n<h3>Being green only takes you so far</h3>\n<p>Morals are a distant second to economic necessities when making wide scale changes in human behavior. Thinking that environmentalism can change transportation behavior requires that the majority of people driving put their personal responsibility for future generations and the planet ahead of any social and economic realities they face. Not gonna happen.</p>\n<p>Fortunately the social and economic realities are driving us towards more efficiency and sustainability in our transit patterns which, if we do this right, might just end up saving the planet.</p>\n<h3>We have to let them fail</h3>\n<p>Our problem is that we continue to turn to old institutions to create transformative products. Ford and GM can&#8217;t make a car that is efficient from the ground up, there are just too many incentives for them to do things the same way they always have even if forced to changes things a bit by congress. </p>\n<p>These companies are going to fail, big time. It&#8217;s an inevitability. People can&#8217;t afford to buy what they are selling and they just can&#8217;t make what people need.</p>\n<p>Transformational products are already coming from a bunch of new companies. Companies that, believe it or not, employ people. The more their products are bought and manufacturing of their vehicles increases the more workers they will need. In fact, medium sized business tend to be much better employers than large corporations, so a new movement of medium sized auto companies in the long term would be much better for workers than trying to save the current lot.</p>\n<p>An yes, steel production will decrease, steel companies will fail and people will lose their jobs, because we need to use less steel. The suppliers of the big auto companies will also fail, because we don&#8217;t need their parts, we need new parts from new companies. All those jobs will be replaced by new companies and new jobs because you know what, people still need to get around.</p>", "timestamp": "2008-12-06T00:38:16.000005", "title": "Will people buy fuel efficient american cars?"}None{"body-raw": "<p>It took a few months but the <a href=\"http://www.myspace.com/broaklandbicycles\">Broakland guys</a> built me a new custom track bike.</p>\n<table border=\"0\">\n<tbody>\n<tr>\n<td><a href=\"http://picasaweb.google.com/lh/photo/XtmLJeUJKj9ydkvFbH9YxQ\"><img src=\"http://lh4.ggpht.com/_khvmq56W610/STeL5emDZeI/AAAAAAAAAwc/kjo2FzyMwVQ/s400/Bike.JPG\" alt=\"\" /></a></td>\n</tr>\n<tr>\n<td></td>\n</tr>\n</tbody>\n</table>\n<p>I&#8217;m still getting used to it, evidenced by the fact that I took huge dive the other day, but it rides beautifully.</p>", "timestamp": "2008-12-04T07:58:23.000003", "title": "New Bike!"}None{"body-raw": "<p>In <a href=\"http://code.google.com/p/jsbridge/\">jsbridge</a> we have a socket that stays open constantly and the JavaScript end streams JSON objects for all the events we care about in the browser back over to Python. In jsbridge this happens asynchronously and we use asyncore since it&#8217;s available in stdlib and is pretty lightweight, but the bulk of the parsing code is universal.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>import</span> simplejson\ndecoder = simplejson.<span>JSONDecoder</span><span>&#40;</span><span>&#41;</span>\n&nbsp;\n<span>class</span> StreamReader<span>&#40;</span><span>object</span><span>&#41;</span>:\n sbuffer = <span>''</span>\n <span>def</span> process_read<span>&#40;</span><span>self</span>, data<span>&#41;</span>:\n <span>&quot;&quot;&quot;Parse out json objects and fire callbacks.&quot;&quot;&quot;</span>\n <span>self</span>.<span>sbuffer</span> += data\n <span>self</span>.<span>parsing</span> = <span>True</span>\n <span>while</span> <span>self</span>.<span>parsing</span>:\n <span># Remove erroneus data in front of callback object</span>\n index = <span>self</span>.<span>sbuffer</span>.<span>find</span><span>&#40;</span><span>'{'</span><span>&#41;</span>\n <span>if</span> index <span>is</span> <span>not</span> -<span>1</span> <span>and</span> index <span>is</span> <span>not</span> <span>0</span>:\n <span>self</span>.<span>sbuffer</span> = <span>self</span>.<span>sbuffer</span><span>&#91;</span>index:<span>&#93;</span>\n <span># Try to get a json object from the data stream</span>\n <span>try</span>:\n obj, index = decoder.<span>raw_decode</span><span>&#40;</span><span>self</span>.<span>sbuffer</span><span>&#41;</span>\n <span>except</span> <span>Exception</span>, e:\n <span>self</span>.<span>parsing</span> = <span>False</span>\n <span># If we got an object fire the callback infra</span>\n <span>if</span> <span>self</span>.<span>parsing</span>:\n <span>self</span>.<span>fire_callbacks</span><span>&#40;</span>obj<span>&#41;</span>\n <span>self</span>.<span>sbuffer</span> = <span>self</span>.<span>sbuffer</span><span>&#91;</span>index:<span>&#93;</span></pre></div></div>\n\n<p>The process_read function gets called every time a block of data gets read from the stream so it needs to be able to handle multiple JSON objects in a single read, objects that span multiple reads, and junk (usually spaces and return carriers) showing up between JSON objects.</p>\n<p>If you wanna see this code in the wild you can check out the <a href=\"http://code.google.com/p/jsbridge/source/browse/trunk/jsbridge/network.py#205\">jsbridge source</a>.</p>", "timestamp": "2008-12-04T02:40:14.000003", "title": "Processing a JSON stream"}None{"body-raw": "<p>One of the first pieces of feedback we got on MozMill was that there didn&#8217;t seem to be any way to click on system menus.</p>\n<p>System menus are defined in XUL using a <a href=\"https://developer.mozilla.org/en/XUL/menu\">special set of elements</a>. Those are then displayed differently on every operating system and as such we can&#8217;t use tools like the MozMill Inspector to get repeatable elements to click on.</p>\n<p>After digging in to this problem a bit I figured out that the elements defining menus can be traversed and that they even respond properly to .click(). I then wrote thin API around the elements so that they can be easily looked up by name the way they are displayed in the menus. You can see the full documentation <a href=\"http://code.google.com/p/mozmill/wiki/MenuAPI\">here</a>.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"javascript\"><span>var</span> mozmill <span>=</span> <span>&#123;</span><span>&#125;</span><span>;</span> \nComponents.<span>utils</span>.<span>import</span><span>&#40;</span><span>'resource://mozmill/modules/mozmill.js'</span><span>,</span> mozmill<span>&#41;</span><span>;</span>\n<span>var</span> elementslib <span>=</span> <span>&#123;</span><span>&#125;</span><span>;</span> \nComponents.<span>utils</span>.<span>import</span><span>&#40;</span><span>'resource://mozmill/modules/elementslib.js'</span><span>,</span> elementslib<span>&#41;</span><span>;</span>\n&nbsp;\n<span>var</span> setupModule <span>=</span> <span>function</span> <span>&#40;</span>module<span>&#41;</span> <span>&#123;</span>\n module.<span>controller</span> <span>=</span> mozmill.<span>getBrowserController</span><span>&#40;</span><span>&#41;</span><span>;</span>\n<span>&#125;</span>\n&nbsp;\n<span>var</span> testMenu <span>=</span> <span>function</span> <span>&#40;</span><span>&#41;</span> <span>&#123;</span>\n <span>// Example 1: Click menus without testing the click</span>\n controller.<span>menus</span>.<span>File</span><span>&#91;</span><span>&quot;New Tab&quot;</span><span>&#93;</span>.<span>click</span><span>&#40;</span><span>&#41;</span><span>;</span>\n controller.<span>menus</span>.<span>View</span>.<span>Sidebar</span>.<span>Bookmarks</span>.<span>click</span><span>&#40;</span><span>&#41;</span><span>;</span>\n controller.<span>menus</span>.<span>View</span><span>&#91;</span><span>&quot;Page Style&quot;</span><span>&#93;</span><span>&#91;</span><span>&quot;No Style&quot;</span><span>&#93;</span>.<span>click</span><span>&#40;</span><span>&#41;</span><span>;</span>\n <span>// Example 2: Click menus and test the click</span>\n controller.<span>click</span><span>&#40;</span><span>new</span> elementslib.<span>Elem</span><span>&#40;</span>controller.<span>menus</span>.<span>File</span><span>&#91;</span><span>&quot;New Tab&quot;</span><span>&#93;</span><span>&#41;</span><span>&#41;</span><span>;</span>\n controller.<span>click</span><span>&#40;</span><span>new</span> elementslib.<span>Elem</span><span>&#40;</span>controller.<span>menus</span>.<span>View</span>.<span>Sidebar</span>.<span>Bookmarks</span><span>&#41;</span><span>&#41;</span><span>;</span>\n controller.<span>click</span><span>&#40;</span><span>new</span> elementslib.<span>Elem</span><span>&#40;</span>controller.<span>menus</span>.<span>View</span><span>&#91;</span><span>&quot;Page Style&quot;</span><span>&#93;</span><span>&#91;</span><span>&quot;No Style&quot;</span><span>&#93;</span><span>&#41;</span><span>&#41;</span><span>;</span>\n<span>&#125;</span></pre></div></div>\n\n<p>As you can see the API is a simple chain of objects by name cascading down the different sub menus until a menu element is reached. Attribute access is just plain old JavaScript so you only need to use [\"name\"] syntax when looking up menus with names that contain spaces. The API is most definitely case sensitive.</p>", "timestamp": "2008-12-03T03:25:16.000002", "title": "Using the mozmill menu API"}None{"body-raw": "<p>MozMill already has some big advantages over mochitest. For one, you don&#8217;t need a special test build, you can write and run tests against any build of a Mozilla Application. You can even write and run tests just using the extension and not worry about any Python stuff until you set it up in continuous integration.</p>\n<p>MozMill already runs in &#8220;chrome&#8221;, or what Adam and I have been referring to as the &#8220;trusted&#8221; environment. All the tests that get run in MozMill are imported in this environment, which means you have access to pretty much everything in the Mozilla environment. We also have a <a href=\"http://code.google.com/p/mozmill/wiki/MozMillTestBasics\">dependency system and a setup/teardown system for tests</a>.</p>\n<p>All we were missing was a simple unittest API that can trigger failures without causing exceptions like the MozMill functional testing APIs. I looked at what others have done including <a href=\"http://dojotoolkit.org/book/dojo-book-0-9/part-4-meta-dojo/d-o-h-unit-testing\">dojo</a>, <a href=\"http://mochikit.com/tests/index.html\">mochikit</a>, and <a href=\"http://www.jsunit.net/documentation/assertions.html\">jsunit</a>. </p>\n<p>Fortunately MozMill gets out of any test registration and staggering stuff, it already has a well defined way of defining tests and dependencies and a clear way to run tests for debugging and continuous integration. Of all the different jum (JavaScript Unittest Module) APIs I liked jsunit the most except for the incredibly stupid idea of passing the comment argument first instead of making it an optional last argument.</p>\n<p>In the end MozMill got it&#8217;s own jum which I&#8217;ve just <a href=\"http://code.google.com/p/mozmill/wiki/JavascriptUnittestModule\">finished up documenting</a>.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"javascript\"><span>var</span> jum <span>=</span> <span>&#123;</span><span>&#125;</span><span>;</span> Components.<span>utils</span>.<span>import</span><span>&#40;</span><span>'resource://mozmill/modules/jum.js'</span><span>,</span> jum<span>&#41;</span><span>;</span>\n&nbsp;\n<span>var</span> testAsserts <span>=</span> <span>function</span><span>&#40;</span><span>&#41;</span> <span>&#123;</span>\n jum.<span>assert</span><span>&#40;</span><span>true</span><span>&#41;</span><span>;</span>\n jum.<span>assertTrue</span><span>&#40;</span><span>true</span><span>&#41;</span><span>;</span>\n jum.<span>assertFalse</span><span>&#40;</span><span>false</span><span>&#41;</span><span>;</span>\n jum.<span>assertEquals</span><span>&#40;</span><span>'asdf'</span><span>,</span> <span>'asdf'</span><span>&#41;</span><span>;</span>\n jum.<span>assertNotEquals</span><span>&#40;</span><span>'asdf'</span><span>,</span> <span>'fdsa'</span><span>&#41;</span><span>;</span>\n jum.<span>assertNull</span><span>&#40;</span><span>null</span><span>&#41;</span><span>;</span>\n jum.<span>assertNotNull</span><span>&#40;</span><span>true</span><span>&#41;</span><span>;</span>\n jum.<span>assertUndefined</span><span>&#40;</span><span>&#123;</span><span>&#125;</span>.<span>asdf</span><span>&#41;</span><span>;</span>\n jum.<span>assertNotUndefined</span><span>&#40;</span><span>'asdf'</span><span>&#41;</span><span>;</span>\n jum.<span>assertNaN</span><span>&#40;</span><span>'a'</span><span>&#41;</span><span>;</span>\n jum.<span>assertNotNaN</span><span>&#40;</span><span>4</span><span>&#41;</span><span>;</span>\n jum.<span>pass</span><span>&#40;</span><span>&#41;</span><span>;</span>\n<span>&#125;</span>\n&nbsp;\n<span>var</span> testNotAsserts <span>=</span> <span>function</span><span>&#40;</span><span>&#41;</span> <span>&#123;</span>\n <span>// All of these calls should fail</span>\n jum.<span>assert</span><span>&#40;</span><span>false</span><span>&#41;</span><span>;</span>\n jum.<span>assertTrue</span><span>&#40;</span><span>false</span><span>&#41;</span><span>;</span>\n jum.<span>assertTrue</span><span>&#40;</span><span>'asf'</span><span>&#41;</span><span>;</span>\n jum.<span>assertFalse</span><span>&#40;</span><span>true</span><span>&#41;</span><span>;</span>\n jum.<span>assertFalse</span><span>&#40;</span><span>'asdf'</span><span>&#41;</span><span>;</span>\n jum.<span>assertEquals</span><span>&#40;</span><span>'asdf'</span><span>,</span> <span>'fdsa'</span><span>&#41;</span><span>;</span>\n jum.<span>assertNotEquals</span><span>&#40;</span><span>'asdf'</span><span>,</span> <span>'asdf'</span><span>&#41;</span><span>;</span>\n jum.<span>assertNull</span><span>&#40;</span><span>true</span><span>&#41;</span><span>;</span>\n jum.<span>assertNotNull</span><span>&#40;</span><span>null</span><span>&#41;</span><span>;</span>\n jum.<span>assertUndefined</span><span>&#40;</span><span>'asdf'</span><span>&#41;</span><span>;</span>\n jum.<span>assertNotUndefined</span><span>&#40;</span><span>&#123;</span><span>&#125;</span>.<span>asdf</span><span>&#41;</span><span>;</span>\n jum.<span>assertNaN</span><span>&#40;</span><span>4</span><span>&#41;</span><span>;</span>\n jum.<span>assertNotNaN</span><span>&#40;</span><span>'f'</span><span>&#41;</span><span>;</span>\n jum.<span>fail</span><span>&#40;</span><span>&#41;</span><span>;</span>\n<span>&#125;</span></pre></div></div>\n\n<p>All of these functions take an optional comment argument which can be any JSON serializable value (string, int, obj, array, null, bool).</p>\n<p>What we&#8217;re missing right now is the http local file server. I&#8217;ve already ported mochikit&#8217;s web server to be a resource but I&#8217;m still working on a better API for using it. What we want is for tests to simply define local relative paths that should be mounted at different local url namespaces and the framework can handle starting and stopping the server if necessary. This API will be finished in the next few weeks and ready for MozMill 1.0 (which we&#8217;re looking at pushing out before January 1st).</p>", "timestamp": "2008-12-03T01:16:27.000002", "title": "Using mozmill for unittests"}None{"body-raw": "<p>Last week we finished up the <a href=\"https://addons.mozilla.org/en-US/firefox/addon/9018\">1.0RC2</a> release of <a href=\"http://code.google.com/p/mozmill/\">MozMill</a>.</p>\n<p>The biggest new feature was is the Test Recorder. You can now hit the Record button and use the Application normally and create a test outline. I say &#8220;test outline&#8221; because it&#8217;s usually necessary after creating a recorded test to go in and fill it up with a few conditional wait calls, like waitForElement and waitForPageLoad. If you don&#8217;t the test runs too fast and ends up failing pretty quickly. We&#8217;re working on some future code to pick up things like new page loads so that we can add those waits in a recorded test but for now you&#8217;ll have to do them by hand.</p>\n<p>We also have significantly improved some of the documentation.</p>\n<ul>\n<li><a href=\"http://code.google.com/p/mozmill/wiki/MozMillTestBasics\">http://code.google.com/p/mozmill/wiki/MozMillTestBasics</a></li>\n<li><a href=\"http://code.google.com/p/mozmill/wiki/CommandLine\">http://code.google.com/p/mozmill/wiki/CommandLine</a></li>\n<li><a href=\"http://code.google.com/p/mozmill/wiki/MenuAPI\">http://code.google.com/p/mozmill/wiki/MenuAPI</a></li>\n</ul>\n<p>I&#8217;ll be writing some more blog entries this week on using MozMill for writing and running different kinds of tests.</p>", "timestamp": "2008-11-30T00:24:51.000006", "title": "MozMill 1.0RC2 w/ Test Recorder"}None{"body-raw": "<p>So, what do you do after &#8220;your guy&#8221; wins the presidency.</p>\n<p>First you have a drink, then you start holding them to task for all those campaign promises and poisitons they took. If you&#8217;re a good activist, you&#8217;re always attacking the guy who&#8217;s in power, no matter who they are.</p>\n<p>Unfortunately, I don&#8217;t even have to wait for Obama to be president to start attacking him. Now, and even during his campaign, Obama took up one position in particular that is completely unacceptable under any circumstances; his position on gay marriage.</p>\n<p>At this time in our history, nearly the 30th anniversary of the assassination of Harvey Milk, anything less than unequivocal and complete support of gay rights is unacceptable. There is no excuse.</p>\n<p>I disagree with Obama on a variety of issues, but on most of them I can see why it isn&#8217;t politically feasible for him to take my position. For example; Obama does not share my position on fundamental Palestinian human rights. But that&#8217;s my fault, and the fault of the movement for Palentine, in not convincing enough of the american public of our position on Palestine rather than <a href=\"http://www.aipac.org/\">AIPAC&#8217;s</a>.</p>\n<p>But gay rights is very different. Within popular American culture homosexuality is now almost universally accepted. In the last ten years homosexual persons have gone from a few stereotypical sitcom characters to a series of incredibly popular talk show hosts, political pundits, and positive sitcom characters. Many of which do not conform to traditional gay stereotypes and are well accepted in popular American culture. I don&#8217;t wanna harp on television as a pop culture barometer but it&#8217;s a good metric to what is easily accepted by the public.</p>\n<p>In this climate, at this time in our history, there is no excuse for those in power who do not support gay rights. There is no compromise. No &#8220;civil union&#8221;. This is not a negotiation. There is only one word for any position less than universal gay rights in the United States; &#8220;Unacceptable&#8221;.</p>", "timestamp": "2008-11-24T08:47:58", "title": "Obama\u2019s unacceptable position"}None{"body-raw": "<p>Those that know me well know that I hold some fairly radical political beliefs. Regardless of what might be referred to as my &#8220;Utopian&#8221; beliefs suggest, I do partake regularly in main stream politics. But because I hold such radical beliefs I think of voting a little differently than most.</p>\n<p>Most people think of their vote as a moral stake in the ground, declaring to the ballot machine that YOU BELIEVE IN THIS! It&#8217;s easy for me to detach myself from that because there isn&#8217;t a viable candidate that believes in all of my values. There are, however, candidates that will make things a little better than they are now. There are candidates that will be more malleable to social movements and changes in policy. And although I don&#8217;t believe that capitalism can ultimately provide equality to all people significantly less people would starve to death or die of preventable illnesses if we listened to Nobel prize winning economists like Joseph Stiglitz.</p>\n<h2>Ballot</h2>\n<p>I get an absentee ballot but I don&#8217;t mail it in. In California you can show up on election day and drop your absentee ballot in a locked box to be counted later. I do this so that I can fill out all of the local representatives and propositions from my home with all the information available on the internet about each issue. I don&#8217;t fill in some state representatives and the presidential pick until the day of the election for reasons that will be explained.</p>\n<h2>National</h2>\n<p>California is going to Obama, it&#8217;s 2pm on November 4th and it&#8217;s very clear I don&#8217;t have to worry about him winning my state. If I lived in Pennsylvania or Ohio I&#8217;d be concerned and I would be voting for Obama. On economic policy there are large differences between the candidates. These differences translate in to serious standard of living differences for poor and working people across the country.</p>\n<p>I&#8217;m fortunate enough to live in a state where Obama doesn&#8217;t need my vote and I can easily support a third party. I&#8217;ve voted for Nadar in the past but I just can&#8217;t do it this year.</p>\n<p>Nadar is a true American hero. Nadar did much more as a professional citizen than Obama can hope to accomplish as President. Just to name a few things; Safe Drinking Water Act, Occupational Safety and Health Administration (OSHA), Environment Protection Agency (EPA), Consumer Product Safety Administration, the recall of millions of defective motor vehicles, seat belts and air bags, and last but not least the Freedom of Information Act of 1974. Unfortunately, Nadar&#8217;s presidential bids have done nothing but marginalize him in a time where he should have been the strongest citizen voice in the country. The unbelievable corporate greed and economic failures of the last 7 years are issues in which Ralph Nadar should have been the first voice you would hear on news and television but instead he was on the road raising money for another Presidential bid or paying down his debt from the last. It&#8217;s time to move on.</p>\n<p>I&#8217;ll be voting for Cynthia McKinney of the Green Party. The Green Party does a lot, and they are building a good third party from the ground up; a grass roots organization with lots of local representatives in seats of influence gaining momentum for better viability in higher electoral positions. The more votes they get this election the better for the Party and they need it more than Obama needs another California vote.</p>\n<h2>Propositions</h2>\n<p>I love California. California has the strongest ballot initiative program I know of in the country. I&#8217;m a strong believer in participatory democracy over representative democracy so the ability to take important issues directly to voters is a great thing to be a part of as a resident of this state.</p>\n<p>As a resident of Seattle, Washington I voted NO on the building of 2 different sports stadiums in which I was in the majority. The elected representatives kindly told me and other majority voters that we can shove it up our ass and built the stadiums anyway. Certainly seems to have done a lot for those amazing Seattle sports teams everyone talks about <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_razz.gif\" alt=\":P\" class=\"wp-smiley\" /> </p>\n<p>I always hear complaints about all the propositions on the ballot in California, mainly just complaints about the sheer number of them. And of course whenever there is an initiative you don&#8217;t agree you complain about it being an abuse of the process. This is what democracy looks like, and if you&#8217;re not in agreement with the majority of the electorate then you need to work towards a social movement that will change the minds of citizens, not complain about a more democratic process.</p>\n<p>Prop 1A is a zero emissions rail line from SF to LA, a good idea at virtually any cost.</p>\n<p>Prop 2 is a standard on confining farm animals, targeted mainly at chicken coops. Confining animals like this is a bad idea even if you don&#8217;t believe in animal rights, it&#8217;s not sanitary and leads to poor agricultural product and the spread of diseases among animals. It&#8217;s not rocket science why some free range chicken tests 0% for salmonella while Foster Farms tests 60%. The main argument against the proposition is primarily that agricultural standards like this don&#8217;t belong on the ballot, I disagree and think that direct democracy is a proper place for any law or standard.</p>\n<p>Prop 3 is a bond for Children&#8217;s Hospital. Children&#8217;s Hospital is a for profit medical company and I don&#8217;t approve all the money I see for them on the ballot and in fact I voted against an Oakland initiative earlier in the year for construction of a new building. This measure is a bit different. 95% of Children&#8217;s Hospital patients are children on Medi-Cal (a wonderful state medical insurance program) of which all the poor children in Oakland are covered. The bond covers new equipment and what seems to be just enough money to keep things running at their current level. I&#8217;m voting YES.</p>\n<p>Prop 4 is a waiting period and notification for parents of underage women who wish to have an abortion. I&#8217;m sorry but if a 16 year old girl gets pregnant I believe she has the right to her body and health and as such should be able to terminate the pregnancy even if her mother is Catholic.</p>\n<p>Prop 5 is a measure championed by the Drug Policy Alliance. It&#8217;s a step toward further decriminalization of non-violent drug offenses. It has more money for treatment and limits court authority to incarcerate non-violent offenders. California already passed a measure like this before but the results haven&#8217;t been very good. In my opinion some of the previous measure&#8217;s failings were because courts were still allowed to incarcerate under a myriad of conditions and not only treatment was required of offenders but clean drug tests. We have atrocious drug policy in this country and an incarceration rate only rivaled by China. Non-Violent offenders shouldn&#8217;t be jailed by the hundreds of thousands and mandatory treatment will never immediately result in the recession of an addiction. Both my father and step-mother are chemical dependency counselors and happen to agree. I&#8217;m voting YES.</p>\n<p>Prop 6 is one of two &#8220;tough on crime&#8221; propositions. I not only don&#8217;t agree with the premise of the bill (increased mandatory sentencing and the increase of certain offenses to new degrees) but it burdens California with a huge bill to pay for increased spending on the criminal system without a way to pay for it. Propositions that don&#8217;t dictate how they are paid for take money out of the general budget, which in California means decreases in federal employees and huge cuts to the already suffering California Public School system. Voting NO.</p>\n<p>Prop 7 is an incredibly aggressive environmental proposition. It sets aside a bunch of money for renewable energy and more local production of energy as well as proposes some lofty emission goals. Critics have basically said that the targets aren&#8217;t reachable, which they probably aren&#8217;t. But it&#8217;s not like the voters will be throwing anyone in jail if the goals aren&#8217;t met, I actually find the aggressiveness of the goals a good thing and think the less the state relies on national energy conglomerates and foreign oil the better.</p>\n<p>Obviously I&#8217;m voting NO on Prop 8, a California State Constitutional Amendment banning on gay marriage. The movement for Prop 8 has mostly consisted of a scare campaign that shows children being informed about the fact that gay people do in fact exist and start happy families together. The entire notion of children being informed about homosexuality as a moral slight is openly ignorant and I won&#8217;t dedicate too much time to arguing against it.</p>\n<p>Prop 9 is the other &#8220;tough on crime&#8221; bill. It suffers from all the same problems Prop 6 suffers but this time in the name of &#8220;protecting victims&#8221; by making it more difficult for inmates to be released from prison.</p>\n<p>Prop 10 is the first environmental measure I&#8217;ve ever voted AGAINST. It&#8217;s focused almost entirely on natural gas, and provides further state subsidy to buyers of low emission vehicles. At this point I think we can safely stop adding additional state giveaways for people who purchase hybrid vehicles, of which I am a member, there&#8217;s already enough of an incentive to buy one with current tax breaks and the cost of oil in general. Not to mention the obscene giveaways to natural gas companies, of which the promoter of the bill is a major owner.</p>\n<p>Prop 11 is a no brainer. It takes away from elected officials one of the most undemocratic of privileges, the ability to redistrict voters based solely on improving electoral victories for oneself or party. Voting for the measure creates huge barriers to redistricting preventing things like&#8230;. Texas.</p>\n<p>And finally, Prop 12 is a reinvestment in the Cal-Vet program in the form of a general bond. This program provides good money in to the right pockets helping veterans with rising costs and home foreclosures among other things.</p>", "timestamp": "2008-11-05T00:38:21.000002", "title": "Mandatory Election Day Post"}None{"body-raw": "<p>It&#8217;s usually a good idea to document cool features you write and tell people about them. I totally forgot about this one, which I wrote during DjangoCon a few months back.</p>\n<p>A few years ago I wrote a patch for live server support in Django. The patch fell out of sync with trunk and was picked up a year or so later and <a href=\"http://code.djangoproject.com/ticket/2879\">substantially improved</a>. But the patch didn&#8217;t end up making it in for 1.0 <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_sad.gif\" alt=\":(\" class=\"wp-smiley\" /> . Luckily the code is simple enough that I was able to use it windmill and add live server support to any Django 1.0 install by <a href=\"http://trac.getwindmill.com/browser/trunk/windmill/authoring/djangotest.py\">dynamically overriding and changing the classes that we need</a> to start and stop a live test server for you django project.</p>\n<p>After it&#8217;s all said and done this makes it dirt simple to bootstrap windmill tests from your Django unittests, all you need to do is define a single test class along side your other django unittests pointing to the directory of windmill tests you want to run and which browser you want to run them in and windmill&#8217;s django support will automatically start a live django server and run your windmill tests against it.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>from</span> <span>os</span> <span>import</span> path\n<span>from</span> windmill.<span>authoring</span> <span>import</span> djangotest \n&nbsp;\n<span>class</span> WindmillTests<span>&#40;</span>djangotest.<span>WindmillDjangoUnitTest</span><span>&#41;</span>:\n test_dir = path.<span>join</span><span>&#40;</span>path.<span>dirname</span><span>&#40;</span>path.<span>abspath</span><span>&#40;</span>__file__<span>&#41;</span><span>&#41;</span>, <span>'windmilltests'</span><span>&#41;</span>\n browser = <span>'firefox'</span></pre></div></div>\n\n<p>This is also all written up on a <a href=\"http://trac.getwindmill.com/wiki/WindmillAndDjango\">wiki page</a> along with some of the caveats.</p>", "timestamp": "2008-11-02T22:59:28.000006", "title": "Running Windmill tests from Django"}None{"body-raw": "<p>I started working on this library months ago and it&#8217;s been getting some use already. I spoke about it a bit at Mozilla Summit and as a result there was a post on <a href=\"http://ajaxian.com/archives/jsbridge-powering-mozilla-with-python\">Ajaxian</a>, but for the most part I&#8217;ve been holding off on promoting it until I solidified the API and pushed out a solid release.</p>\n<p><a href=\"http://code.google.com/p/jsbridge\">jsbridge</a> is a Python to JavaScript translation interface for Mozilla applications. It&#8217;s implemented as an extension and can be dynamically installed and launched in a new &#8220;clean&#8221; profile using <a href=\"http://code.google.com/p/mozrunner\">mozrunner</a>.</p>\n<p>You can call functions and set variables in any window in any scope from Python and those objects are returned and represented as Python objects (which are just classes that inherit from Python base types). There are obvious limitations for assignment and representations in Python, you can really only send objects over the bridge that can be JSON serialized, but it does support assignments by reference so you can move around and manipulate anything that&#8217;s already there.</p>\n<p>But the most interesting feature is the event system. The event system is available as a resource from inside the Mozilla environment (in other words you can import it from your Firefox extension). Events fired on the JavaScript end are serialized as JSON and sent to the Python side. This means you can add listeners in Python to events fired from the Mozilla JavaScript environment.</p>\n<p>This is a big deal. It means we can write significantly cleaner tools. We can now create tools solely as Firefox extensions that don&#8217;t require any special Python code to run, but have code that checks if jsbridge is installed and send pertinent events over the bridge for continuous integration. No more printing to console and parsing in Python, no more outputting to log files and parsing them, no more scripts calling scripts and OH MAN MY HEAD HURTS!</p>\n<p>The documentation has some great <a href=\"http://code.google.com/p/jsbridge/wiki/UsingJSBridge#JavaScript_(most_likely_to_be_placed_in_your_extension_code)\">examples</a>.</p>\n<p>For a little snippet of the events system in the wild here is some new <a href=\"http://code.google.com/p/mozmill\">mozmill</a> Python code that sends all the events to the Python logger.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>import</span> <span>logging</span>\nlogger = <span>logging</span>.<span>getLogger</span><span>&#40;</span><span>&quot;mozmill&quot;</span><span>&#41;</span>\n&nbsp;\n<span>from</span> jsbridge <span>import</span> events\n&nbsp;\n<span>class</span> LoggerListener<span>&#40;</span><span>object</span><span>&#41;</span>:\n cases = <span>&#123;</span>\n <span>'mozmill.pass'</span>: <span>lambda</span> obj: logger.<span>debug</span><span>&#40;</span><span>'Test Pass: '</span>+<span>repr</span><span>&#40;</span>obj<span>&#41;</span><span>&#41;</span>,\n <span>'mozmill.fail'</span>: <span>lambda</span> obj: logger.<span>error</span><span>&#40;</span><span>'Test Failure: '</span>+<span>repr</span><span>&#40;</span>obj<span>&#41;</span><span>&#41;</span>,\n <span>&#125;</span>\n&nbsp;\n <span>class</span> default<span>&#40;</span><span>object</span><span>&#41;</span>:\n <span>def</span> <span>__init__</span><span>&#40;</span><span>self</span>, eName<span>&#41;</span>: <span>self</span>.<span>eName</span> = eName\n <span>def</span> <span>__call__</span><span>&#40;</span><span>self</span>, obj<span>&#41;</span>: logger.<span>info</span><span>&#40;</span><span>self</span>.<span>eName</span>+<span>' :: '</span>+<span>repr</span><span>&#40;</span>obj<span>&#41;</span><span>&#41;</span>\n&nbsp;\n <span>def</span> <span>__call__</span><span>&#40;</span><span>self</span>, eName, obj<span>&#41;</span>:\n <span>if</span> <span>self</span>.<span>cases</span>.<span>has_key</span><span>&#40;</span>eName<span>&#41;</span>:\n <span>self</span>.<span>cases</span><span>&#91;</span>eName<span>&#93;</span><span>&#40;</span>obj<span>&#41;</span>\n <span>else</span>:\n <span>self</span>.<span>cases</span><span>&#91;</span>eName<span>&#93;</span> = <span>self</span>.<span>default</span><span>&#40;</span>eName<span>&#41;</span>\n <span>self</span>.<span>cases</span><span>&#91;</span>eName<span>&#93;</span><span>&#40;</span>obj<span>&#41;</span>\n&nbsp;\nevents.<span>add_global_listener</span><span>&#40;</span>LoggerListener<span>&#40;</span><span>&#41;</span><span>&#41;</span>\n<span>logging</span>.<span>basicConfig</span><span>&#40;</span>level=<span>logging</span>.<span>ERROR</span><span>&#41;</span></pre></div></div>", "timestamp": "2008-10-28T07:10:37.000001", "title": "Introducing\u2026 jsbridge"}None{"body-raw": "<p>Ubiquity rocks! A month or so ago I completely removed the search box from Firefox and started solely using ubiquity for searches.</p>\n<p>The one thing that I really missed was a python doc search that I used to have for the search box. For a while I just used the awesome bar to perform google and history searches for python docs but that basically broke when Python 2.6 was released since all the old docs.python.org urls that google returns break because 2.6 has completely new docs provided by <a href=\"http://sphinx.pocoo.org/\">Sphinx</a>.</p>\n<p>So today I took a break from my &#8220;normal&#8221; work to write a ubiquity command to bring up the search page from docs.python.org for your input text. You can see the source <a title=\"python ubiquity command\" href=\"http://www.mikealrogers.com/wp-content/uploads/python-ubiquity.js\">here</a> and you should be able to install it by viewing this <a href=\"http://www.mikealrogers.com/archives/196\">blog post</a>.</p>\n<p>In the future I&#8217;d like to do better previews of the searches but I can&#8217;t seem to find any web API for searching docs.python.org.</p>", "timestamp": "2008-10-24T01:01:34.000004", "title": "Ubiquity command for docs.python.org"}None{"body-raw": "<p>Last week we finished up the Beta2 Release for MozMill.</p>\n<p>You can <a href=\"https://addons.mozilla.org/en-US/firefox/addon/9018\">install it from AMO</a>.</p>\n<p>We&#8217;ve been gathering feedback from our Beta1 release and pushed out another incremental beta release before the big push for MozMill 1.0 RC1.</p>\n<p>One important thing we did was improve the inspector workflow. It&#8217;s much smother clicking on an element and coming back to the Inspector. The inspector also gives you much more information now, including what document you should be passing the Elem you create and what method you should use to create a controller for the window you&#8217;re testing.</p>\n<p><a href=\"http://www.mikealrogers.com/wp-content/uploads/2008/10/mozmill.png\"><img class=\"alignnone size-full wp-image-185\" title=\"MozMill Beta2 Inspector\" src=\"http://www.mikealrogers.com/wp-content/uploads/2008/10/mozmill.png\" alt=\"\" width=\"530\" height=\"655\" /></a></p>\n<p>Lot&#8217;s of bug fixes, special thanks to Tony, Tracy and a big hug to Farhad for feature suggestions and filing bugs against beta1.</p>\n<p>This release does not include the new framework that hooks up to <a href=\"http://code.google.com/p/jsbridge\">jsbridge</a>, and therefor isn&#8217;t ready for full continuous integration, that&#8217;s now in trunk getting worked on for the RC1 release.</p>", "timestamp": "2008-10-13T19:52:35", "title": "MozMill Beta2 Released"}None{"body-raw": "<p>I didn&#8217;t think we&#8217;d be doing any notable windmill releases until 1.0. Boy was I wrong!</p>\n<h4>Seriously Faster</h4>\n<p>On Wednesday Adam messaged me and said that the windmill startup time was too slow. He was right, we&#8217;ve know about this for a while but hadn&#8217;t put a lot of serious thought in to how we could reduce it.<br />\nThe issue here was was that we have about 50 JavaScript files that need to get loaded for windmill to start.</p>\n<p>Enter windmill-compressor, a new url namespace we added that concats all the js windmill needs in to one file and minifies it. We do this dynamically when windmill starts up, because adding a &#8220;build&#8221; step would just be too&#8230;.. Java.</p>\n<p>That reduced the startup time from 5-10 seconds to around 2 seconds. But that wasn&#8217;t good enough. We saw that most of that startup time was blocking waiting for the compressor to finish, so I threaded it when we start the windmill service and it does the compression while we wait for the browser to start up.</p>\n<p>In all, windmill startup times are about 10x faster than 0.9!</p>\n<p>Adam also decided to make our page load wait code a bit more aggressive which made not only startup times faster but all of our tests!</p>\n<h4>Native JavaScript Test Framework</h4>\n<p>We tied up the loose ends on the JavaScript testing framework and it can now shutdown all of windmill in it&#8217;s own teardown, hello continuous integration for native JavaScript tests <img src=\"http://www.mikealrogers.com/wp-includes/images/smilies/icon_smile.gif\" alt=\":)\" class=\"wp-smiley\" /> </p>\n<p>This was the last thing holding us back from promoting this along side the Python test authoring library.</p>\n<h4>We Love Firebug</h4>\n<p>In 0.9 we introduced Firebug Lite integration for windmill on all browsers. But when you&#8217;re using Firefox you probably still want to use the full Firebug extension, which is easy enough to integrate since we use <a href=\"http://code.google.com/p/mozrunner\">mozrunner</a> for Firefox launching.</p>\n<p>Windmill now has a &#8220;firebug&#8221; command line argument that installs the full Firebug<br />\nextension when launching Firefox.</p>", "timestamp": "2008-10-13T17:51:27", "title": "Windmill 0.9.1 Released"}None{"body-raw": "<p>It&#8217;s no secret that shortly after I started at Mozilla I began working on an ambitious automation project. The project, called <a href=\"http://code.google.com/p/mozmill/\">MozMill</a>, is a tool that can be used for full UI automation of all Mozilla applications. In time this means not just Firefox but Thunderbird, Flock, Songbird, etc.</p>\n<p>We hit a major milestone last week when I finished implementation of the &#8220;Lookup&#8221; object, which uses a custom expression syntax that can define lookup for any element, even anonymous elements created by XBL that aren&#8217;t in the DOM. We also made some crucial additions to the Inspector UI;\u00a0 generation of expressions for the new Lookup object, better XPath, validation for all the expressions the inspector generates, and enhanced fallback logic. After about an hour of testing I couldn&#8217;t find a single element the Inspector couldn&#8217;t generate an expression for testing, which means we can simulate all events on all elements in any Mozilla application.</p>\n<p>Late last week we finally pushed our Beta release, and now the extension is up on <a href=\"https://addons.mozilla.org/en-US/firefox/addon/9018\">AMO and ready for anyone interested to install and start poking around.</a></p>\n<p>Clint has also written some great documentation; a <a href=\"https://wiki.mozilla.org/QA/TDAI/Gristmill/Mozmill_Tutorial\">great tutorial</a> and a fairly complete <a href=\"https://wiki.mozilla.org/QA/TDAI/Gristmill/Gristmill_API\">API reference</a>.</p>", "timestamp": "2008-09-29T04:35:34", "title": "MozMill Beta Released"}None{"body-raw": "<p>I&#8217;ve been a bad open source developer. I&#8217;ve had some really useful code sitting on my laptop for nearly 8 months now without publishing it. It&#8217;s a pretty simple mako plugin for django that makes using mako templates as simple and integrated as django&#8217;s regular template system.</p>\n<p>A week or so ago I finally got off my ass and put it up, but it took me until today to write proper documentation.</p>\n<p>The google code project is here, <a href=\"http://code.google.com/p/django-mako/\">http://code.google.com/p/django-mako/</a> .</p>\n<p>The documentation is here, <a href=\"http://code.google.com/p/django-mako/wiki/Usage\">http://code.google.com/p/django-mako/wiki/Usage</a> .</p>\n<p>Basically all you need to do is enable the middleware and all the Mako lookup stuff is handled for you and you can use new shortcut functions that mimic django&#8217;s regular <em>render_to_string</em> and <em>render_to_response</em> functions.</p>", "timestamp": "2008-09-28T21:57:59.000006", "title": "Introducing\u2026 django-mako"}None{"body-raw": "<p>During OSCON this year I attended <a href=\"http://jan.prima.de/\">Jan Lehnardt</a>&#8217;s talk on CouchDB. Somewhere in the middle of the talk I realized how much time I spend &#8220;dealing&#8221; with RDBMS and what a pain in the ass it is.</p>\n<p>That weekend, in between OSCON and Mozilla Summit, I started playing with CouchDB and totally fell in love. Certainly my favorite part of CouchDB is that I no longer feel like I need huge abstractions between me and the datastore. The datastore is simple enough to get your head around and it comes with a beautiful web interface and it makes me feel like I don&#8217;t need a heavy duty ORM that handles <strong>everything</strong> for me, I can have a more intimate relationship with my datastore.</p>\n<p>At some point I decided to seek out the Python library for interfacing with CouchDB, <a href=\"http://code.google.com/p/couchdb-python\">couchdb-python</a>, and wasn&#8217;t too pleased. It&#8217;s a big library and a lot of great work was put in to it, but it just wasn&#8217;t what I wanted at all.</p>\n<p>It feels like an ORM for RDBMS in that it does a lot of work to be a complete abstraction between you and CouchDB, which I just don&#8217;t want. The &#8220;schema&#8221; stuff, which is it&#8217;s mapper classes, feels a <strong>lot</strong> like RDBMS ORM. One of the great things about CouchDB is that there is no &#8220;schema&#8221; and that all your documents can fully mutate. This is how I want to define most of my &#8220;models&#8221;.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>class</span> User<span>&#40;</span>Model<span>&#41;</span>: <span>pass</span></pre></div></div>\n\n<p>So on the plane to Mozilla Summit I wrote a CouchDB library and spent free minutes here and there tweaking it. It&#8217;s incredibly small, about 243 lines with whitespace and comments, which is a testament to how much easier a REST API is to program for than SQL. You can create &#8220;Restrictions&#8221; which can do type checking and other validation before an attribute is set for a given property, and you can also use a Restriction to define custom marshalling before it hits the JSON parser. But all Models are fully mutatable and no validation is done at read time from the datastore, this way the ORM won&#8217;t ever get in your way as you change you data definitions over time in your application.</p>\n<p>The whole thing is hosted on Google Code at <a href=\"http://code.google.com/p/pouch/\">http://code.google.com/p/pouch/</a> .</p>\n<p>The docs right now are short and sweet <a href=\"http://code.google.com/p/pouch/wiki/Usage\">http://code.google.com/p/pouch/wiki/Usage</a> .</p>\n<p>There are some features I&#8217;d like to add, it currently uses httplib and I&#8217;d like the option of using httplib2 so that you could do caching pretty seamlessly. Any other features or patches are welcome. I&#8217;ll be pushing it to the cheeseshop later today when I get a chance. Here&#8217;s a taste;</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>import</span> pouch\n&nbsp;\npouch.<span>set_globals</span><span>&#40;</span><span>'http://127.0.0.1:5984'</span>, <span>'test'</span><span>&#41;</span>\n&nbsp;\n<span>class</span> TestModel<span>&#40;</span>pouch.<span>Model</span><span>&#41;</span>: <span>pass</span>\n&nbsp;\n<span>class</span> TestModelTwo<span>&#40;</span>pouch.<span>Model</span><span>&#41;</span>:\n unicode_test = pouch.<span>Unicode</span><span>&#40;</span><span>&#41;</span>\n int_test = pouch.<span>Int</span><span>&#40;</span><span>&#41;</span>\n float_test = pouch.<span>Float</span><span>&#40;</span><span>&#41;</span>\n list_test = pouch.<span>List</span><span>&#40;</span><span>&#41;</span>\n dict_test = pouch.<span>Dict</span><span>&#40;</span><span>&#41;</span>\n bool_test = pouch.<span>Bool</span><span>&#40;</span><span>&#41;</span>\n&nbsp;\n<span>test</span> = TestModel<span>&#40;</span>anything=<span>&quot;yes&quot;</span><span>&#41;</span>\n<span>test</span>.<span>another</span> = <span>&quot;ok&quot;</span>\n<span>test</span>.<span>save</span><span>&#40;</span><span>&#41;</span>\n&nbsp;\n<span>test</span> == TestModel.<span>get</span><span>&#40;</span><span>test</span>.<span>id</span><span>&#41;</span>\n&nbsp;\nresult = pouch.<span>GLOBAL_DB</span>.<span>views</span>.<span>company</span>.<span>all</span><span>&#40;</span><span>&#41;</span> <span># Retrieves the response for view I have named company.</span></pre></div></div>", "timestamp": "2008-09-19T18:29:35.000004", "title": "Yet Another CouchDB Library"}None{"body-raw": "<p>I never thought this would be the kind of blog that talks about politics too much or posts funny videos, but this must be shared.</p>\n<p></p>", "timestamp": "2008-09-16T17:21:37.000001", "title": "A bad Disney film"}None{"body-raw": "<p>Last Wednesday Adam and I had our work laptops stolen out of the back of my car. It sucked, and I was stupid about information security so all my data was open to whomever decided to steal it.</p>\n<p>For a variety of reasons I decided to buy a MacBook Air out of pocket, which I intend to do all my work on. I shelled out the extra money for the SSD drive after looking at the read speed numbers.</p>\n<p><a href=\"http://www.flickr.com/photos/sammich/2203244198/\"><img src=\"http://farm3.static.flickr.com/2144/2203244198_dbbb871a70.jpg\" alt=\"MacBookAir\" /></a></p>\n<p>After a few days I&#8217;ve got everything up and running, and all the files I need restored from a TimeMachine backup of my old laptop. I have to say, this computer is fast enough to do the vast majority of tasks most people do, including developers.</p>\n<p>Even though I love this machine and am perfectly able to get everything I need done, I do think there are some work situations in which you just cannot use this machine on a daily basis.</p>\n<ul>\n<li>You work on a large compiled application</li>\n<li>You write Java</li>\n<li>You spend a sizable portion of your time in VMWare</li>\n</ul>\n<p>The write speeds are pretty slow, and it maxes out at the OOTB 2GB of memory. BUT, the read speeds are astonishing. In fact I&#8217;m finding most of what I do on this laptop to be <strong>FASTER</strong> than my MacBook Pro.</p>\n<p>You read from your drive a lot more than you write to it, and seeing 18x improvements in read performance has some stunning consequences. Firefox is noticeably more responsive, bootup times are really fast, Mail.app is usable again, and switching applications is instantaneous.</p>\n<p>Not to mention, this machine is BEAUTIFUL. I never thought I&#8217;d be staring over at a MacBook Pro and thinking it looked &#8220;dated&#8221;. I really like this keyboard better than the MBP, I know it&#8217;s the same keyboard that&#8217;s been on the Macbook for a while but I&#8217;m happy to finally have one in my hands, it&#8217;s a big improvement.</p>\n<p><a href=\"http://www.flickr.com/photos/randomix/2517524833/\"><img src=\"http://farm3.static.flickr.com/2036/2517524833_2136dcc3e0.jpg\" alt=\"MacBookAir\" /></a></p>", "timestamp": "2008-09-13T22:25:43.000005", "title": "You too can use a MacBook Air"}None{"body-raw": "<p>Everyone knows how awesome <a href=\"http://getfirebug.com/\">Firebug</a> is. But for those times you have the unfortunate task of debugging in a browser that isn&#8217;t Firefox the Firebug team recently put out a new release of <a href=\"http://getfirebug.com/lite.html\">Firebug Lite</a>.</p>\n<p>For some time now we&#8217;ve always had a shell in Windmill for debugging but it was never as nice as the Firebug shell and maintaining that code was kind of a pain. In the <a href=\"http://www.getwindmill.com/archives/210\">recent 0.8.2</a> release of Windmill we dropped our old shell code and fully integrated Firebug Lite so that whenever you need to debug a test in any browser you can open Firebug Lite in the target application by clicking a single link in the Windmill IDE.</p>\n<p><img class=\"size-full wp-image-85 aligncenter\" title=\"windmillide1\" src=\"http://www.mikealrogers.com/wp-content/uploads/2008/09/windmillide1.png\" alt=\"\" /></p>\n<p><img class=\"size-full wp-image-86 aligncenter\" title=\"windmillfirebug2\" src=\"http://www.mikealrogers.com/wp-content/uploads/2008/09/windmillfirebug2.png\" alt=\"\" width=\"539\" height=\"470\" /></p>\n<p>\n<p>I can&#8217;t even begin to explain how much easier this is going to make writing and debugging tests in Windmill.</p>", "timestamp": "2008-09-09T05:12:29.000001", "title": "Firebug Lite in Windmill"}None{"body-raw": "<p>I had the pleasure of attending the very first DjangoCon this last weekend.</p>\n<p>I&#8217;ve attended a lot of conferences; big conferences, small conferences, very targetted conferences and very broad conferences. I think DjangoCon may have been the best conference I&#8217;ve ever been to.</p>\n<p>Over the years what I&#8217;ve learned to truly value about a conference is; meeting with people in the community, learning and understanding things I care about that would be harder to learn from reading than listening to a speaker, and just generally having a good time. DjangoCon was fantastic on all fronts. Being so targeted (people who use Django) there weren&#8217;t many talks that I didn&#8217;t care about and the people speaking were in all cases the best person to be speaking about a particular topic. The Django community is my favorite open source community, beating out the larger Python community by a small margin. Everyone is nice, helpful, and rarely suffer from even a marginal amount of smugness. Add food, decent wifi, and Cal&#8217;s talk &#8220;Why I hate Django&#8221; and you definitely cover the &#8220;having a good time&#8221; bit.</p>\n<h3>AppEngine</h3>\n<p>I messed with AppEngine for a couple weeks when it was first released. There were some serious rough edges that I decided I couldn&#8217;t deal with and I really didn&#8217;t completely get my head around the datastore.</p>\n<p><a href=\"http://www.flickr.com/photos/muffinresearch/2838298294/\"><img src=\"http://farm4.static.flickr.com/3130/2838298294_8db6dc6b16.jpg\" alt=\"Guido on AppEngine\" /></a></p>\n<p>Seeing Guido&#8217;s talk I noticed that those rough edges have been smoothed out and the development environment seems nicer, not to mention the documentation seems to have significantly improved. I&#8217;ve also been doing a lot of CouchDB work lately so I&#8217;ve internalized the &#8220;Document Store&#8221; concept and once I saw the Expando class provided by AppEngine I felt like I was now in a place where I can really understand Google&#8217;s datastore. It&#8217;s also not documented very well but Google&#8217;s datastore supports some geo data, which has always been a concern of mine putting too many eggs in the CouchDB basket right now. Add the fact that I absolutely hate managing infrastructure and I made a quick decision to invest once again in AppEngine or an upcoming project.</p>\n<h3>Why I Hate Django</h3>\n<p>I don&#8217;t think anyone will disagree that the highlight of Day One was Cal Henderson talk &#8220;Why I Hate Django&#8221;, he was absolutely hilarious. The video will be up eventually and I highly suggest everyone watch because it&#8217;s just too damn entertaining. I pulled a series of CC pictures from flickr in the meantime that illustrate the humor of the talk.</p>\n<p><a href=\"http://www.flickr.com/photos/muffinresearch/2837507027/\"><img src=\"http://farm4.static.flickr.com/3054/2837507027_a18521bd1d.jpg?v=0\" alt=\"Cal Hates Django\" /></a></p>\n<p><a href=\"http://www.flickr.com/photos/muffinresearch/2837504939/\"><img src=\"http://farm4.static.flickr.com/3157/2837504939_dca1ded576.jpg?v=0\" alt=\"Cal Hates Django\" /></a></p>\n<p><a href=\"http://www.flickr.com/photos/muffinresearch/2838339086/\"><img src=\"http://farm4.static.flickr.com/3151/2838339086_5a25a76ed5.jpg?v=0\" alt=\"Cal Hates Django\" /></a></p>\n<p><a href=\"http://www.flickr.com/photos/muffinresearch/2837507379/\"><img src=\"http://farm4.static.flickr.com/3167/2837507379_11a1b244d6.jpg?v=0\" alt=\"Cal Hates Django\" /></a></p>\n<p><a href=\"http://www.flickr.com/photos/muffinresearch/2837504033/\"><img src=\"http://farm4.static.flickr.com/3177/2837504033_2c6226188b.jpg?v=0\" alt=\"Cal Hates Django\" /></a></p>\n<p><a href=\"http://www.flickr.com/photos/muffinresearch/2838342286/\"><img src=\"http://farm4.static.flickr.com/3205/2838342286_d197933757.jpg?v=0\" alt=\"Cal Hates Django\" /></a></p>\n<p><a href=\"http://www.flickr.com/photos/muffinresearch/2837506505/\"><img src=\"http://farm4.static.flickr.com/3041/2837506505_567f91f368.jpg?v=0\" alt=\"Cal Hates Django\" /></a></p>\n<h3>Live Testing</h3>\n<p>Something like two years ago I wrote a patch to add live server support to the Django Test Framework (based on unittest). That patch fell out of sync with trunk and on the floor at some point. Eventually an intern at Disqus came along and got it working again and made some really nice improvements.</p>\n<p>Although the patch didn&#8217;t make it in to Django 1.0 I&#8217;m told it should land soon and will be in 3.1, but Disqus has been running with it all summer, using it for some Selenium tests. Well I couldn&#8217;t stand idle while Selenium test were running with Django and Windmill tests weren&#8217;t so I put my head down for about an hour during one of the talks and committed Django support to Windmill trunk. I ported the current patch for live server support in Django&#8217;s Trac so that it dynamically adds what is needed to Django and you can use this with Django 1.0 unmodified, and created a TestCase class that will launch your Windmill tests from within the normal Django <em>python mange.py test</em> runner. I wrote up a bit more about this <a href=\"http://groups.google.com/group/windmill-dev/browse_thread/thread/85f23d2a0d4e99\">in a post to the windmill-dev list.</a></p>", "timestamp": "2008-09-08T19:12:20", "title": "DjangoCon 2008"}None{"body-raw": "<p><a href=\"http://adamchristian.com/\">Adam</a> wrote a <a href=\"http://www.getwindmill.com/archives/207\">great post</a> recently on some code he wrote that outputs his test results in an xml format that <a href=\"https://hudson.dev.java.net/\">Hudson</a> can digest. It serves as an example of a fairly underutilized feature in <a href=\"http://functest.pythonesque.org/\">functest</a> for <a href=\"http://functest.pythonesque.org/wiki/FunctestReporting\">reporting</a>. It&#8217;s incredibly simple and powerful, you add a simple class to the highest level <em>__init__.py</em> with your report code and it will be called when all the tests have finished.</p>\n<p>Ideally you want to checkin your reporting mechanism with the source for all your tests but only run the reporter when it runs in continuous integration. Another functest feature is that any unrecognized command line <em>=</em> arguments are stuffed in to dictionary at <em>functest.registry</em>, and there is code in the windmill command line that will do the same.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"shell\">$ windmill shell report=true [14:15]\nreport is not a windmill argument. Sticking in functest registry.\n&nbsp;\nIn [1]: import functest\nIn [2]: functest.registry\nOut[2]: {'report': 'true'}</pre></div></div>\n\n<p>You can use this in your Report class to decide when you should actually report, you can even do different types of reporting based on what you pass. I wrote an example by refactoring Adam&#8217;s earlier Hudson example, I&#8217;ve also sped up some of the code and use ElementTree to write the xml instead of writing the string output by hand.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><pre class=\"python\"><span>import</span> functest\n<span>from</span> functest <span>import</span> reports\n<span>from</span> <span>xml</span>.<span>etree</span> <span>import</span> ElementTree\n&nbsp;\n<span>class</span> JUnitReporter<span>&#40;</span>reports.<span>FunctestReportInterface</span><span>&#41;</span>:\n <span>def</span> summary<span>&#40;</span><span>self</span>, test_list, totals_dict, stdout_capture<span>&#41;</span>:\n <span>if</span> functest.<span>registry</span>.<span>get</span><span>&#40;</span><span>'report'</span>, <span>False</span><span>&#41;</span>:\n total_sec = <span>reduce</span><span>&#40;</span><span>lambda</span> x, y: <span>&#40;</span>y.<span>endtime</span> - y.<span>starttime</span><span>&#41;</span>.<span>seconds</span> + x, test_list, <span>0</span><span>&#41;</span>\n e = ElementTree.<span>Element</span><span>&#40;</span><span>'testsuite'</span><span>&#41;</span>\n e.<span>attrib</span><span>&#91;</span><span>'errors'</span><span>&#93;</span> = e.<span>attrib</span><span>&#91;</span><span>'failures'</span><span>&#93;</span> = <span>str</span><span>&#40;</span>totals_dict<span>&#91;</span><span>'fail'</span><span>&#93;</span><span>&#41;</span>\n e.<span>attrib</span><span>&#91;</span><span>'tests'</span><span>&#93;</span> = <span>str</span><span>&#40;</span><span>len</span><span>&#40;</span>test_list<span>&#41;</span><span>&#41;</span>\n e.<span>attrib</span><span>&#91;</span><span>'name'</span><span>&#93;</span> = <span>'windmill.functional'</span>\n e.<span>attrib</span><span>&#91;</span><span>'time'</span><span>&#93;</span> = <span>str</span><span>&#40;</span>total_sec<span>&#41;</span>\n <span>for</span> entry <span>in</span> test_list:\n t = entry.<span>endtime</span> - entry.<span>starttime</span>\n <span>test</span> = ElementTree.<span>Element</span><span>&#40;</span><span>'testcase'</span><span>&#41;</span>\n <span>test</span>.<span>attrib</span><span>&#91;</span><span>'classname'</span><span>&#93;</span> = <span>test</span>.<span>attrib</span><span>&#91;</span><span>'name'</span><span>&#93;</span> = entry.__name__\n <span>test</span>.<span>attrib</span><span>&#91;</span><span>'time'</span><span>&#93;</span> = <span>str</span><span>&#40;</span>t.<span>seconds</span><span>&#41;</span>+<span>'.'</span>+<span>str</span><span>&#40;</span>t.<span>microseconds</span><span>&#41;</span>\n <span>if</span> entry.<span>result</span> <span>is</span> <span>not</span> <span>True</span>:\n failure = ElementTree.<span>Element</span><span>&#40;</span><span>'failure'</span><span>&#41;</span>\n failure.<span>attrib</span><span>&#91;</span><span>'type'</span><span>&#93;</span> = entry.<span>tb</span><span>&#91;</span>-<span>1</span><span>&#93;</span>.<span>split</span><span>&#40;</span><span>':'</span><span>&#41;</span><span>&#91;</span><span>0</span><span>&#93;</span>\n failure.<span>text</span> = <span>'<span>\\n</span>'</span>.<span>join</span><span>&#40;</span>entry.<span>tb</span><span>&#41;</span>\n <span>test</span>.<span>append</span><span>&#40;</span>failure<span>&#41;</span>\n e.<span>append</span><span>&#40;</span><span>test</span><span>&#41;</span>\n&nbsp;\n <span>if</span> <span>len</span><span>&#40;</span>stdout_capture<span>&#41;</span>:\n <span># ElementTree doesn't support CDATA so we need to hack it a little</span>\n replace = <span>'#$!#$!replace#@!$'</span>\n sysout = ElementTree.<span>Element</span><span>&#40;</span><span>'system-out'</span><span>&#41;</span>\n sysout.<span>text</span> = replace\n e.<span>append</span><span>&#40;</span>sysout<span>&#41;</span>\n outs = ElementTree.<span>tostring</span><span>&#40;</span>e<span>&#41;</span>.<span>replace</span><span>&#40;</span>replace, <span>'&lt;!--[CDATA['</span>+stdout_capture+<span>']]--&gt;'</span><span>&#41;</span>\n <span>else</span>:\n outs = ElementTree.<span>tostring</span><span>&#40;</span>e<span>&#41;</span>\n&nbsp;\n f = <span>open</span><span>&#40;</span><span>'continuous_test.log'</span>,<span>'w'</span><span>&#41;</span>\n f.<span>write</span><span>&#40;</span>outs<span>&#41;</span> <span>;</span> f.<span>close</span><span>&#40;</span><span>&#41;</span>\n&nbsp;\nreports.<span>register_reporter</span><span>&#40;</span>JUnitReporter<span>&#40;</span><span>&#41;</span><span>&#41;</span></pre></div></div>", "timestamp": "2008-09-06T22:03:05.000005", "title": "Windmill Reporting"}None{"body-raw": "<p>Although the task of starting and stopping a given Mozilla Applications is taken on by all Mozilla tools there is no shared code for accomplishing this task. Historically most Mozilla tools have just been part of the main repository and act as &#8220;scripts&#8221; instead of more independent Python libraries and/or Extensions. This meant that shared code could only really be accomplished through cut and paste.</p>\n<p>The task of just starting and stopping the Mozilla Applications is harder than it would seem, particularly when it comes to stopping. There&#8217;s also a bunch of other things you wanna do to Mozilla Applications when you&#8217;re launching them; set preferences, install plugins, build new clean profiles and use them, add command line arguments to the launch, etc.</p>\n<p>mozrunner is a Python library that is independent of any particular Mozilla application source repository and is hosted at <a href=\"http://code.google.com/p/mozrunner\">http://code.google.com/p/mozrunner</a> . The library takes on the task of starting, configuring and stopping Mozilla Applications (only tested against Firefox right now but it <em>should</em> work with Thunderbird, Songbird, etc. and patches are welcome). We used this library when developing the new Gristmill suite of test automation tools and it&#8217;s been wonderful to work with.</p>\n<p>The current documentation is over on the google code wiki; <a href=\"http://code.google.com/p/mozrunner/wiki/UsingMozRunner\">http://code.google.com/p/mozrunner/wiki/UsingMozRunner</a> , there is a lot more that you can do with mozrunner that still isn&#8217;t up in the documentation and I plan on just adding it as people ask me how to do things.</p>\n<p>If you have Python and <a href=\"http://peak.telecommunity.com/DevCenter/setuptools#installing-setuptools\">setuptools</a> installed you can just install it via easy_install.</p>\n\n<div class=\"wp_syntax\"><div class=\"code\"><