Package: corduroy
project:http://samizdat.cc/corduroycode:http://github.com/samizdatco/corduroyAboutCorduroy provides a python-friendly wrapper around CouchDB’s HTTP-based API.
Behind the scenes it hooks into the asynchronous i/o routines from your choice
ofTornadoor theRequests&Geventmodules.Using corduroy you can query the database without blocking your server’s event
loop, making it ideal forCouchAppmicro-middleware
or scripted batch operations.UsageAs a real world(ish) example of working with Corduroy, consider this pair of
Tornado event handlers which update a url-specifed document then query a view.
The first uses explicit callbacks to resume execution after each response from
the database is received:db = Database('players')
class RankingsUpdater(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def post(self, player_id):
        self.new_score = int(self.request.body)
        db.get(player_id, callback=self.got_player)

    def got_player(doc, status):
        doc.score = self.new_score
        db.save(doc, callback=self.saved_player)

    def saved_player(conflicts, status):
        db.view('leaderboard/highscores',
                 callback=self.got_highscores)

    def got_highscores(rows, status):
        self.write(json.dumps(rows))
        self.finish()An alternative syntax is available (when using Tornado) through the use of the
@relax decorator. Instead of defining callbacks for each database operation,
the library can be called as part of a yield expression.Tornado’sgeneratormodule
will intercept these yields and provide a callback automatically. The result is
code that looks quite sequential but will still execute asyncronously:class RankingsUpdater(tornado.web.RequestHandler):
    @relax
    def post(self, player_id):
        # update this player's score
        doc = yield db.get(player_id)
        doc.score = int(self.request.body)
        yield db.save(doc)

        # return the new rankings
        highscores = yield db.view('leaderboard/highscores')
        self.write(json.dumps(highscores))
        self.finish()For a gentle introduction to Corduroy (and CouchDB in general), take a look at
theGuide. Documentation for all of Corduroy’s
module-level classes can be found in theReferencesection.InstallationAutomatic InstallationCorduroy can be found on PyPi and can be installed with your choice of pip or
easy_install.Manual InstallationDownloadcorduroy-0.9.0.tar.gz:tar xvzf corduroy-0.9.0.tar.gz
cd corduroy-0.9.0
python setup.py installDependenciesIf you’re writing a Tornado app, Corduroy can use its pure-python HTTP client
by installing with:pip install corduroy tornadoOr if you’d prefer the libcurl-based client (which supports pooling and other
niceties), use:pip install corduroy tornado pycurlIf pycurl complains (I’m looking at you, OS X), try:env ARCHFLAGS="-arch x86_64" pip install pycurlGevent users can install with:pip install corduroy requests geventThe library can also be used with plain-old blocking i/o:pip install corduroy requestsLicenseCorduroy is released under the BSD license. Use it freely and in good health.AcknowledgmentsCorduroy is derived from Christopher Lenz’s excellentcouchdb-pythonmodule and inherits much of its
API (and most of its test cases) from that codebase. It is also indebted to
Eric Naeseth’s mind-expandingSwirllibrary which first acquainted me with the idea of using generators to
simulate sequential code.