Exemplo n.º 1
0
class Root:
    def __init__(self):
        self._applist = {}  # all apps
        self._index = None  # index app
        self._error = None
        self.environ = None
        self.start_response = None
        self.sessionman = SessionManager()
        self.debug = False

    def register_app(self, name, cpath):
        if name not in self._applist:
            self._applist[name] = ApplicationInfo(name, cpath=cpath)

    def register_index(self, name, cpath):
        self._index = ApplicationInfo(name, cpath=cpath)

    def register_error(self, name, cpath):
        self._error = ApplicationInfo(name, cpath=cpath)

    def _default_index(self):
        page = TextContent(_(u"Index method is left out."))
        return self._prepare_response(Response(200, page))

    def _default_error(self, code, message):
        page = TextContent(message)
        return self._prepare_response(Response(code, page))

    def __call__(self, environ, start_response):
        return self.run(environ, start_response)

    def run(self, environ, start_response):
        def tuplize(x):
            l = x.split("=")[:2]
            if len(l) == 1:
                l.append(True)
            return tuple(l)

        self.environ = environ
        self.start_response = start_response

        try:
            path_info = urllib.unquote_plus(environ["PATH_INFO"])
        except KeyError:
            raise WSGIKeyNotPresentError("PATH_INFO")

        path = [p for p in path_info.split("/") if p] or [""]
        if "QUERY_STRING" in environ:
            query_string = urllib.unquote_plus(environ["QUERY_STRING"])
            params = dict([tuplize(x) for x in query_string.split("&") if x])
        else:
            params = {}

            # a dirty little trick to deny FieldStorage to use QUERY_STRING
        self.environ["QUERY_STRING"] = ""

        xenviron = Struct()
        xenviron.args = path
        xenviron.kwargs = params
        try:
            xenviron.fields = FieldStorage(environ=self.environ, fp=self.environ["wsgi.input"])
        except KeyError:
            raise WSGIKeyNotPresentError("wsgi.input")
        xenviron.cookies = SimpleCookie(environ.get("HTTP_COOKIE", ""))

        try:
            xenviron.cookies, xenviron.session = self.sessionman.get_session(xenviron.cookies)
        except SessionError:
            xenviron.session = self.sessionman.new_session()

        if not path[0]:
            if not self._index:
                return self._default_index()

            app = self._index(xenviron)
        else:
            try:
                name = path[0]
                app = self._applist[name](xenviron)
            except KeyError:
                xenviron.error_code = 404
                xenviron.error_message = _(u"Method not found")

                if self._error:
                    app = self._error(xenviron)
                else:
                    return self._default_error(xenviron.error_code, xenviron.error_message)

        app.body.refresh(xenviron)
        app.body.run()
        app_xenviron, response = app.body.get()

        # further process the app_xenviron
        self.sessionman.update(app_xenviron.session)

        # return preparations
        cookies = SimpleCookie()
        cookies.update(app_xenviron.cookies)
        cookies.update(app_xenviron.session.sidcookie)
        cookies = str(cookies).split()[1]
        response.heads.set_cookie = cookies
        return self._prepare_response(response)

    def _prepare_response(self, response):
        rc, rh, ct = response.get_forwsgi()
        self.start_response(rc, rh)

        return ct

    @staticmethod
    def configure(cfgfilename, update=False):
        root = Root()
        cfg = ConfigParser()
        cfg.read(cfgfilename)

        apps = "applications"

        for app, cpath in cfg.items(apps):
            if not app in root._applist:
                root.register_app(app, cpath)

        index = "index"
        if cfg.has_section(index):
            app, cpath = cfg.items(index)[0]
            root.register_index(app, cpath)

        error = "error"
        if cfg.has_section(error):
            app, cpath = cfg.items(error)[0]
            root.register_error(app, cpath)

        try:
            timeout = cfg.getint("root", "timeout")
        except (NoSectionError, NoOptionError):
            timeout = 0

        root.sessionman.timeout = timeout

        try:
            expiretime = cfg.getint("root", "expiretime")
        except (NoSectionError, NoOptionError):
            expiretime = 0

        root.sessionman.expiretime = expiretime

        try:
            debug = cfg.getboolean("root", "debug")
        except (NoSectionError, NoOptionError):
            debug = False

        root.debug = debug

        return root