##// END OF EJS Templates
spelling: value
timeless@mozdev.org -
r17527:6e11d5cf default
parent child Browse files
Show More
@@ -1,183 +1,183
1 1 # config.py - configuration parsing for Mercurial
2 2 #
3 3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from i18n import _
9 9 import error, util
10 10 import os, errno
11 11
12 12 class sortdict(dict):
13 13 'a simple sorted dictionary'
14 14 def __init__(self, data=None):
15 15 self._list = []
16 16 if data:
17 17 self.update(data)
18 18 def copy(self):
19 19 return sortdict(self)
20 20 def __setitem__(self, key, val):
21 21 if key in self:
22 22 self._list.remove(key)
23 23 self._list.append(key)
24 24 dict.__setitem__(self, key, val)
25 25 def __iter__(self):
26 26 return self._list.__iter__()
27 27 def update(self, src):
28 28 for k in src:
29 29 self[k] = src[k]
30 30 def clear(self):
31 31 dict.clear(self)
32 32 self._list = []
33 33 def items(self):
34 34 return [(k, self[k]) for k in self._list]
35 35 def __delitem__(self, key):
36 36 dict.__delitem__(self, key)
37 37 self._list.remove(key)
38 38 def keys(self):
39 39 return self._list
40 40 def iterkeys(self):
41 41 return self._list.__iter__()
42 42
43 43 class config(object):
44 44 def __init__(self, data=None):
45 45 self._data = {}
46 46 self._source = {}
47 47 if data:
48 48 for k in data._data:
49 49 self._data[k] = data[k].copy()
50 50 self._source = data._source.copy()
51 51 def copy(self):
52 52 return config(self)
53 53 def __contains__(self, section):
54 54 return section in self._data
55 55 def __getitem__(self, section):
56 56 return self._data.get(section, {})
57 57 def __iter__(self):
58 58 for d in self.sections():
59 59 yield d
60 60 def update(self, src):
61 61 for s in src:
62 62 if s not in self:
63 63 self._data[s] = sortdict()
64 64 self._data[s].update(src._data[s])
65 65 self._source.update(src._source)
66 66 def get(self, section, item, default=None):
67 67 return self._data.get(section, {}).get(item, default)
68 68
69 69 def backup(self, section, item):
70 """return a tuple allowing restore to reinstall a previous valuesi
70 """return a tuple allowing restore to reinstall a previous value
71 71
72 72 The main reason we need it is because it handle the "no data" case.
73 73 """
74 74 try:
75 75 value = self._data[section][item]
76 76 source = self.source(section, item)
77 77 return (section, item, value, source)
78 78 except KeyError:
79 79 return (section, item)
80 80
81 81 def source(self, section, item):
82 82 return self._source.get((section, item), "")
83 83 def sections(self):
84 84 return sorted(self._data.keys())
85 85 def items(self, section):
86 86 return self._data.get(section, {}).items()
87 87 def set(self, section, item, value, source=""):
88 88 if section not in self:
89 89 self._data[section] = sortdict()
90 90 self._data[section][item] = value
91 91 self._source[(section, item)] = source
92 92
93 93 def restore(self, data):
94 94 """restore data returned by self.backup"""
95 95 if len(data) == 4:
96 96 # restore old data
97 97 section, item, value, source = data
98 98 self._data[section][item] = value
99 99 self._source[(section, item)] = source
100 100 else:
101 101 # no data before, remove everything
102 102 section, item = data
103 103 if section in self._data:
104 104 del self._data[section][item]
105 105 self._source.pop((section, item), None)
106 106
107 107 def parse(self, src, data, sections=None, remap=None, include=None):
108 108 sectionre = util.compilere(r'\[([^\[]+)\]')
109 109 itemre = util.compilere(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
110 110 contre = util.compilere(r'\s+(\S|\S.*\S)\s*$')
111 111 emptyre = util.compilere(r'(;|#|\s*$)')
112 112 commentre = util.compilere(r'(;|#)')
113 113 unsetre = util.compilere(r'%unset\s+(\S+)')
114 114 includere = util.compilere(r'%include\s+(\S|\S.*\S)\s*$')
115 115 section = ""
116 116 item = None
117 117 line = 0
118 118 cont = False
119 119
120 120 for l in data.splitlines(True):
121 121 line += 1
122 122 if line == 1 and l.startswith('\xef\xbb\xbf'):
123 123 # Someone set us up the BOM
124 124 l = l[3:]
125 125 if cont:
126 126 if commentre.match(l):
127 127 continue
128 128 m = contre.match(l)
129 129 if m:
130 130 if sections and section not in sections:
131 131 continue
132 132 v = self.get(section, item) + "\n" + m.group(1)
133 133 self.set(section, item, v, "%s:%d" % (src, line))
134 134 continue
135 135 item = None
136 136 cont = False
137 137 m = includere.match(l)
138 138 if m:
139 139 inc = util.expandpath(m.group(1))
140 140 base = os.path.dirname(src)
141 141 inc = os.path.normpath(os.path.join(base, inc))
142 142 if include:
143 143 try:
144 144 include(inc, remap=remap, sections=sections)
145 145 except IOError, inst:
146 146 if inst.errno != errno.ENOENT:
147 147 raise error.ParseError(_("cannot include %s (%s)")
148 148 % (inc, inst.strerror),
149 149 "%s:%s" % (src, line))
150 150 continue
151 151 if emptyre.match(l):
152 152 continue
153 153 m = sectionre.match(l)
154 154 if m:
155 155 section = m.group(1)
156 156 if remap:
157 157 section = remap.get(section, section)
158 158 if section not in self:
159 159 self._data[section] = sortdict()
160 160 continue
161 161 m = itemre.match(l)
162 162 if m:
163 163 item = m.group(1)
164 164 cont = True
165 165 if sections and section not in sections:
166 166 continue
167 167 self.set(section, item, m.group(2), "%s:%d" % (src, line))
168 168 continue
169 169 m = unsetre.match(l)
170 170 if m:
171 171 name = m.group(1)
172 172 if sections and section not in sections:
173 173 continue
174 174 if self.get(section, name) is not None:
175 175 del self._data[section][name]
176 176 continue
177 177
178 178 raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
179 179
180 180 def read(self, path, fp=None, sections=None, remap=None):
181 181 if not fp:
182 182 fp = util.posixfile(path)
183 183 self.parse(path, fp.read(), sections, remap, self.read)
General Comments 0
You need to be logged in to leave comments. Login now