<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Jeff Balogh
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));

var pageTracker = _gat._getTracker("UA-6130975-2");
pageTracker._trackPageview();
</description><title>jbalogh</title><generator>Tumblr (3.0; @jeffbalogh)</generator><link>http://blog.jeffbalogh.org/</link><item><title>Highlights from DjangoCon 2009</title><description>&lt;p&gt;Long (long!) overdue, here’s a bunch of links that point to the good things I
learned at djangocon.&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://immike.net/files/restful_ponies.pdf"&gt;Restful Ponies&lt;/a&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Started with a basic REST overview, gets interesting when it shows how you can
easily expose resources using &lt;a href="http://bitbucket.org/jespern/django-piston"&gt;Piston&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://code.welldev.org/django-roa/src/"&gt;django-roa&lt;/a&gt; builds on Piston to give models a basic REST API for free&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://github.com/sixapart/remoteobjects/"&gt;remoteobjects&lt;/a&gt; is an object-restational mapper that maps objects to REST
apis on the web.  It’s really cool and I’m playing with it for the new
Bugzilla rest view.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href="http://oebfare.com/files/DeployingDjangoDC2009.pdf"&gt;Deploying Django&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Talks about how they’re doing “repeatable, automated, isolated” deployments
using Python tools.  Don’t you wish we were rocking this on AMO?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;virtualenv and pip to keep the deployment environment isolated&lt;/li&gt;
&lt;li&gt;fabric to script vcs checkout and installation&lt;/li&gt;
&lt;li&gt;using lightweight tags in git to mark deployment versions&lt;/li&gt;
&lt;li&gt;up &lt;em&gt;and&lt;/em&gt; down migrations with &lt;a href="http://south.aeracode.org/"&gt;South&lt;/a&gt; to stay safe&lt;/li&gt;
&lt;li&gt;mod_wsgi daemon mode is preferred, fastcgi is cool too&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href="http://immike.net/files/scaling_django.pdf"&gt;Scaling Django&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Pownce was serving hundreds of request/sec, thousands of db ops/sec, it can be
done.  It’s simple to do automatic caching and invalidation when your queries
are going through the ORM, Django’s signals decouple the invalidation process
from your update code.  Using multiple databases with Django is not
straightforward, but it’s getting easier with an SoC project that’s ready to
merged in.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://pypi.python.org/pypi/sqlparse/0.1.1"&gt;sqlparse&lt;/a&gt; pretty prints SQL queries&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href="http://www.slideshare.net/err/the-realtime-web-and-other-buzzwords"&gt;The Realtime Web&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Showed how they created an IRC client in the browser over comet with Django on
the backend.  The browser and the app keep “persistent” connections to an
&lt;a href="http://orbited.org/"&gt;orbited&lt;/a&gt; server that handles all the messy details so the app can pretend
it’s really connected directly to the browser.&lt;/p&gt;

&lt;p&gt;This coincided with the release of FriendFeed’s &lt;a href="http://www.tornadoweb.org/"&gt;Tornado&lt;/a&gt; web server, which
led to an interesting focus on async during the conference.&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://media.eflorenzano.com/dropbox/UsingDjangoInNonStandardWays.pdf"&gt;Using Django in Non-Standard Ways&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Covers a lot of little hurdles that people might consider show-stoppers when
using Django, how to overcome them.&lt;/p&gt;

&lt;p&gt;WSGI middleware is fun:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;repoze.bitblt: automatically scales images&lt;/li&gt;
&lt;li&gt;repoze.squeeze: Merges JS/CSS automatically based on statistical analysis&lt;/li&gt;
&lt;li&gt;repoze.profile:  Aggregates Python profiling data across all requests, and
provides an html frontend for viewing the data&lt;/li&gt;
&lt;li&gt;repoze.slicer: extract/filter pieces of an html response&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href="http://www.slideshare.net/pydanny/pinax-tutorial-090909"&gt;Pinax Tutorial&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Pinax tries to be a collection of reusable apps that work well together, but it
looks like you spend more time trying to configure things than actually making
useful apps.&lt;/p&gt;</description><link>http://blog.jeffbalogh.org/post/218433935</link><guid>http://blog.jeffbalogh.org/post/218433935</guid><pubDate>Tue, 20 Oct 2009 14:59:44 -0700</pubDate></item><item><title>The worst schema versioning system, ever?</title><description>&lt;p&gt;&lt;a href="https://github.com/jbalogh/schematic/tree"&gt;schematic&lt;/a&gt; talks to your database over stdin on the command line.  Thus,
it supports all DBMSs that have a command line interface and doesn’t
care what programming language you worship.  Win!&lt;/p&gt;

&lt;p&gt;It only looks for files in the same directory as itself so you should
put this script, settings.py, and all migrations in the same directory.&lt;/p&gt;

&lt;p&gt;Configuration is done in &lt;code&gt;settings.py&lt;/code&gt;, which should look something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# How to connect to the database
db = 'mysql --silent -p blam -D pow'
# The table where version info is stored.
table = 'schema_version'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It’s python so you can do whatever crazy things you want, and it’s a
separate file so you can keep local settings out of version control.&lt;/p&gt;

&lt;p&gt;Migrations are just sql in files whose names start with a number, like
&lt;code&gt;001-adding-awesome.sql&lt;/code&gt;.  They’re matched against &lt;code&gt;'^\d+'&lt;/code&gt; so you can
put zeros in front to keep ordering in &lt;code&gt;ls&lt;/code&gt; happy, and whatever you want
after the migration number, such as text describing the migration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jbalogh/schematic/tree"&gt;schematic&lt;/a&gt; creates a table (named in settings.py) with one column, that
holds one row, which describes the current version of the database.  Any
migration file with a number greater than the current version will be
applied to the database and the version tracker will be upgraded.  The
migration and version bump are performed in a transaction.&lt;/p&gt;

&lt;p&gt;The version-tracking table will initially be set to 0, so the 0th
migration could be a script that creates all your tables (for
reference).  Migration numbers are not required to increase linearly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jbalogh/schematic/tree"&gt;schematic&lt;/a&gt; doesn’t pretend to be intelligent. Running migrations manually
without upgrading the version tracking will throw things off.&lt;/p&gt;

&lt;p&gt;Tested on sqlite any mysql.&lt;/p&gt;

&lt;p&gt;NOTE: any superfluous output, like column headers, will cause an error.
On mysql, this is fixed by using the &lt;code&gt;--silent&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;Things that might be nice: downgrades, running python files.&lt;/p&gt;</description><link>http://blog.jeffbalogh.org/post/112148568</link><guid>http://blog.jeffbalogh.org/post/112148568</guid><pubDate>Sat, 23 May 2009 20:24:25 -0700</pubDate></item><item><title>Introducing poboy</title><description>&lt;p&gt;I’d be surprised if &lt;a href="http://github.com/jbalogh/poboy/tree/master"&gt;poboy&lt;/a&gt; is useful to anyone I don’t work with, but I wrote a README, so that should be shared with the internet.&lt;/p&gt;

&lt;p&gt;Finds all the gettext calls that have an inline fallback and moves that fallback
into the messages.po file.  Thus, you can use &lt;code&gt;___('msgid', 'msgstr')&lt;/code&gt; when you’re
writing new code and use this script to clean up afterwards.&lt;/p&gt;

&lt;p&gt;poboy won’t edit any code files.  Instead, it prints out a unified diff that you
can check for correctness and send to patch.  I didn’t want to deal with
rewriting files safely.&lt;/p&gt;

&lt;h3&gt;How I use it&lt;/h3&gt;

&lt;p&gt;Find all the strings that have a fallback:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;poboy locale/en_US/LC_MESSAGES/messages.po --find
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Find the strings with a fallback that aren’t already in messages.po:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;poboy locale/en_US/LC_MESSAGES/messages.po -an
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That’s &lt;code&gt;-a&lt;/code&gt; for &lt;code&gt;--add&lt;/code&gt; (to the .po file) and &lt;code&gt;-n&lt;/code&gt; for &lt;code&gt;--dry_run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Show the strings that will be added and the cleanup patch:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;poboy locale/en_US/LC_MESSAGES/messages.po -n
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the fun one, add the strings to messages.po and generate a cleanup patch:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;poboy locale/en_US/LC_MESSAGES/messages.po &gt; poboy.patch
&lt;/code&gt;&lt;/pre&gt;</description><link>http://blog.jeffbalogh.org/post/108035503</link><guid>http://blog.jeffbalogh.org/post/108035503</guid><pubDate>Thu, 14 May 2009 21:55:31 -0700</pubDate></item><item><title>pyquery: a jquery-like library for python</title><description>&lt;p&gt;&lt;a href="http://pyquery.org/"&gt;pyquery&lt;/a&gt; is a fantastic little library for dealing with XML and HTML documents.  It brings the power and ease of jQuery into Python, letting you deal with CSS selectors and functions instead of a clunky DOM.  I try to avoid dealing with XML as much as possible, but slinging around pyquery almost makes XML fun.&lt;/p&gt;

&lt;h3&gt;Building lxml&lt;/h3&gt;

&lt;p&gt;The hardest part of working with pyquery is getting it installed.  pyquery gets all of its XML power from &lt;a href="http://codespeak.net/lxml/"&gt;lxml&lt;/a&gt;, which has a reputation for being difficult.  &lt;a href="http://blog.ianbicking.org/2008/12/10/lxml-an-underappreciated-web-scraping-library/"&gt;Ian Bicking&lt;/a&gt; mentioned that lxml2.2 has become much easier to install by providing an option to compile the troublesome C libs as static libraries, which has avoided any problems for me.  All you need to do is define &lt;code&gt;STATIC_DEPS=true&lt;/code&gt; in the build environment:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;STATIC_DEPS=true pip install pyquery
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This has worked for me on OS X with &lt;code&gt;pip&lt;/code&gt;, &lt;code&gt;easy_install&lt;/code&gt;, &lt;code&gt;buildout&lt;/code&gt;, and probably anything else based on &lt;code&gt;distutils&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;Web Scraping&lt;/h3&gt;

&lt;p&gt;Web scraping is ridiculously easy with pyquery.  Grabbing a &lt;a href="http://www.pangloss.com/seidel/Shaker/"&gt;Shakespearean insult&lt;/a&gt; from the web is as simple as&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import pyquery

p = pyquery.PyQuery('http://www.pangloss.com/seidel/Shaker/')
insult = p('font').text()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finding the insult on that page is aided by the author’s semantic &lt;code&gt;font&lt;/code&gt; tag.&lt;/p&gt;

&lt;h3&gt;Testing&lt;/h3&gt;

&lt;p&gt;I like to make sure that my views are working correctly, another task in which I’m finding pyquery indispensable.  I’ve seen regexen used for the same task, but examining a real DOM is much more resilient than trying to pick out pieces by matching strings.  Testing views is especially useful when dealing with template systems like Django’s and Jinja’s which silently hide errors instead of raising exceptions.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;assert d('#stats').text() == '5 tests: +2 -3'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’ve noticed that testing the HTML in this manner has improved my semantic markup.  Pulling out and testing pieces of the page forces me to add meaningful ids and classes to the elements.&lt;/p&gt;

&lt;h3&gt;Bonus&lt;/h3&gt;

&lt;p&gt;For extra HTML goodness, the tests submit response pages to the &lt;a href="http://validator.w3.org/"&gt;w3c Validator&lt;/a&gt; using this &lt;a href="http://github.com/jbalogh/bosley/blob/f64cfeb739954311c36b357d657c227e6d9646a2/bosley/tests/multipart.py"&gt;multipart form encoder&lt;/a&gt;.  Then, of course, I use pyquery to make sure all is well.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;validator = post_multipart('validator.w3.org', '/check',
                           {'fragment': response.data})
assert pyquery.PyQuery(validator)('#congrats')
&lt;/code&gt;&lt;/pre&gt;</description><link>http://blog.jeffbalogh.org/post/89619207</link><guid>http://blog.jeffbalogh.org/post/89619207</guid><pubDate>Tue, 24 Mar 2009 23:35:04 -0700</pubDate><category>python</category><category>jquery</category><category>html</category><category>testing</category></item><item><title>Nose Test Runner for Django</title><description>&lt;p&gt;&lt;strong&gt;Update: you can now find django-nose on &lt;a href="http://pypi.python.org/pypi/django-nose"&gt;pypi&lt;/a&gt; and &lt;a href="http://github.com/jbalogh/django-nose"&gt;github&lt;/a&gt; with much better documentation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I am not a big fan of Python’s &lt;code&gt;unittest&lt;/code&gt; library.  The Java-inspired API and the difficulty of running tests are too much for me to deal with.  That’s why I love &lt;a href="http://www.somethingaboutorange.com/mrl/projects/nose/"&gt;nose&lt;/a&gt;: I can use regular &lt;code&gt;assert&lt;/code&gt;s (or the Pythonic helpers in &lt;code&gt;nose.tools&lt;/code&gt;) and running all my tests is as simple as calling &lt;code&gt;nosetests&lt;/code&gt; from the command line.  On top of that, nose also supports cool plugins like generating coverage reports and running tests interactively, test fixtures at any granularity level, and simple selection of tests to run, making me a happy tester.&lt;/p&gt;

&lt;p&gt;Which is why I wrote a custom &lt;a href="http://docs.djangoproject.com/en/dev/topics/testing/#defining-a-test-runner"&gt;test runner&lt;/a&gt; as soon as I started working on &lt;a href="http://basieproject.org"&gt;basie&lt;/a&gt;.  Django provides its own test runner framework, but it’s far less advanced than nose.&lt;/p&gt;

&lt;p&gt;I haven’t packaged it up for PyPI yet, but you can download &lt;a href="http://code.basieproject.org/trunk/apps/django_nose/nose_runner.py"&gt;nose_runner.py&lt;/a&gt; from our repository.  Here’s the documentation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
Django test runner that invokes nose.

Usage:
    ./manage.py test DJANGO_ARGS -- NOSE_ARGS

The 'test' argument, and any other args before '--', will not be passed
to nose, allowing django args and nose args to coexist.

You can use

    NOSE_ARGS = ['list', 'of', 'args']

in settings.py for arguments that you always want passed to nose.
&lt;/code&gt;&lt;/pre&gt;</description><link>http://blog.jeffbalogh.org/post/57653515</link><guid>http://blog.jeffbalogh.org/post/57653515</guid><pubDate>Sun, 02 Nov 2008 18:18:00 -0800</pubDate><category>testing</category><category>python</category></item></channel></rss>
