+import sys, traceback
+from . import env
+
__all__ = ["restart"]
class restart(Exception):
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:
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:
--- /dev/null
+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)])
-from . import dispatch, proto
+from . import dispatch, proto, env
__all__ = ["skeleton", "skelfor", "setskel", "usererror"]
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):
import threading, time, pickle, random, os
-from . import cookie
+from . import cookie, env
__all__ = ["db", "get"]
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)