root/galaxy-central/eggs/Paste-1.6-py2.6.egg/paste/cascade.py

リビジョン 3, 4.1 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
2# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
3
4"""
5Cascades through several applications, so long as applications
6return ``404 Not Found``.
7"""
8from paste import httpexceptions
9from paste.util import converters
10import tempfile
11from cStringIO import StringIO
12
13__all__ = ['Cascade']
14
15def make_cascade(loader, global_conf, catch='404', **local_conf):
16    """
17    Expects configuration like:
18
19    [composit:cascade]
20    use = egg:Paste#cascade
21    # all start with 'app' and are sorted alphabetically
22    app1 = foo
23    app2 = bar
24    ...
25    catch = 404 500 ...
26    """
27    catch = map(int, converters.aslist(catch))
28    apps = []
29    for name, value in local_conf.items():
30        if not name.startswith('app'):
31            raise ValueError(
32                "Bad configuration key %r (=%r); all configuration keys "
33                "must start with 'app'"
34                % (name, value))
35        app = loader.get_app(value, global_conf=global_conf)
36        apps.append((name, app))
37    apps.sort()
38    apps = [app for name, app in apps]
39    return Cascade(apps, catch=catch)
40   
41class Cascade(object):
42
43    """
44    Passed a list of applications, ``Cascade`` will try each of them
45    in turn.  If one returns a status code listed in ``catch`` (by
46    default just ``404 Not Found``) then the next application is
47    tried.
48
49    If all applications fail, then the last application's failure
50    response is used.
51    """
52
53    def __init__(self, applications, catch=(404,)):
54        self.apps = applications
55        self.catch_codes = {}
56        self.catch_exceptions = []
57        for error in catch:
58            if isinstance(error, str):
59                error = int(error.split(None, 1)[0])
60            if isinstance(error, httpexceptions.HTTPException):
61                exc = error
62                code = error.code
63            else:
64                exc = httpexceptions.get_exception(error)
65                code = error
66            self.catch_codes[code] = exc
67            self.catch_exceptions.append(exc)
68        self.catch_exceptions = tuple(self.catch_exceptions)
69               
70    def __call__(self, environ, start_response):
71        failed = []
72        def repl_start_response(status, headers, exc_info=None):
73            code = int(status.split(None, 1)[0])
74            if code in self.catch_codes:
75                failed.append(None)
76                return _consuming_writer
77            return start_response(status, headers, exc_info)
78
79        try:
80            length = int(environ.get('CONTENT_LENGTH', 0) or 0)
81        except ValueError:
82            length = 0
83        if length > 0:
84            # We have to copy wsgi.input
85            copy_wsgi_input = True
86            if length > 4096 or length < 0:
87                f = tempfile.TemporaryFile()
88                if length < 0:
89                    f.write(environ['wsgi.input'].read())
90                else:
91                    copy_len = length
92                    while copy_len > 0:
93                        chunk = environ['wsgi.input'].read(min(copy_len, 4096))
94                        f.write(chunk)
95                        copy_len -= len(chunk)
96                f.seek(0)
97            else:
98                f = StringIO(environ['wsgi.input'].read(length))
99            environ['wsgi.input'] = f
100        else:
101            copy_wsgi_input = False
102        for app in self.apps[:-1]:
103            environ_copy = environ.copy()
104            if copy_wsgi_input:
105                environ_copy['wsgi.input'].seek(0)
106            failed = []
107            try:
108                v = app(environ_copy, repl_start_response)
109                if not failed:
110                    return v
111                else:
112                    if hasattr(v, 'close'):
113                        # Exhaust the iterator first:
114                        list(v)
115                        # then close:
116                        v.close()
117            except self.catch_exceptions, e:
118                pass
119        if copy_wsgi_input:
120            environ['wsgi.input'].seek(0)
121        return self.apps[-1](environ, start_response)
122
123def _consuming_writer(s):
124    pass
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。