# -*- coding: utf-8 -*- """ simplewiki.application ~~~~~~~~~~~~~~~~~~~~~~ This module implements the wiki WSGI application which dispatches requests to specific wiki pages and actions. :copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details. :license: BSD. """ from os import path from sqlalchemy import create_engine from werkzeug import ClosingIterator, SharedDataMiddleware, redirect from simplewiki.utils import Request, Response, local, local_manager, href from simplewiki.database import session, metadata from simplewiki import actions from simplewiki.specialpages import pages, page_not_found #: path to shared data SHARED_DATA = path.join(path.dirname(__file__), 'shared') class SimpleWiki(object): """ Our central WSGI application. """ def __init__(self, database_uri): self.database_engine = create_engine(database_uri) # apply our middlewares. we apply the middlewars *inside* the # application and not outside of it so that we never lose the # reference to the `SimpleWiki` object. self._dispatch = SharedDataMiddleware(self.dispatch_request, { '/_shared': SHARED_DATA }) # free the context locals at the end of the request self._dispatch = local_manager.make_middleware(self._dispatch) def init_database(self): """Called from the management script to generate the db.""" metadata.create_all(bind=self.database_engine) def bind_to_context(self): """ Useful for the shell. Binds the application to the current active context. It's automatically called by the shell command. """ local.application = self def dispatch_request(self, environ, start_response): """Dispatch an incoming request.""" # set up all the stuff we want to have for this request. That is # creating a request object, propagating the application to the # current context and instanciating the database session. self.bind_to_context() request = Request(environ) request.bind_to_context() # get the current action from the url and normalize the page name # which is just the request path action_name = request.args.get('action') or 'show' page_name = u'_'.join([x for x in request.path.strip('/') .split() if x]) # redirect to the Main_Page if the user requested the index if not page_name: response = redirect(href('Main_Page')) # check special pages elif page_name.startswith('Special:'): if page_name[8:] not in pages: response = page_not_found(request, page_name) else: response = pages[page_name[8:]](request) # get the callback function for the requested action from the # action module. It's "on_" + the action name. If it doesn't # exists call the missing_action method from the same module. else: action = getattr(actions, 'on_' + action_name, None) if action is None: response = actions.missing_action(request, action_name) else: response = action(request, page_name) # make sure the session is removed properly return ClosingIterator(response(environ, start_response), session.remove) def __call__(self, environ, start_response): """Just forward a WSGI call to the first internal middleware.""" return self._dispatch(environ, start_response)