from urllib import unquote import threading from paste.registry import RegistryManager, StackedObjectProxy from rhubarbtart.httpobjects import Request, Response request = StackedObjectProxy() response = StackedObjectProxy() from rhubarbtart.resolution import resolve from paste.util import import_string from paste import httpexceptions from paste.deploy.converters import asbool __all__ = ['request', 'response', 'TartRootController', 'WSGIApp', 'expose', 'make_middleware', 'httpobjects'] def expose(func): """ Decorator to mark a method as public (having an ``.exposed`` attribute indicates this; this decorator just sets that attribute). """ func.exposed = True return func def make_controller(global_conf, root_object): return TartRootController(root_object) def make_middleware(app, global_conf, **local_conf): """ Wrap the basic application (typically based on TartRootController) in a standard set of middleware. """ wrapped = app conf = global_conf.copy() conf.update(local_conf) debug = asbool(conf.get('debug', False)) if asbool(conf.get('use_recursive', True)): from paste import recursive wrapped = recursive.RecursiveMiddleware( wrapped, conf) if asbool(conf.get('use_session', True)): from paste import session wrapped = session.SessionMiddleware( wrapped, conf) if debug: if asbool(conf.get('use_wdg_validate', False)): from paste.debug import wdg_validate wrapped = wdg_validate.WDGValidateMiddleware( wrapped, conf) if asbool(conf.get('use_lint', False)): from paste import lint wrapped = lint.make_middleware( wrapped, conf) if asbool(conf.get('use_profile', False)): from paste.debug import profile wrapped = profile.ProfileMiddleware( wrapped, conf) if asbool(conf.get('use_interactive', False)): from paste import evalexception wrapped = evalexception.EvalException( wrapped, conf) else: from paste.exceptions import errormiddleware wrapped = errormiddleware.ErrorMiddleware( wrapped, conf) if asbool(conf.get('use_printdebug', True)): from paste.debug import prints wrapped = prints.PrintDebugMiddleware( wrapped, conf) else: from paste.exceptions import errormiddleware wrapped = errormiddleware.ErrorMiddleware( wrapped, conf) from paste.deploy.config import ConfigMiddleware wrapped = ConfigMiddleware(wrapped, conf) return wrapped class WSGIApp(object): """ Used to wrap a WSGI application to put it in the object tree and have it invoked. Any object with a ``.wsgi_application`` attribute will do, this just happens to be an easy way to make such an attribute. Usage:: class Root(object): foreign_app = WSGIApp(actual_wsgi_app) """ exposed = True def __init__(self, app): self.wsgi_application = app class TartRootController(object): wsgi_application = True root_object = None # @@: This lets people not call TartRootController.__init__ in their # subclasses. Maybe we should not let people do that? fake_cherrypy = False default_encoding = 'UTF-8' def __init__(self, root_object=None, fake_cherrypy=False, default_encoding='UTF-8'): """ Create a new RhubarbTart controller. ``root_object``: If given, this will be the root object; otherwise the controller itself will be the root object. ``fake_cherrypy``: If true, then ``cherrypy.request`` and ``cherrypy.response`` will point at RhubarbTart's request and response objects. """ if root_object is None: root_object = self if isinstance(root_object, basestring): root_object = import_string.eval_import(root_object) self.root_object = root_object self.fake_cherrypy = fake_cherrypy self.default_encoding = default_encoding def __call__(self, environ, start_response): if 'paste.httpexceptions' not in environ: return httpexceptions.make_middleware(self)(environ, start_response) if 'paste.registry' not in environ: return RegistryManager(self)(environ, start_response) root_object = self.root_object if root_object is None: root_object = self req = Request(environ) default_encoding = req.config.get( 'default_encoding', self.default_encoding) res = Response(req, default_encoding=default_encoding) environ['paste.registry'].register(request, req) environ['paste.registry'].register(response, res) if self.fake_cherrypy: import cherrypy cherrypy.serving.request = req cherrypy.serving.response = res install_fake_cherrypy_config() environ['paste.registry'].register(cherrypy.config.configs, {'global': req.config}) try: return resolve(root_object, environ, start_response) except cherrypy.HTTPRedirect, e: e.set_response() start_response(res.status, res.headeritems()) return res.body_iter() except cherrypy.HTTPError, e: start_response('%s error' % e.status, [('Content-type', 'text/plain')]) return [str(e)] else: return resolve(root_object, environ, start_response) _fake_cherrypy_lock = threading.Lock() def install_fake_cherrypy_config(): import cherrypy if not isinstance(cherrypy.config.configs, StackedObjectProxy): _fake_cherrypy_lock.acquire() try: if not isinstance(cherrypy.config.configs, StackedObjectProxy): cherrypy.config.configs = StackedObjectProxy() finally: _fake_cherrypy_lock.release()