Merge branch 'master' into python3
authorFredrik Tolf <fredrik@dolda2000.com>
Sun, 5 Feb 2012 16:00:30 +0000 (17:00 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Sun, 5 Feb 2012 16:00:30 +0000 (17:00 +0100)
Conflicts:
wrw/resp.py
wrw/session.py

wrw/dispatch.py
wrw/env.py [new file with mode: 0644]
wrw/resp.py
wrw/session.py
wrw/util.py

index 709cfe4..e51559e 100644 (file)
@@ -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 (file)
index 0000000..6c7e859
--- /dev/null
@@ -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)])
index 75a7f3a..6e95ec5 100644 (file)
@@ -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, """<h1>%s</h1>\n<p>%s</p>\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):
index d78c43b..832387e 100644 (file)
@@ -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)
index e338e2c..58ead25 100644 (file)
@@ -50,7 +50,7 @@ class sessiondata(object):
 
     @classmethod
     def sessdb(cls):
-        return session.default
+        return session.default.val
 
 class autodirty(sessiondata):
     @classmethod