Use the env module to catch errors in the dispatcher.
[wrw.git] / wrw / dispatch.py
CommitLineData
784d41f3
FT
1import sys, traceback
2import env
3
b409a338
FT
4__all__ = ["restart"]
5
6class restart(Exception):
7 def handle(self, req):
8 pass
9
10def mangle(result):
11 try:
12 iter(result)
13 except TypeError:
14 pass
15 else:
16 return result
17 return [str(result)]
18
e8aa9ce2
FT
19class iterproxy(object):
20 # Makes sure iter(real).next() is called immediately, in order to
21 # let generator code run.
22 def __init__(self, real):
23 self.bk = real
24 self.bki = iter(real)
25 self._next = [None]
26 self.next()
27
28 def __iter__(self):
29 return self
30
31 def next(self):
32 if self._next is None:
33 raise StopIteration()
34 ret = self._next[0]
35 try:
36 self._next[:] = [self.bki.next()]
37 except StopIteration:
38 self._next = None
39 return ret
40
41 def close(self):
42 if hasattr(self.bk, "close"):
43 self.bk.close()
44
784d41f3
FT
45def defaulterror(req, excinfo):
46 import resp
47 traceback.print_exception(*excinfo)
48 raise resp.httperror(500)
49
50def wraphandler(handler, excinfo):
51 def wrapped(req):
52 return handler(req, excinfo)
53 return wrapped
54
55errorhandler = env.var(defaulterror)
56
b409a338 57def handle(req, startreq, handler):
784d41f3 58 eh = errorhandler.val
b409a338
FT
59 try:
60 resp = [""]
61 while True:
62 try:
e8aa9ce2 63 resp = iterproxy(handler(req))
b409a338
FT
64 break
65 except restart, i:
d7604bee 66 handler = i.handle
784d41f3
FT
67 except Exception, i:
68 if eh is None:
69 raise
70 handler = wraphandler(eh, sys.exc_info())
71 eh = None
b409a338
FT
72 req.commit(startreq)
73 return resp
74 finally:
75 req.cleanup()