]> mj.ucw.cz Git - moe.git/commitdiff
Added a prototype of the configuration module.
authorMartin Mares <mj@ucw.cz>
Sat, 8 Aug 2009 14:23:44 +0000 (16:23 +0200)
committerMartin Mares <mj@ucw.cz>
Sat, 8 Aug 2009 14:23:44 +0000 (16:23 +0200)
t/moe/config.py
t/test.py

index 3075d8036989a461f47f822499bcec5a4c6a1fc2..3280283e0e3c63add243ee591e463ae935e94185 100644 (file)
 #!/usr/bin/env python
 
+import re
+import sys
+
+key_pattern = re.compile('^[A-Za-z0-9_-]+$')
+ref_pattern = re.compile('^[A-Za-z0-9_-]+')
+
+class MoeConfigInvalid(Exception):
+    pass
+
+class MoeConfigEvalErr(Exception):
+    pass
+
 class MoeConfig:
     """Moe configuration file."""
 
-    def __init__(self):
-        cfg = { 'XYZZY' : 'brum' }
+    def __init__(self, file=None, name=None):
+        self.cfg = {}
+       if file is not None:
+           self.load(file)
+       elif name is not None:
+           self.load(open(name, 'r'))
+
+    def load(self, file):
+       for x in file.readlines():
+           x = x.rstrip("\n").lstrip(" \t")
+           if x=='' or x.startswith('#'):
+               pass
+           else:
+               sep = x.find('=')
+               if sep >= 0:
+                   k = x[:sep]
+                   v = x[sep+1:]
+                   if k.endswith("+"):
+                       k = k[:-1]
+                       if not self.cfg.has_key(k):
+                           self.cfg[k] = [('a','')];
+                   else:
+                       self.cfg[k] = []
+                   if not key_pattern.match(k):
+                       raise MoeConfigInvalid, "Malformed name of configuration variable"
+                   if v.startswith("'"):
+                       v=v[1:]
+                       if not v.endswith("'"):
+                           raise MoeConfigInvalid, "Misquoted string"
+                       self.cfg[k].append(('s', v[:-1]))
+                   elif v.startswith('"'):
+                       v=v[1:]
+                       if not v.endswith('"'):
+                           raise MoeConfigInvalid, "Misquoted string"
+                       self.parse_interpolated(self.cfg[k], v[:-1])
+                   else:
+                       self.cfg[k].append(('s', v))
+               else:
+                   ## FIXME: Report line numbers
+                   raise MoeConfigInvalid, "Parse error"
+
+    def parse_interpolated(self, list, s):
+        while s<>'':
+           if s.startswith('$'):
+               s = s[1:]
+               if s.startswith('{'):
+                   p = s.find('}')
+                   if not p:
+                       raise MoeConfigInvalid, "Unbalanced braces"
+                   k, s = s[1:p], s[p+1:]
+                   if not key_pattern.match(k):
+                       raise MoeConfigInvalid, "Invalid variable name"
+               else:
+                   m = ref_pattern.match(s)
+                   if m:
+                       k, s = s[:m.end()], s[m.end():]
+                   else:
+                       raise MoeConfigInvalid, "Invalid variable reference"
+               list.append(('i', k))
+           else:
+               p = s.find('$')
+               if p < 0:
+                   p = len(s)
+               list.append(('s', s[:p]))
+               s = s[p:]
+
+    def dump(self, file=sys.stdout):
+        for k,v in self.cfg.items():
+           file.write(k)
+           if len(v) > 0 and v[0][0] == 'a':
+               file.write('+')
+               v = v[1:]
+           file.write('=')
+           for t,w in v:
+               if t == 's':
+                   file.write("'" + w + "'")
+               elif t == 'i':
+                   file.write('"$' + w + '"')
+           file.write("\n")
 
 class MoeConfigStack:
     """Stack of configuration files."""
 
-    def __init__(self):
-        stk = []
+    def __init__(self, base=None):
+       ## FIXME: Do we need to duplicate the config files themselves?
+        if base:
+           self.stk = base.stk[:]
+       else:
+           self.stk = []
+       self.in_progress = {}
+
+    def push(self, cfg):
+       self.stk.append(cfg)
+
+    def __getitem__(self, k):
+        if self.in_progress.has_key(k):
+           raise MoeConfigEvalErr, "Definition of $%s is recursive" % k;
+       self.in_progress[k] = 1;
+        v = self.do_get(k, len(self.stk)-1)
+       del self.in_progress[k]
+       return v
+
+    def do_get(self, k, pos):
+        while pos >= 0:
+           cfg = self.stk[pos]
+           if cfg.cfg.has_key(k):
+               new = cfg.cfg[k]
+               if new[0][0] == 'a':
+                   v = self.do_get(k, pos-1)
+               else:
+                   v = ''
+               for op,arg in new:
+                   if op == 's':
+                       v = v + arg
+                   elif op == 'i':
+                       v = v + self[arg]
+               return v
+           pos -= 1
+       return ''
index e928214ac5b7904c61b3c3ad20423f17f1f27dab..2460a214f3989723817bf4507a594243cb1462fe 100755 (executable)
--- a/t/test.py
+++ b/t/test.py
@@ -4,7 +4,20 @@ import sys
 sys.path.append('.')
 
 import moe.meta
+import moe.config
 
-m = moe.meta.MoeMeta()
-m['a'] = '1'
-m.write()
+#m = moe.meta.MoeMeta()
+#m['a'] = '1'
+#m.write()
+
+c = moe.config.MoeConfig(name='/dev/stdin')
+c.dump()
+
+d = moe.config.MoeConfig(name='/dev/stdin')
+d.dump()
+
+s = moe.config.MoeConfigStack()
+s.push(c)
+s.push(d)
+
+print s['a']