Thursday, September 15, 2011

Simple Nosy Script: Personal Continuous Integration for TDD

I recently cleaned up and resurrected my old nosy script.  These days there are a few alternatives on PyPI as well though I prefer mine.  The whole concept of nosy is simply to rerun the tests whenever the code changes.  Personally, I find a script like this is really helpful for maintaining flow while doing test driven development.

What I like about this nosy script is that it allows me to basically just say "run this nosetests / trial command every time the code changes" and nothing else.  There's no config file to setup or any tool specific arguments.  You just need to know how to use your test runner.

Here's the code in case anyone is interested: https://gist.github.com/1220683

Oh, and despite the name I've used it successfully to work on twisted projects with trial.  I'm also willing to bet that it would work just fine with py.test.

Edit:  The polling loop with a time.sleep(1) is eating away at me now that I've posted this.  I'm thinking that the only way to live with myself is to replace that with listening for real filesystem events ala inotify... So do ease my conscience I'll see about doing a followup post to show what the script would look like with filesystem events instead of the polling loop..

Tuesday, September 13, 2011

Git Pre-commit Hook For Python now with extra Python!

After reading a post by Bryce Verdier, and inspired by comments that suggested the Python version of said hook script would not be as nice as the bash version I decided to hack up a quick python version of the same script using pyflakes instead of pylint.

#!/usr/bin/env python
#-*- mode: python -*-

from subprocess import Popen, PIPE
import sys

syntax_checker = "pyflakes"

def run(command):
    p = Popen(command.split(), stdout=PIPE, stderr=PIPE)
    p.wait()
    return p.returncode, p.stdout.read().strip().split(), p.stderr.read()

_, files_modified, _= run("git diff-index --name-only HEAD")

for fname in files_modified:
    if fname.endswith(".py"):
        print >>sys.stderr, "Checking syntax on %s: ... "%(fname,),
        exit_code, _, errors = run("%s %s"%(syntax_checker, fname))
        if exit_code != 0:
            print >>sys.stderr, "\rChecking syntax on %s: FAILED! \n%s"%(fname, errors)
            sys.exit(exit_code)
        else:
            print >>sys.stderr, "\rChecking syntax on %s: OK!"%(fname,)

You can download / fork this here if would like to give it a try: https://gist.github.com/1214061 And of course, if you're like me and you have no idea what to do with this script you can just do the following:

cp pre-commit.py YourGitProject/.git/hooks/pre-commit
chmod +x YourGitProject/.git/hooks/pre-commit

It's also worth noting that this version is currently really strict.  ANY warnings will cause your commit to fail.  Of course, replacing pyflakes with pylint again is a simple modification of the syntax_checker variable in the above script.