blob: 89e2d851f1b44a2b999e31977c4dea83198d2685 [file] [log] [blame]
Guido van Rossum3d209861997-12-09 16:10:31 +00001"""Configuration file parser.
2
3A setup file consists of sections, lead by a "[section]" header,
4and followed by "name: value" entries, with continuations and such in
Barry Warsawbfa3f6b1998-07-01 20:41:12 +00005the style of RFC 822.
Guido van Rossum3d209861997-12-09 16:10:31 +00006
Barry Warsawbfa3f6b1998-07-01 20:41:12 +00007The option values can contain format strings which refer to other values in
8the same section, or values in a special [DEFAULT] section.
9
Guido van Rossum3d209861997-12-09 16:10:31 +000010For example:
11
12 something: %(dir)s/whatever
13
14would resolve the "%(dir)s" to the value of dir. All reference
15expansions are done late, on demand.
16
17Intrinsic defaults can be specified by passing them into the
18ConfigParser constructor as a dictionary.
19
20class:
21
22ConfigParser -- responsible for for parsing a list of
23 configuration files, and managing the parsed database.
24
25 methods:
26
27 __init__(defaults=None) -- create the parser and specify a
28 dictionary of intrinsic defaults. The
29 keys must be strings, the values must
30 be appropriate for %()s string
Barry Warsaw64462121998-08-06 18:48:41 +000031 interpolation. Note that `__name__' is
Guido van Rossum3d209861997-12-09 16:10:31 +000032 always an intrinsic default; it's value
33 is the section's name.
34
35 sections() -- return all the configuration section names, sans DEFAULT
36
37 options(section) -- return list of configuration options for the named
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000038 section
Guido van Rossum3d209861997-12-09 16:10:31 +000039
40 read(*filenames) -- read and parse the list of named configuration files
41
42 get(section, option, raw=0) -- return a string value for the named
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000043 option. All % interpolations are
44 expanded in the return values, based on
45 the defaults passed into the constructor
46 and the DEFAULT section.
Guido van Rossum3d209861997-12-09 16:10:31 +000047
48 getint(section, options) -- like get(), but convert value to an integer
49
50 getfloat(section, options) -- like get(), but convert value to a float
51
52 getboolean(section, options) -- like get(), but convert value to
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000053 a boolean (currently defined as 0
54 or 1, only)
Guido van Rossum3d209861997-12-09 16:10:31 +000055"""
56
57import sys
58import string
Barry Warsawbfa3f6b1998-07-01 20:41:12 +000059import re
Guido van Rossum3d209861997-12-09 16:10:31 +000060
61DEFAULTSECT = "DEFAULT"
62
63
64
65# exception classes
66class Error:
67 def __init__(self, msg=''):
Barry Warsawbfa3f6b1998-07-01 20:41:12 +000068 self._msg = msg
Guido van Rossum3d209861997-12-09 16:10:31 +000069 def __repr__(self):
Barry Warsawbfa3f6b1998-07-01 20:41:12 +000070 return self._msg
Guido van Rossum3d209861997-12-09 16:10:31 +000071
72class NoSectionError(Error):
73 def __init__(self, section):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000074 Error.__init__(self, 'No section: %s' % section)
75 self.section = section
Guido van Rossum3d209861997-12-09 16:10:31 +000076
77class DuplicateSectionError(Error):
78 def __init__(self, section):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000079 Error.__init__(self, "Section %s already exists" % section)
80 self.section = section
Guido van Rossum3d209861997-12-09 16:10:31 +000081
82class NoOptionError(Error):
83 def __init__(self, option, section):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000084 Error.__init__(self, "No option `%s' in section: %s" %
85 (option, section))
86 self.option = option
87 self.section = section
Guido van Rossum3d209861997-12-09 16:10:31 +000088
89class InterpolationError(Error):
Barry Warsaw64462121998-08-06 18:48:41 +000090 def __init__(self, reference, option, section, rawval):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000091 Error.__init__(self,
Barry Warsaw64462121998-08-06 18:48:41 +000092 "Bad value substitution:\n"
93 "\tsection: [%s]\n"
94 "\toption : %s\n"
95 "\tkey : %s\n"
96 "\trawval : %s\n"
97 % (section, option, reference, rawval))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000098 self.reference = reference
99 self.option = option
100 self.section = section
Guido van Rossum3d209861997-12-09 16:10:31 +0000101
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000102class MissingSectionHeaderError(Error):
103 def __init__(self, filename, lineno, line):
104 Error.__init__(
105 self,
106 'File contains no section headers.\nfile: %s, line: %d\n%s' %
107 (filename, lineno, line))
108 self.filename = filename
109 self.lineno = lineno
110 self.line = line
111
112class ParsingError(Error):
113 def __init__(self, filename):
114 Error.__init__(self, 'File contains parsing errors: %s' % filename)
115 self.filename = filename
116 self.errors = []
117
118 def append(self, lineno, line):
119 self.errors.append((lineno, line))
120 self._msg = self._msg + '\n\t[line %2d]: %s' % (lineno, line)
121
Guido van Rossum3d209861997-12-09 16:10:31 +0000122
123
124class ConfigParser:
125 def __init__(self, defaults=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000126 self.__sections = {}
127 if defaults is None:
128 self.__defaults = {}
129 else:
130 self.__defaults = defaults
Guido van Rossum3d209861997-12-09 16:10:31 +0000131
132 def defaults(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 return self.__defaults
Guido van Rossum3d209861997-12-09 16:10:31 +0000134
135 def sections(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000136 """Return a list of section names, excluding [DEFAULT]"""
137 # self.__sections will never have [DEFAULT] in it
138 return self.__sections.keys()
Guido van Rossum3d209861997-12-09 16:10:31 +0000139
140 def add_section(self, section):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000141 """Create a new section in the configuration.
Guido van Rossum3d209861997-12-09 16:10:31 +0000142
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000143 Raise DuplicateSectionError if a section by the specified name
144 already exists.
145 """
146 if self.__sections.has_key(section):
147 raise DuplicateSectionError(section)
148 self.__sections[section] = {}
Guido van Rossum3d209861997-12-09 16:10:31 +0000149
150 def has_section(self, section):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000151 """Indicate whether the named section is present in the configuration.
Guido van Rossum3d209861997-12-09 16:10:31 +0000152
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000153 The DEFAULT section is not acknowledged.
154 """
155 return self.__sections.has_key(section)
Guido van Rossum3d209861997-12-09 16:10:31 +0000156
157 def options(self, section):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000158 try:
159 opts = self.__sections[section].copy()
160 except KeyError:
161 raise NoSectionError(section)
162 opts.update(self.__defaults)
163 return opts.keys()
Guido van Rossum3d209861997-12-09 16:10:31 +0000164
165 def read(self, filenames):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000166 """Read and parse a list of filenames."""
167 if type(filenames) is type(''):
168 filenames = [filenames]
169 for file in filenames:
170 try:
171 fp = open(file, 'r')
172 self.__read(fp)
173 except IOError:
174 pass
Guido van Rossum3d209861997-12-09 16:10:31 +0000175
176 def get(self, section, option, raw=0):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000177 """Get an option value for a given section.
Guido van Rossum3d209861997-12-09 16:10:31 +0000178
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000179 All % interpolations are expanded in the return values, based
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000180 on the defaults passed into the constructor, unless the optional
181 argument `raw' is true.
Guido van Rossum3d209861997-12-09 16:10:31 +0000182
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000183 The section DEFAULT is special.
184 """
185 try:
186 sectdict = self.__sections[section].copy()
187 except KeyError:
188 if section == DEFAULTSECT:
189 sectdict = {}
190 else:
191 raise NoSectionError(section)
192 d = self.__defaults.copy()
193 d.update(sectdict)
194 option = string.lower(option)
195 try:
196 rawval = d[option]
197 except KeyError:
198 raise NoOptionError(option, section)
199 # do the string interpolation
200 if raw:
201 return rawval
202 try:
203 return rawval % d
204 except KeyError, key:
Barry Warsaw64462121998-08-06 18:48:41 +0000205 raise InterpolationError(key, option, section, rawval)
Guido van Rossum3d209861997-12-09 16:10:31 +0000206
207 def __get(self, section, conv, option):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000208 return conv(self.get(section, option))
Guido van Rossum3d209861997-12-09 16:10:31 +0000209
210 def getint(self, section, option):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000211 return self.__get(section, string.atoi, option)
Guido van Rossum3d209861997-12-09 16:10:31 +0000212
213 def getfloat(self, section, option):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000214 return self.__get(section, string.atof, option)
Guido van Rossum3d209861997-12-09 16:10:31 +0000215
216 def getboolean(self, section, option):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000217 v = self.get(section, option)
218 val = string.atoi(v)
219 if val not in (0, 1):
220 raise ValueError, 'Not a boolean: %s' % v
221 return val
Guido van Rossum3d209861997-12-09 16:10:31 +0000222
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000223 #
224 # Regular expressions for parsing section headers and options. Note a
225 # slight semantic change from the previous version, because of the use
226 # of \w, _ is allowed in section header names.
227 __SECTCRE = re.compile(
228 r'\[' # [
229 r'(?P<header>[-\w]+)' # `-', `_' or any alphanum
230 r'\]' # ]
231 )
232 __OPTCRE = re.compile(
233 r'(?P<option>[-.\w]+)' # - . _ alphanum
234 r'[ \t]*[:=][ \t]*' # any number of space/tab,
235 # followed by separator
236 # (either : or =), followed
237 # by any # space/tab
238 r'(?P<value>.*)$' # everything up to eol
239 )
240
Guido van Rossum3d209861997-12-09 16:10:31 +0000241 def __read(self, fp):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000242 """Parse a sectioned setup file.
Guido van Rossum3d209861997-12-09 16:10:31 +0000243
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000244 The sections in setup file contains a title line at the top,
245 indicated by a name in square brackets (`[]'), plus key/value
246 options lines, indicated by `name: value' format lines.
247 Continuation are represented by an embedded newline then
248 leading whitespace. Blank lines, lines beginning with a '#',
249 and just about everything else is ignored.
250 """
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000251 cursect = None # None, or a dictionary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000252 optname = None
253 lineno = 0
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000254 e = None # None, or an exception
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000255 while 1:
256 line = fp.readline()
257 if not line:
258 break
259 lineno = lineno + 1
260 # comment or blank line?
261 if string.strip(line) == '' or line[0] in '#;':
262 continue
263 if string.lower(string.split(line)[0]) == 'rem' \
264 and line[0] == "r": # no leading whitespace
265 continue
266 # continuation line?
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000267 if line[0] in ' \t' and cursect is not None and optname:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000268 value = string.strip(line)
269 if value:
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000270 cursect[optname] = cursect[optname] + '\n ' + value
271 # a section header or option header?
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000272 else:
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000273 # is it a section header?
274 mo = self.__SECTCRE.match(line)
275 if mo:
276 sectname = mo.group('header')
277 if self.__sections.has_key(sectname):
278 cursect = self.__sections[sectname]
279 elif sectname == DEFAULTSECT:
280 cursect = self.__defaults
281 else:
Barry Warsaw64462121998-08-06 18:48:41 +0000282 cursect = {'__name__': sectname}
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000283 self.__sections[sectname] = cursect
284 # So sections can't start with a continuation line
285 optname = None
286 # no section header in the file?
287 elif cursect is None:
288 raise MissingSectionHeaderError(fp.name, lineno, `line`)
289 # an option line?
290 else:
291 mo = self.__OPTCRE.match(line)
292 if mo:
293 optname, optval = mo.group('option', 'value')
294 optname = string.lower(optname)
295 optval = string.strip(optval)
296 # allow empty values
297 if optval == '""':
298 optval = ''
299 cursect[optname] = optval
300 else:
301 # a non-fatal parsing error occurred. set up the
302 # exception but keep going. the exception will be
303 # raised at the end of the file and will contain a
304 # list of all bogus lines
305 if not e:
306 e = ParsingError(fp.name)
307 e.append(lineno, `line`)
308 # if any parsing errors occurred, raise an exception
309 if e:
310 raise e