# A generic configuration file parser

import os

# master vs user:
# the 'user' hash (~/.foorc) overrides the master hash (/etc/foorc),
# if a value is present in the user hash.

# When writing out, only things *not* equal to the master hash (or only
# in the master hash) are written back out. 

class Config(object):
  # Start a config file, based off a hash - this hash is always a master set
  def __init__(self, data = None):
    self.user = {}
    self.master = {}
    if data != None: self.update(data, True)

  # Update with a dict object, instead of a file.
  def update(self, data, master = False):
    if master: self.master.update(data)
    else: self.user[k].update(data)
        
  def __getitem__(self, key):
    if key in self.user: return self.user[key]
    else: return self.master.get(key)
  
  def __setitem__(self, key, value, master = False):
    if master: self.master[key] = value
    else: self.user[key] = value

  def __delitem__(self, key):
    if key in self.master: del(self.master[key])
    if key in self.user: del(self.user[key])

  def get(self, key, value = None):
    if key in self.user: return self.user[key]
    else: return self.master.get(key, value)

  # Update the config data with a 'key value' filename.
  # If should_exist is true, raise exceptions if the file doesn't exist.
  # Otherwise, we silently ignore it.
  def load(self, filename, master = False, should_exist = False):
    d = self.user
    if master: d = self.master

    if not os.path.isfile(filename) and not should_exist: return

    fi = file(filename, "r")
    for line in fi:
      line = line.strip()
      if not line or line[0] == '#': pass # comment
      else:
        key = line[0:line.find(' ')]
        val = line[line.find(' ') + 1:].strip()
        # Try to cast the input to a nicer type
        try: d[key] = int(val)
        except ValueError:
          try: d[key] = float(val)
          except ValueError: d[key] = val

    fi.close()

  # Write the filename back out to disk.
  def write(self, filename):
    fi = file(filename, "w")
    keys = self.user.keys()
    keys.sort()
    for key in keys:
      if key not in self.master or self.master[key] != self.user[key]:
        fi.write("%s %s\n" % (key, self.user[key]))
    fi.close()
