File: application.py

package info (click to toggle)
python-werkzeug 1.0.1%2Bdfsg1-2%2Bdeb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,888 kB
  • sloc: python: 21,897; javascript: 173; makefile: 36; xml: 16
file content (104 lines) | stat: -rw-r--r-- 3,667 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# -*- coding: utf-8 -*-
"""
    simplewiki.application
    ~~~~~~~~~~~~~~~~~~~~~~

    This module implements the wiki WSGI application which dispatches
    requests to specific wiki pages and actions.


    :copyright: 2007 Pallets
    :license: BSD-3-Clause
"""
from os import path

from sqlalchemy import create_engine
from werkzeug.middleware.shared_data import SharedDataMiddleware
from werkzeug.utils import redirect
from werkzeug.wsgi import ClosingIterator

from . import actions
from .database import metadata
from .database import session
from .specialpages import page_not_found
from .specialpages import pages
from .utils import href
from .utils import local
from .utils import local_manager
from .utils import Request


#: 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)