Mercurial > hg > toolbox
diff toolbox/dispatcher.py @ 0:b0942f44413f
import from git://github.com/mozilla/toolbox.git
author | Jeff Hammel <k0scist@gmail.com> |
---|---|
date | Sun, 11 May 2014 09:15:35 -0700 |
parents | |
children | 394648c67478 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolbox/dispatcher.py Sun May 11 09:15:35 2014 -0700 @@ -0,0 +1,124 @@ +""" +request dispatcher WSGI app: +data persisting across requests should go here +""" + +import os + +from handlers import CreateProjectView +from handlers import DeleteProjectHandler +from handlers import FieldView +from handlers import ProjectView +from handlers import QueryView +from handlers import TagsView +from handlers import AboutView +from handlers import NotFound + +from model import models +from util import strsplit +from webob import Request, Response, exc + +here = os.path.dirname(os.path.abspath(__file__)) + +class Dispatcher(object): + """toolbox WSGI app which dispatchers to associated handlers""" + + # class defaults + defaults = { 'about': None, # file path to ReST about page + 'model_type': 'memory_cache', # type of model to use + 'handlers': None, + 'reload': True, # reload templates + 'reserved': None, # reserved URL namespaces + 'template_dir': None, # directory for template overrides + 'baseurl': '', # base URL for redirects + + # branding variables + 'site_name': 'toolbox', # name of the site + 'item_name': 'tool', # name of a single item + 'item_plural': None, # item_name's plural, or None for item_name + 's' + } + + def __init__(self, **kw): + """ + **kw arguments used to override defaults + additional **kw are passed to the model + """ + + # set instance parameters from kw and defaults + for key in self.defaults: + setattr(self, key, kw.pop(key, self.defaults[key])) + if self.item_plural is None: + self.item_plural = self.item_name + 's' + + # should templates be reloaded? + if isinstance(self.reload, basestring): + self.reload = self.reload.lower() == 'true' + + # model: backend storage and associated methods + if 'fields' in kw and isinstance(kw['fields'], basestring): + # split fields if given as a string + kw['fields'] = strsplit(kw['fields']) + if hasattr(self.model_type, '__call__'): + model = self.model_type + elif self.model_type in models: + model = models[self.model_type] + else: + try: + import pyloader + model = pyloader.load(self.model_type) + except: + raise AssertionError("model_type '%s' not found in %s" % (self.model_type, models.keys())) + self.model = model(**kw) + + # add an about view if file specified + if self.about: + about = file(self.about).read() + import docutils.core + about = docutils.core.publish_parts(about, writer_name='html')['body'] + self.about = about + + + # request handlers in order they will be tried + if self.handlers is None: + self.handlers = [ TagsView, + CreateProjectView, + FieldView, + QueryView, + DeleteProjectHandler, + ProjectView] + if self.about: + self.handlers.append(AboutView) + + # extend reserved URLS from handlers + if self.reserved is None: + self.reserved = set(['css', 'js', 'img']) + for handler in self.handlers: + if handler.handler_path: + self.reserved.add(handler.handler_path[0]) + + def __call__(self, environ, start_response): + + # get a request object + request = Request(environ) + + # get the path + path = request.path_info.strip('/').split('/') + if path == ['']: + path = [] + request.environ['path'] = path + + # load any new data + self.model.load() + + # match the request to a handler + for h in self.handlers: + handler = h.match(self, request) + if handler is not None: + break + else: + # our 404 handler + handler = NotFound(self, request) + + # get response + res = handler() + return res(environ, start_response)