eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/config.py
changeset 69 c6bca38c1cbf
equal deleted inserted replaced
68:5ff1fc726848 69:c6bca38c1cbf
       
     1 # config.py - configuration parsing for Mercurial
       
     2 #
       
     3 #  Copyright 2009 Matt Mackall <mpm@selenic.com> and others
       
     4 #
       
     5 # This software may be used and distributed according to the terms of the
       
     6 # GNU General Public License version 2 or any later version.
       
     7 
       
     8 from i18n import _
       
     9 import error, util
       
    10 import re, os
       
    11 
       
    12 class sortdict(dict):
       
    13     'a simple sorted dictionary'
       
    14     def __init__(self, data=None):
       
    15         self._list = []
       
    16         if data:
       
    17             self.update(data)
       
    18     def copy(self):
       
    19         return sortdict(self)
       
    20     def __setitem__(self, key, val):
       
    21         if key in self:
       
    22             self._list.remove(key)
       
    23         self._list.append(key)
       
    24         dict.__setitem__(self, key, val)
       
    25     def __iter__(self):
       
    26         return self._list.__iter__()
       
    27     def update(self, src):
       
    28         for k in src:
       
    29             self[k] = src[k]
       
    30     def items(self):
       
    31         return [(k, self[k]) for k in self._list]
       
    32     def __delitem__(self, key):
       
    33         dict.__delitem__(self, key)
       
    34         self._list.remove(key)
       
    35 
       
    36 class config(object):
       
    37     def __init__(self, data=None):
       
    38         self._data = {}
       
    39         self._source = {}
       
    40         if data:
       
    41             for k in data._data:
       
    42                 self._data[k] = data[k].copy()
       
    43             self._source = data._source.copy()
       
    44     def copy(self):
       
    45         return config(self)
       
    46     def __contains__(self, section):
       
    47         return section in self._data
       
    48     def __getitem__(self, section):
       
    49         return self._data.get(section, {})
       
    50     def __iter__(self):
       
    51         for d in self.sections():
       
    52             yield d
       
    53     def update(self, src):
       
    54         for s in src:
       
    55             if s not in self:
       
    56                 self._data[s] = sortdict()
       
    57             self._data[s].update(src._data[s])
       
    58         self._source.update(src._source)
       
    59     def get(self, section, item, default=None):
       
    60         return self._data.get(section, {}).get(item, default)
       
    61     def source(self, section, item):
       
    62         return self._source.get((section, item), "")
       
    63     def sections(self):
       
    64         return sorted(self._data.keys())
       
    65     def items(self, section):
       
    66         return self._data.get(section, {}).items()
       
    67     def set(self, section, item, value, source=""):
       
    68         if section not in self:
       
    69             self._data[section] = sortdict()
       
    70         self._data[section][item] = value
       
    71         self._source[(section, item)] = source
       
    72 
       
    73     def parse(self, src, data, sections=None, remap=None, include=None):
       
    74         sectionre = re.compile(r'\[([^\[]+)\]')
       
    75         itemre = re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
       
    76         contre = re.compile(r'\s+(\S|\S.*\S)\s*$')
       
    77         emptyre = re.compile(r'(;|#|\s*$)')
       
    78         unsetre = re.compile(r'%unset\s+(\S+)')
       
    79         includere = re.compile(r'%include\s+(\S|\S.*\S)\s*$')
       
    80         section = ""
       
    81         item = None
       
    82         line = 0
       
    83         cont = False
       
    84 
       
    85         for l in data.splitlines(True):
       
    86             line += 1
       
    87             if cont:
       
    88                 m = contre.match(l)
       
    89                 if m:
       
    90                     if sections and section not in sections:
       
    91                         continue
       
    92                     v = self.get(section, item) + "\n" + m.group(1)
       
    93                     self.set(section, item, v, "%s:%d" % (src, line))
       
    94                     continue
       
    95                 item = None
       
    96                 cont = False
       
    97             m = includere.match(l)
       
    98             if m:
       
    99                 inc = util.expandpath(m.group(1))
       
   100                 base = os.path.dirname(src)
       
   101                 inc = os.path.normpath(os.path.join(base, inc))
       
   102                 if include:
       
   103                     try:
       
   104                         include(inc, remap=remap, sections=sections)
       
   105                     except IOError, inst:
       
   106                         raise error.ParseError(_("cannot include %s (%s)")
       
   107                                                % (inc, inst.strerror),
       
   108                                                "%s:%s" % (src, line))
       
   109                 continue
       
   110             if emptyre.match(l):
       
   111                 continue
       
   112             m = sectionre.match(l)
       
   113             if m:
       
   114                 section = m.group(1)
       
   115                 if remap:
       
   116                     section = remap.get(section, section)
       
   117                 if section not in self:
       
   118                     self._data[section] = sortdict()
       
   119                 continue
       
   120             m = itemre.match(l)
       
   121             if m:
       
   122                 item = m.group(1)
       
   123                 cont = True
       
   124                 if sections and section not in sections:
       
   125                     continue
       
   126                 self.set(section, item, m.group(2), "%s:%d" % (src, line))
       
   127                 continue
       
   128             m = unsetre.match(l)
       
   129             if m:
       
   130                 name = m.group(1)
       
   131                 if sections and section not in sections:
       
   132                     continue
       
   133                 if self.get(section, name) != None:
       
   134                     del self._data[section][name]
       
   135                 continue
       
   136 
       
   137             raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
       
   138 
       
   139     def read(self, path, fp=None, sections=None, remap=None):
       
   140         if not fp:
       
   141             fp = open(path)
       
   142         self.parse(path, fp.read(), sections, remap, self.read)