1 # WSGI interface for Roundup Issue Tracker
2 #
3 # This module is free software, you may redistribute it
4 # and/or modify under the same terms as Python.
5 #
7 import os
8 import cgi
9 import weakref
11 import roundup.instance
12 from roundup.cgi import TranslationService
13 from BaseHTTPServer import BaseHTTPRequestHandler
16 class Writer(object):
17 '''Perform a start_response if need be when we start writing.'''
18 def __init__(self, request):
19 self.request = request #weakref.ref(request)
20 def write(self, data):
21 f = self.request.get_wfile()
22 self.write = f
23 return f(data)
25 class RequestDispatcher(object):
26 def __init__(self, home, debug=False, timing=False, lang=None):
27 assert os.path.isdir(home), '%r is not a directory'%(home,)
28 self.home = home
29 self.debug = debug
30 self.timing = timing
31 if lang:
32 self.translator = TranslationService.get_translation(lang,
33 tracker_home=home)
34 else:
35 self.translator = None
37 def __call__(self, environ, start_response):
38 """Initialize with `apache.Request` object"""
39 self.environ = environ
40 request = RequestDispatcher(self.home, self.debug, self.timing)
41 request.__start_response = start_response
43 request.wfile = Writer(request)
44 request.__wfile = None
46 tracker = roundup.instance.open(self.home, not self.debug)
48 # need to strip the leading '/'
49 environ["PATH_INFO"] = environ["PATH_INFO"][1:]
50 if request.timing:
51 environ["CGI_SHOW_TIMING"] = request.timing
53 form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
55 client = tracker.Client(tracker, request, environ, form,
56 request.translator)
57 try:
58 client.main()
59 except roundup.cgi.client.NotFound:
60 request.start_response([('Content-Type', 'text/html')], 404)
61 request.wfile.write('Not found: %s'%client.path)
63 # all body data has been written using wfile
64 return []
66 def start_response(self, headers, response_code):
67 """Set HTTP response code"""
68 description = BaseHTTPRequestHandler.responses[response_code]
69 self.__wfile = self.__start_response('%d %s'%(response_code,
70 description), headers)
72 def get_wfile(self):
73 if self.__wfile is None:
74 raise ValueError, 'start_response() not called'
75 return self.__wfile