Below is the file 'viewmtn.py' from this revision. You can also download the file.

#!/usr/bin/env python

# Copyright (C) 2005 Grahame Bowland <grahame@angrygoats.net>
#
# This program is made available under the GNU GPL version 2.0 or
# greater. See the accompanying file COPYING for details.
#
# This program is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE.

import os, sys, urllib
from itertools import izip, chain, repeat
from urlparse import urljoin
import web
import mtn, handlers, links
from urls import common_urls, perdb_urls
from render import Renderer
import config

# purloined from: http://docs.python.org/lib/itertools-recipes.html
def grouper(n, iterable, padvalue=None):
    "grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
    return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)

class RequestContext(object):
    def __init__ (self, dbname, ops, renderer):
        self.dbname, self.ops, self.renderer = dbname, ops, renderer
        # make sure that any unread automate output is flushed away
        if not ops is None:
            ops.per_request()
        self.nodb_join = lambda path: urljoin(config.dynamic_uri_path, path)
        if self.dbname is None:
            self.perdb_join = self.nodb_join
        else:
            self.perdb_join = lambda path: urljoin(config.dynamic_uri_path, urllib.quote(self.dbname) + '/' + path)
        self.static_join = lambda path: urljoin(config.static_uri_path, path)

    def link (self, *args, **kwargs):
        kwargs['ctxt'] = self
        return links.link (*args, **kwargs)

    def render(self, *args, **kwargs):
        self.renderer.render (self, *args, **kwargs)

class RequestContextFactory(object):
    def __init__ (self):
        # has the user specified a dbfiles hash? if so, use it
        self.ops_instances = {}
        self.default = None
        self.renderer = Renderer()
        if hasattr (config, "dbfiles"):
            for name in config.dbfiles:
                self.ops_instances[name] = mtn.Operations([config.monotone, config.dbfiles[name]])
            if hasattr (config, "defaultdb"):
                self.default = config.defaultdb
        else:
            self.ops_instances[None] = mtn.Operations([config.monotone, config.dbfile])
            self.default = None

    def __getitem__(self, name):
        if name is None:
            ops = self.ops_instances.get (self.default, None)
        else:
            ops = self.ops_instances.get (name, None)
        if ops is None:
            return None
        else:
            return RequestContext(name, ops, self.renderer)

def runfcgi_apache(func):
    web.wsgi.runfcgi(func, None)

def per_request_wrapper(func, *args, **kwargs):
    return func(*args, **kwargs)

if __name__ == '__main__':
    if hasattr(config, "running_under_apache2") and config.running_under_apache2:
        web.wsgi.runwsgi = runfcgi_apache
    if hasattr(config, "debug") and config.debug:
        web.webapi.internalerror = web.debugerror

    def assemble_urls():
        fvars = {}
        urls = ()

        factory = RequestContextFactory()

        def per_db_closure (handler):
            class PerDBClosure(object):
                def GET (self, *args, **kwargs):
                    db, other_args = args[0], args[1:]
                    # due to regexp we use, db passed in will always have a trailing slash
                    if not db is None:
                        db = db[:-1]
                    ctxt = factory[db]
                    if ctxt is None:
                        return web.notfound()
                    return handler.GET (ctxt, *other_args, **kwargs)
            return PerDBClosure

        for url, fn in grouper (2, common_urls):
            url = r'^/' + url
            if hasattr(handlers, fn):
                fvars[fn] = getattr(handlers, fn)
                urls += (url, fn)
            else:
                print >>sys.stderr, "*** URL defined for non-existant handler %s: %s" % (fn, url)

        for url, fn in grouper (2, perdb_urls):
            if hasattr(handlers, fn):
                url = r'^/([A-Za-z]+/)?' + url
                urls += (url, fn)
                fvars[fn] = per_db_closure (getattr(handlers, fn)())
            else:
                print >>sys.stderr, "*** URL defined for non-existant handler %s: %s" % (fn, url)

        return urls, fvars

    urls, fvars = assemble_urls()
    func = lambda : per_request_wrapper(web.webpyfunc(urls, fvars=fvars))
    web.run(func, globals())

###
### vi:expandtab:sw=4:ts=4
###