6 key_pattern = re.compile('^[A-Za-z0-9_-]+$')
7 ref_pattern = re.compile('^[A-Za-z0-9_-]+')
9 class MoeConfigInvalid(Exception):
12 class MoeConfigEvalErr(Exception):
16 """Moe configuration file."""
18 def __init__(self, file=None, name=None):
22 elif name is not None:
24 self.load(open(name, 'r'))
26 def parse_line(self, x):
27 x = x.rstrip("\n").lstrip(" \t")
28 if x=='' or x.startswith('#'):
37 if not self.vars.has_key(k):
38 self.vars[k] = [('a','')];
41 if not key_pattern.match(k):
42 raise MoeConfigInvalid, "Malformed name of configuration variable"
45 if not v.endswith("'"):
46 raise MoeConfigInvalid, "Misquoted string"
47 self.vars[k].append(('s', v[:-1]))
48 elif v.startswith('"'):
50 if not v.endswith('"'):
51 raise MoeConfigInvalid, "Misquoted string"
52 self.parse_interpolated(self.vars[k], v[:-1])
54 self.parse_interpolated(self.vars[k], v)
56 raise MoeConfigInvalid, "Parse error"
60 for x in file.readlines():
64 except MoeConfigInvalid, x:
65 msg = x.message + ' at line ' + str(lino)
66 if hasattr(self, 'name'):
67 msg += ' of ' + self.name
68 raise MoeConfigInvalid, msg
70 def parse_interpolated(self, list, s):
77 raise MoeConfigInvalid, "Unbalanced braces"
78 k, s = s[1:p], s[p+1:]
79 if not key_pattern.match(k):
80 raise MoeConfigInvalid, "Invalid variable name"
82 m = ref_pattern.match(s)
84 k, s = s[:m.end()], s[m.end():]
86 raise MoeConfigInvalid, "Invalid variable reference"
92 list.append(('s', s[:p]))
95 def dump(self, file=sys.stdout):
96 for k,v in self.vars.items():
98 if len(v) > 0 and v[0][0] == 'a':
104 file.write("'" + w + "'")
106 file.write('"$' + w + '"')
109 class MoeConfigStack:
110 """Stack of configuration files."""
112 def __init__(self, base=None):
113 ## FIXME: Do we need to duplicate the config files themselves?
115 self.stk = base.stk[:]
118 self.in_progress = {}
123 def __getitem__(self, k):
124 if self.in_progress.has_key(k):
125 raise MoeConfigEvalErr, "Definition of $%s is recursive" % k;
126 self.in_progress[k] = 1;
127 v = self.do_get(k, len(self.stk)-1)
128 del self.in_progress[k]
131 def do_get(self, k, pos):
134 if cfg.vars.has_key(k):
137 v = self.do_get(k, pos-1)
152 for k in cfg.vars.keys():
156 def dump(self, file=sys.stdout):
157 for k in self.keys():
159 file.write("%s=%s\n" % (k,v))
161 def dump_defs(self, file=sys.stdout):
162 file.write("Configuration stack:\n")
166 file.write("(level %d)\n" % level)
168 file.write("(end)\n")
170 def apply_overrides(self, prefix):
175 for k in cfg.vars.keys():
176 if k.startswith(prefix):
177 over.vars[k[len(prefix):]] = cfg.vars[k]
181 for k in cfg.vars.keys():
182 if not k.startswith(prefix):
183 clean.vars[k] = cfg.vars[k]