diff python/simpleini.py @ 113:44534594f402

add variable interpolation
author Jeff Hammel <jhammel@mozilla.com>
date Thu, 02 Dec 2010 13:04:54 -0800
parents e85298a35998
children 9b193312ceba
line wrap: on
line diff
--- a/python/simpleini.py	Thu Dec 02 09:53:29 2010 -0800
+++ b/python/simpleini.py	Thu Dec 02 13:04:54 2010 -0800
@@ -2,20 +2,38 @@
 
 import os
 
-def read(fp, comments=';#', separators=('=', ':')):
+def read(fp, variables=None, default='DEFAULT',
+         comments=';#', separators=('=', ':'), strict=True):
+  """
+  read an .ini file and return a list of [(section, values)]
+  - fp : file pointer or name to read
+  - variables : default set of variables
+  - default : name of the section for the default section
+  - comments : characters that if they start a line denote a comment
+  - separators : strings that denote key, value separation in order
+  - strict : whether to be strict about parsing
+  """
+
+  if variables is None:
+    variables = {}
+  variables = variables.copy() # no reason to overwrite the originals
 
   if isinstance(fp, basestring):
     fp = file(fp)
 
   sections = []
   key = value = None
-  
+  section_names = set([])
+
+  # read the lines
   for line in fp.readlines():
 
     stripped = line.strip()
 
     # ignore blank lines
     if not stripped:
+      # XXX should probably reset key and value to avoid continuation lines
+      key = value = None
       continue
 
     # ignore comment lines
@@ -25,13 +43,28 @@
     # check for a new section
     if len(stripped) > 2 and stripped[0] == '[' and stripped[-1] == ']':
       section = stripped[1:-1].strip()
-      sections.append((section, {}))
       key = value = None
-      # TODO: should probably make sure this section doesn't already exist
+
+      # deal with DEFAULT section
+      if section.lower() == default.lower():
+        if strict:
+          assert default not in section_names
+        section_names.add(default)
+        current_section = variables
+        continue
+
+      if strict:
+        # make sure this section doesn't already exist
+        assert section not in section_names
+
+      section_names.add(section)
+
+      current_section = {}
+      sections.append((section, current_section))
       continue
 
     # if there aren't any sections yet, something bad happen
-    if not sections:
+    if not section_names:
       raise Exception('No sections yet :(')
 
     # (key, value) pair
@@ -40,18 +73,32 @@
         key, value = stripped.split(separator, 1)
         key = key.strip()
         value = value.strip()
-        sections[-1][1][key] = value
-        # TODO: should probably make sure this key isn't already in the section
+
+        if strict:
+          # make sure this key isn't already in the section or empty
+          assert key
+          if current_section is not variables:
+            assert key not in current_section
+        
+        current_section[key] = value
         break
     else:
       # continuation line ?
       if line[0].isspace() and key:
         value = '%s%s%s' % (value, os.linesep, stripped)
-        sections[-1][1][key] = value
+        current_section[key] = value
       else:
         # something bad happen!
         raise Exception("Not sure what you're trying to do")
 
+  # interpret the variables
+  def interpret_variables(global_dict, local_dict):
+    variables = global_dict.copy()
+    variables.update(local_dict)
+    # TODO: string intepolation
+    return variables
+
+  sections = [(i, interpret_variables(variables, j)) for i, j in sections]
   return sections
 
 if __name__ == '__main__':