X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=t%2Fmoe%2Fconfig.py;h=e6ce045913797a4ff411ee84357fe543f1ab9a1d;hb=11ea8e933d3a8d827da650898c277424e64f2040;hp=f24e1ef8f357748b41b13f2b8cff20419cfb90d7;hpb=b07a7c4bf08db2928e1845c4e60798f7c9ad8b65;p=moe.git diff --git a/t/moe/config.py b/t/moe/config.py index f24e1ef..e6ce045 100644 --- a/t/moe/config.py +++ b/t/moe/config.py @@ -1,10 +1,6 @@ """ -config.py ---------- - Lazy conditional string evaluation module for Moe configuration variables. - * Each variable has ordered list of operations (definitions), each defining operation either assigns (SET) or appends (APPEND) value of an expression to the variable. Each operation may be guarded by condition(s). @@ -59,6 +55,17 @@ class VariableFixedError(ConfigError): class CyclicConfigError(ConfigError): pass +class ParseProxy(list): + """Proxy helper class around values returned by `parse` and `parse_file`, + useful in "with" constructs.""" + def __init__(self, config, parsed_ops): + super(ParseProxy, self).__init__(parsed_ops) + self.config = config + def __enter__(self): + pass + def __exit__(self, etype, value, traceback): + self.config.remove(list(self)) + class ConfigTree(object): """ @@ -98,19 +105,52 @@ class ConfigTree(object): self.variables[k].dump(prefix) for k in sorted(self.variables.keys()) ]) - def parse(self, s, source=None, level=0): - """Parse `s` (stream/string) into the tree, see `moe.confparser.ConfigParser` for details.""" - import moe.confparser - p = moe.confparser.ConfigParser(text, self, source=source, level=level) - p.parse() - - def parse_file(self, filename, desc=None, level=0): - """Parse an utf-8 file into the tree, see `moe.confparser.ConfigParser` for details. + def fix(self, keys): + "Fix value of variable or list of variables. Fixing undefined variable raises `UndefinedError`." + if isinstance(keys, types.StringTypes): + keys = [keys] + for key in keys: + self.lookup(key, create=False).fix() + + def unfix(self, keys): + "Unfix value of variable or list of variables. Unfixing undefined variable raises `UndefinedError`." + if isinstance(keys, types.StringTypes): + keys = [keys] + for key in keys: + self.lookup(key, create=False).unfix() + + def remove(self, parsed): + """Given a list [(varname, `Operation`)] as returned by `parse` or `parse_file`, + removes the operations from the respective variables config tree. + Variables/operations not present int the tree raise ValueError. + """ + for vname, o in parsed: + v = self.lookup(vname, create = True) + v.remove_operation(o) + + def parse(self, s, source=None, level=0, proxy=True): + """Parse `s` (stream/string) into the tree, see `moe.config_parser.ConfigParser` for details. + Returns list of parset operations: [(varname, `Operation`)]. + By default returns a proxy list-like object that can be used in "with" constructs: + + with config.parse("TEST='1'"): + print config['TEST'] + raise StupidError + """ + import moe.config_parser + p = moe.config_parser.ConfigParser(s, self, source=source, level=level) + l = p.parse() + if not proxy: + return l + return ParseProxy(self, l) + + def parse_file(self, filename, desc=None, level=0, proxy=True): + """Parse an utf-8 file into the tree using func:`parse`. Names the source "`filename` <`desc`>". """ - f = open(filename, 'rt') - if desc: - filename += " <" + desc + ">" - self.parse(f, source=filename, level=level) + with open(filename, 'rt') as f: + if desc: + filename += " <" + desc + ">" + return self.parse(f, source=filename, level=level, proxy=proxy) class ConfigElem(object): @@ -265,7 +305,9 @@ class ConfigVar(ConfigElem): def variables(self): "Return a set of variables used in the expressions" - return set(sum([ list(op.expression.variables()) for op in self.operations ], [])) + if not self.operations: + return set([]) + return set.union(*[ op.expression.variables() for op in self.operations ]) def fix(self): """ @@ -278,14 +320,14 @@ class ConfigVar(ConfigElem): self.fixed = True def unfix(self): - "Set the variable to be modifiable again." + "Make the variable modifiable again." self.fixed = False def value(self, depth=0): "Handle the case when fixed, raise exc. on different evaluation" val = super(ConfigVar,self).value(depth) if self.fixed and self.fixed_val != val: - raise VariableFixedError("value of var %s was fixed to %r but evaluated to %r", self.name, self.fixed_val, val) + raise VariableFixedError("value of var %r was fixed to %r but evaluated to %r", self.name, self.fixed_val, val) return val def add_operation(self, operation): @@ -315,7 +357,7 @@ class ConfigVar(ConfigElem): self.invalidate() # Remove the operation self.operations.remove(operation) - # Remove dependencies on variables unused in other operations + # Remove dependencies on variables unused in other defining operations vs = self.variables() for v in operation.expression.variables(): if v not in vs: @@ -380,8 +422,8 @@ class ConfigExpression(object): self.exprlist[i] = unicode(e, 'ascii') def variables(self): - "Return an iterator of variables user in the expression" - return itertools.ifilter(lambda e: isinstance(e, ConfigVar), self.exprlist) + "Return a set of variables used in the expression" + return set([e for e in self.exprlist if isinstance(e, ConfigVar)]) def __str__(self): return self.original