From: Fredrik Tolf Date: Sun, 5 Feb 2012 15:43:47 +0000 (+0100) Subject: Added a kind of generic module to handle configuration environments. X-Git-Url: http://git.dolda2000.com/gitweb/?a=commitdiff_plain;h=e88ff533f2aba6613f0abcdb759d0b2197d0c313;p=wrw.git Added a kind of generic module to handle configuration environments. --- 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)])