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, types from itertools import izip, chain, repeat from urlparse import urljoin import web import mtn, handlers, links, branchdiv 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, **kwargs): for k in kwargs: setattr(self, k, kwargs[k]) self.render_attrs = kwargs.keys() # make sure that any unread automate output is flushed away if not self.ops is None: self.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): for attr in self.render_attrs: kwargs[attr] = getattr(self, attr) self.renderer.render (self, *args, **kwargs) class RequestContextFactory(object): def __init__ (self): self.dbstore = { 'ops' : {}, 'branchdivs' : {}, 'dbdescr' : {}} self.db_summary = {} self.default = None # has the user specified a dbfiles hash? if so, use it if hasattr (config, "dbfiles"): # is dbfiles a function? if so, call it.. dbfiles = config.dbfiles if isinstance(dbfiles, types.FunctionType): dbfiles = dbfiles() # we should have something iterable now; if not, abort if not hasattr(dbfiles, "__iter__"): raise Exception("dbfiles defined incorrectly. It must be an interable (eg. tuple or list) or a function taking no arguments which returns an iterable.") for name, dbfile, description in grouper(3, dbfiles): self.add_to_store(name, ops=mtn.Operations([config.monotone, dbfile]), branchdivs=branchdiv.BranchDivisions(), dbdescr=description) self.db_summary[name] = description if hasattr (config, "defaultdb"): self.default = config.defaultdb have_multidb = True else: self.add_to_store(None, ops=mtn.Operations([config.monotone, config.dbfile]), branchdivs=branchdiv.BranchDivisions(), dbdescr="") self.default = None have_multidb = False self.renderer = Renderer(have_multidb=have_multidb) def add_to_store(self, name, **kwargs): for k in kwargs: self.dbstore[k][name] = kwargs[k] def get_from_store(self, k, name, default=None): return self.dbstore[k].get(name, default) def __getitem__(self, name): if name is None: name = self.default ops = self.get_from_store("ops", name) if ops is None: return None else: dbdescr = self.get_from_store("dbdescr", name) branchdivs = self.get_from_store("branchdivs", name) return RequestContext(dbname=name, ops=ops, dbdescr=dbdescr, branchdivs=branchdivs, renderer=self.renderer, db_summary=self.db_summary) def runfcgi_apache(func): web.wsgi.runfcgi(func, None) 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() web.run(urls, fvars) ### ### vi:expandtab:sw=4:ts=4 ###