X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=t%2Fmoe%2Fconfig.py;h=e6ce045913797a4ff411ee84357fe543f1ab9a1d;hb=11ea8e933d3a8d827da650898c277424e64f2040;hp=1de679904a3b8a92f1ed3fdf19ffdb02408042dd;hpb=8020078dd0c80b9b6680244c586c8a34c1912682;p=moe.git diff --git a/t/moe/config.py b/t/moe/config.py index 1de6799..e6ce045 100644 --- a/t/moe/config.py +++ b/t/moe/config.py @@ -55,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): """ @@ -99,21 +110,47 @@ class ConfigTree(object): if isinstance(keys, types.StringTypes): keys = [keys] for key in keys: - self.lookup(key, create=True).fix() - - 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() + 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 parse_file(self, filename, desc=None, level=0): - """Parse an utf-8 file into the tree, see `moe.confparser.ConfigParser` for details. + 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`>". """ with open(filename, 'rt') as f: if desc: filename += " <" + desc + ">" - self.parse(f, source=filename, level=level) + return self.parse(f, source=filename, level=level, proxy=proxy) class ConfigElem(object): @@ -268,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): """ @@ -288,7 +327,7 @@ class ConfigVar(ConfigElem): "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): @@ -318,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: @@ -383,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