From: Fredrik Tolf Date: Sun, 5 Feb 2012 16:00:30 +0000 (+0100) Subject: Merge branch 'master' into python3 X-Git-Url: http://dolda2000.com/gitweb/?p=wrw.git;a=commitdiff_plain;h=3614ca8353a5f2055fdcc086e6bc9dc993b49b42;hp=f9e9a7b5b192adfc7318e7f3ba0153668eef3bc1 Merge branch 'master' into python3 Conflicts: wrw/resp.py wrw/session.py --- diff --git a/wrw/dispatch.py b/wrw/dispatch.py index 709cfe4..e51559e 100644 --- a/wrw/dispatch.py +++ b/wrw/dispatch.py @@ -1,3 +1,6 @@ +import sys, traceback +from . import env + __all__ = ["restart"] class restart(Exception): @@ -39,7 +42,20 @@ class iterproxy(object): if hasattr(self.bk, "close"): self.bk.close() +def defaulterror(req, excinfo): + from . import resp + traceback.print_exception(*excinfo) + raise resp.httperror(500) + +def wraphandler(handler, excinfo): + def wrapped(req): + return handler(req, excinfo) + return wrapped + +errorhandler = env.var(defaulterror) + def handle(req, startreq, handler): + eh = errorhandler.val try: resp = [""] while True: @@ -48,6 +64,11 @@ def handle(req, startreq, handler): break except restart as i: handler = i.handle + except Exception as i: + if eh is None: + raise + handler = wraphandler(eh, sys.exc_info()) + eh = None req.commit(startreq) return resp finally: diff --git a/wrw/env.py b/wrw/env.py new file mode 100644 index 0000000..6c7e859 --- /dev/null +++ b/wrw/env.py @@ -0,0 +1,86 @@ +import threading, weakref + +__all__ = ["environment", "root", "get", "binding", "var"] + +class stack(object): + __slots__ = ["env", "prev"] + def __init__(self, env, prev): + self.env = env + self.prev = prev + +class environment(object): + __slots__ = ["parent", "map"] + def __init__(self, parent = None): + self.parent = None + self.map = weakref.WeakKeyDictionary() + + def get(self, var): + if var in self.map: + return self.map[var] + if self.parent is None: + return None + return self.parent.get(var) + + def set(self, var, val): + self.map[var] = val + + def __enter__(self): + cur = context.env + context.prev = stack(cur, context.prev) + context.env = self + return None + + def __exit__(self, *excinfo): + prev = context.prev + if prev is None: + raise Exception("Unbalanced __enter__/__exit__") + context.env = prev.env + context.prev = prev.prev + return False + +root = environment() + +class context(threading.local): + env = root + prev = None +context = context() + +def get(): + return context.env + +class binding(object): + __slots__ = ["bindings"] + def __init__(self, bindings): + if isinstance(bindings, dict): + bindings = bindings.items() + self.bindings = bindings + + def __enter__(self): + cur = context.env + new = environment(cur) + for var, val in self.bindings: + new.map[var] = val + context.prev = stack(cur, context.prev) + context.env = new + return None + + def __exit__(self, *excinfo): + prev = context.prev + if prev is None: + raise Exception("Unbalanced __enter__/__exit__") + context.env = prev.env + context.prev = prev.prev + return False + +class var(object): + __slots__ = ["__weakref__"] + def __init__(self, default = None): + if default is not None: + root.map[self] = default + + @property + def val(self): + return context.env.get(self) + + def binding(self, val): + return binding([(self, val)]) diff --git a/wrw/resp.py b/wrw/resp.py index 75a7f3a..6e95ec5 100644 --- a/wrw/resp.py +++ b/wrw/resp.py @@ -1,4 +1,4 @@ -from . import dispatch, proto +from . import dispatch, proto, env __all__ = ["skeleton", "skelfor", "setskel", "usererror"] @@ -27,10 +27,10 @@ class skeleton(object): def message(self, message, detail): return self.page(message, """

%s

\n

%s

\n""" % (message, detail)) -defskel = skeleton() +defskel = env.var(skeleton()) def getskel(req): - return [defskel] + return [defskel.val] def skelfor(req): return req.item(getskel)[0] def setskel(req, skel): diff --git a/wrw/session.py b/wrw/session.py index d78c43b..832387e 100644 --- a/wrw/session.py +++ b/wrw/session.py @@ -1,5 +1,5 @@ import threading, time, pickle, random, os -from . import cookie +from . import cookie, env __all__ = ["db", "get"] @@ -180,7 +180,7 @@ class dirback(object): with open(os.path.join(self.path, key), "w") as out: out.write(value) -default = db(backdb = dirback(os.path.join("/tmp", "wrwsess-" + str(os.getuid())))) +default = env.var(db(backdb = dirback(os.path.join("/tmp", "wrwsess-" + str(os.getuid()))))) def get(req): - return default.get(req) + return default.val.get(req) diff --git a/wrw/util.py b/wrw/util.py index e338e2c..58ead25 100644 --- a/wrw/util.py +++ b/wrw/util.py @@ -50,7 +50,7 @@ class sessiondata(object): @classmethod def sessdb(cls): - return session.default + return session.default.val class autodirty(sessiondata): @classmethod