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:
23 self.load(open(name, 'r'))
26 for x in file.readlines():
27 x = x.rstrip("\n").lstrip(" \t")
28 if x=='' or x.startswith('#'):
37 if not self.cfg.has_key(k):
38 self.cfg[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.cfg[k].append(('s', v[:-1]))
48 elif v.startswith('"'):
50 if not v.endswith('"'):
51 raise MoeConfigInvalid, "Misquoted string"
52 self.parse_interpolated(self.cfg[k], v[:-1])
54 self.cfg[k].append(('s', v))
56 ## FIXME: Report line numbers
57 raise MoeConfigInvalid, "Parse error"
59 def parse_interpolated(self, list, s):
66 raise MoeConfigInvalid, "Unbalanced braces"
67 k, s = s[1:p], s[p+1:]
68 if not key_pattern.match(k):
69 raise MoeConfigInvalid, "Invalid variable name"
71 m = ref_pattern.match(s)
73 k, s = s[:m.end()], s[m.end():]
75 raise MoeConfigInvalid, "Invalid variable reference"
81 list.append(('s', s[:p]))
84 def dump(self, file=sys.stdout):
85 for k,v in self.cfg.items():
87 if len(v) > 0 and v[0][0] == 'a':
93 file.write("'" + w + "'")
95 file.write('"$' + w + '"')
99 """Stack of configuration files."""
101 def __init__(self, base=None):
102 ## FIXME: Do we need to duplicate the config files themselves?
104 self.stk = base.stk[:]
107 self.in_progress = {}
112 def __getitem__(self, k):
113 if self.in_progress.has_key(k):
114 raise MoeConfigEvalErr, "Definition of $%s is recursive" % k;
115 self.in_progress[k] = 1;
116 v = self.do_get(k, len(self.stk)-1)
117 del self.in_progress[k]
120 def do_get(self, k, pos):
123 if cfg.cfg.has_key(k):
126 v = self.do_get(k, pos-1)