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