Merge branch 'master' into python3
[wrw.git] / wrw / dispatch.py
CommitLineData
784d41f3 1import sys, traceback
3614ca83 2from . import env
784d41f3 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]
6cf09c76 26 self.__next__()
e8aa9ce2
FT
27
28 def __iter__(self):
29 return self
30
6cf09c76 31 def __next__(self):
e8aa9ce2
FT
32 if self._next is None:
33 raise StopIteration()
34 ret = self._next[0]
35 try:
6cf09c76 36 self._next[:] = [self.bki.__next__()]
e8aa9ce2
FT
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 45def defaulterror(req, excinfo):
3614ca83 46 from . import resp
784d41f3
FT
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 64 break
c33f2d6c 65 except restart as i:
d7604bee 66 handler = i.handle
3614ca83 67 except Exception as i:
784d41f3
FT
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()