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

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

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

行番号 
1"""WSGI Paste wrapper for mod_python. Requires Python 2.2 or greater.
2
3
4Example httpd.conf section for a Paste app with an ini file::
5
6    <Location />
7        SetHandler python-program
8        PythonHandler paste.modpython
9        PythonOption paste.ini /some/location/your/pasteconfig.ini
10    </Location>
11   
12Or if you want to load a WSGI application under /your/homedir in the module
13``startup`` and the WSGI app is ``app``::
14
15    <Location />
16        SetHandler python-program
17        PythonHandler paste.modpython
18        PythonPath "['/virtual/project/directory'] + sys.path"
19        PythonOption wsgi.application startup::app
20    </Location>
21
22
23If you'd like to use a virtual installation, make sure to add it in the path
24like so::
25
26    <Location />
27        SetHandler python-program
28        PythonHandler paste.modpython
29        PythonPath "['/virtual/project/directory', '/virtual/lib/python2.4/'] + sys.path"
30        PythonOption paste.ini /virtual/project/directory/pasteconfig.ini
31    </Location>
32
33Some WSGI implementations assume that the SCRIPT_NAME environ variable will
34always be equal to "the root URL of the app"; Apache probably won't act as
35you expect in that case. You can add another PythonOption directive to tell
36modpython_gateway to force that behavior:
37
38    PythonOption SCRIPT_NAME /mcontrol
39
40Some WSGI applications need to be cleaned up when Apache exits. You can
41register a cleanup handler with yet another PythonOption directive:
42
43    PythonOption wsgi.cleanup module::function
44
45The module.function will be called with no arguments on server shutdown,
46once for each child process or thread.
47
48This module highly based on Robert Brewer's, here:
49http://projects.amor.org/misc/svn/modpython_gateway.py
50"""
51
52import traceback
53
54try:
55    from mod_python import apache
56except:
57    pass
58from paste.deploy import loadapp
59
60class InputWrapper(object):
61   
62    def __init__(self, req):
63        self.req = req
64   
65    def close(self):
66        pass
67   
68    def read(self, size=-1):
69        return self.req.read(size)
70   
71    def readline(self, size=-1):
72        return self.req.readline(size)
73   
74    def readlines(self, hint=-1):
75        return self.req.readlines(hint)
76   
77    def __iter__(self):
78        line = self.readline()
79        while line:
80            yield line
81            # Notice this won't prefetch the next line; it only
82            # gets called if the generator is resumed.
83            line = self.readline()
84
85
86class ErrorWrapper(object):
87   
88    def __init__(self, req):
89        self.req = req
90   
91    def flush(self):
92        pass
93   
94    def write(self, msg):
95        self.req.log_error(msg)
96   
97    def writelines(self, seq):
98        self.write(''.join(seq))
99
100
101bad_value = ("You must provide a PythonOption '%s', either 'on' or 'off', "
102             "when running a version of mod_python < 3.1")
103
104
105class Handler(object):
106   
107    def __init__(self, req):
108        self.started = False
109       
110        options = req.get_options()
111       
112        # Threading and forking
113        try:
114            q = apache.mpm_query
115            threaded = q(apache.AP_MPMQ_IS_THREADED)
116            forked = q(apache.AP_MPMQ_IS_FORKED)
117        except AttributeError:
118            threaded = options.get('multithread', '').lower()
119            if threaded == 'on':
120                threaded = True
121            elif threaded == 'off':
122                threaded = False
123            else:
124                raise ValueError(bad_value % "multithread")
125           
126            forked = options.get('multiprocess', '').lower()
127            if forked == 'on':
128                forked = True
129            elif forked == 'off':
130                forked = False
131            else:
132                raise ValueError(bad_value % "multiprocess")
133       
134        env = self.environ = dict(apache.build_cgi_env(req))
135       
136        if 'SCRIPT_NAME' in options:
137            # Override SCRIPT_NAME and PATH_INFO if requested.
138            env['SCRIPT_NAME'] = options['SCRIPT_NAME']
139            env['PATH_INFO'] = req.uri[len(options['SCRIPT_NAME']):]
140        else:
141            env['SCRIPT_NAME'] = ''
142            env['PATH_INFO'] = req.uri
143       
144        env['wsgi.input'] = InputWrapper(req)
145        env['wsgi.errors'] = ErrorWrapper(req)
146        env['wsgi.version'] = (1, 0)
147        env['wsgi.run_once'] = False
148        if env.get("HTTPS") in ('yes', 'on', '1'):
149            env['wsgi.url_scheme'] = 'https'
150        else:
151            env['wsgi.url_scheme'] = 'http'
152        env['wsgi.multithread']  = threaded
153        env['wsgi.multiprocess'] = forked
154       
155        self.request = req
156   
157    def run(self, application):
158        try:
159            result = application(self.environ, self.start_response)
160            for data in result:
161                self.write(data)
162            if not self.started:
163                self.request.set_content_length(0)
164            if hasattr(result, 'close'):
165                result.close()
166        except:
167            traceback.print_exc(None, self.environ['wsgi.errors'])
168            if not self.started:
169                self.request.status = 500
170                self.request.content_type = 'text/plain'
171                data = "A server error occurred. Please contact the administrator."
172                self.request.set_content_length(len(data))
173                self.request.write(data)
174   
175    def start_response(self, status, headers, exc_info=None):
176        if exc_info:
177            try:
178                if self.started:
179                    raise exc_info[0], exc_info[1], exc_info[2]
180            finally:
181                exc_info = None
182       
183        self.request.status = int(status[:3])
184       
185        for key, val in headers:
186            if key.lower() == 'content-length':
187                self.request.set_content_length(int(val))
188            elif key.lower() == 'content-type':
189                self.request.content_type = val
190            else:
191                self.request.headers_out.add(key, val)
192       
193        return self.write
194   
195    def write(self, data):
196        if not self.started:
197            self.started = True
198        self.request.write(data)
199
200
201startup = None
202cleanup = None
203wsgiapps = {}
204
205def handler(req):
206    options = req.get_options()
207    # Run a startup function if requested.
208    global startup
209    if 'wsgi.startup' in options and not startup:
210        func = options['wsgi.startup']
211        if func:
212            module_name, object_str = func.split('::', 1)
213            module = __import__(module_name, globals(), locals(), [''])
214            startup = apache.resolve_object(module, object_str)
215            startup(req)
216   
217    # Register a cleanup function if requested.
218    global cleanup
219    if 'wsgi.cleanup' in options and not cleanup:
220        func = options['wsgi.cleanup']
221        if func:
222            module_name, object_str = func.split('::', 1)
223            module = __import__(module_name, globals(), locals(), [''])
224            cleanup = apache.resolve_object(module, object_str)
225            def cleaner(data):
226                cleanup()
227            try:
228                # apache.register_cleanup wasn't available until 3.1.4.
229                apache.register_cleanup(cleaner)
230            except AttributeError:
231                req.server.register_cleanup(req, cleaner)
232   
233    # Import the wsgi 'application' callable and pass it to Handler.run
234    global wsgiapps
235    appini = options.get('paste.ini')
236    app = None
237    if appini:
238        if appini not in wsgiapps:
239            wsgiapps[appini] = loadapp("config:%s" % appini)
240        app = wsgiapps[appini]
241   
242    # Import the wsgi 'application' callable and pass it to Handler.run
243    appwsgi = options.get('wsgi.application')
244    if appwsgi and not appini:
245        modname, objname = appwsgi.split('::', 1)
246        module = __import__(modname, globals(), locals(), [''])
247        app = getattr(module, objname)
248   
249    Handler(req).run(app)
250   
251    # status was set in Handler; always return apache.OK
252    return apache.OK
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。