Merge branch 'master' into python3
[wrw.git] / wrw / dispatch.py
... / ...
CommitLineData
1import sys, traceback
2from . import env
3
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
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
45def defaulterror(req, excinfo):
46 from . 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
57def handle(req, startreq, handler):
58 eh = errorhandler.val
59 try:
60 resp = [""]
61 while True:
62 try:
63 resp = iterproxy(handler(req))
64 break
65 except restart as i:
66 handler = i.handle
67 except Exception as i:
68 if eh is None:
69 raise
70 handler = wraphandler(eh, sys.exc_info())
71 eh = None
72 req.commit(startreq)
73 return resp
74 finally:
75 req.cleanup()