blob: f22306a720163d661ef8b8a1ce0db61730abfc8f [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
31 interpolation. Note that `name' is
32 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):
90 def __init__(self, reference, option, section):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000091 Error.__init__(self,
92 "Bad value substitution: sect `%s', opt `%s', ref `%s'"
93 % (section, option, reference))
94 self.reference = reference
95 self.option = option
96 self.section = section
Guido van Rossum3d209861997-12-09 16:10:31 +000097
Barry Warsawbfa3f6b1998-07-01 20:41:12 +000098class MissingSectionHeaderError(Error):
99 def __init__(self, filename, lineno, line):
100 Error.__init__(
101 self,
102 'File contains no section headers.\nfile: %s, line: %d\n%s' %
103 (filename, lineno, line))
104 self.filename = filename
105 self.lineno = lineno
106 self.line = line
107
108class ParsingError(Error):
109 def __init__(self, filename):
110 Error.__init__(self, 'File contains parsing errors: %s' % filename)
111 self.filename = filename
112 self.errors = []
113
114 def append(self, lineno, line):
115 self.errors.append((lineno, line))
116 self._msg = self._msg + '\n\t[line %2d]: %s' % (lineno, line)
117
Guido van Rossum3d209861997-12-09 16:10:31 +0000118
119
120class ConfigParser:
121 def __init__(self, defaults=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000122 self.__sections = {}
123 if defaults is None:
124 self.__defaults = {}
125 else:
126 self.__defaults = defaults
Guido van Rossum3d209861997-12-09 16:10:31 +0000127
128 def defaults(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000129 return self.__defaults
Guido van Rossum3d209861997-12-09 16:10:31 +0000130
131 def sections(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000132 """Return a list of section names, excluding [DEFAULT]"""
133 # self.__sections will never have [DEFAULT] in it
134 return self.__sections.keys()
Guido van Rossum3d209861997-12-09 16:10:31 +0000135
136 def add_section(self, section):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000137 """Create a new section in the configuration.
Guido van Rossum3d209861997-12-09 16:10:31 +0000138
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000139 Raise DuplicateSectionError if a section by the specified name
140 already exists.
141 """
142 if self.__sections.has_key(section):
143 raise DuplicateSectionError(section)
144 self.__sections[section] = {}
Guido van Rossum3d209861997-12-09 16:10:31 +0000145
146 def has_section(self, section):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000147 """Indicate whether the named section is present in the configuration.
Guido van Rossum3d209861997-12-09 16:10:31 +0000148
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000149 The DEFAULT section is not acknowledged.
150 """
151 return self.__sections.has_key(section)
Guido van Rossum3d209861997-12-09 16:10:31 +0000152
153 def options(self, section):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000154 try:
155 opts = self.__sections[section].copy()
156 except KeyError:
157 raise NoSectionError(section)
158 opts.update(self.__defaults)
159 return opts.keys()
Guido van Rossum3d209861997-12-09 16:10:31 +0000160
161 def read(self, filenames):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000162 """Read and parse a list of filenames."""
163 if type(filenames) is type(''):
164 filenames = [filenames]
165 for file in filenames:
166 try:
167 fp = open(file, 'r')
168 self.__read(fp)
169 except IOError:
170 pass
Guido van Rossum3d209861997-12-09 16:10:31 +0000171
172 def get(self, section, option, raw=0):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000173 """Get an option value for a given section.
Guido van Rossum3d209861997-12-09 16:10:31 +0000174
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000175 All % interpolations are expanded in the return values, based
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000176 on the defaults passed into the constructor, unless the optional
177 argument `raw' is true.
Guido van Rossum3d209861997-12-09 16:10:31 +0000178
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000179 The section DEFAULT is special.
180 """
181 try:
182 sectdict = self.__sections[section].copy()
183 except KeyError:
184 if section == DEFAULTSECT:
185 sectdict = {}
186 else:
187 raise NoSectionError(section)
188 d = self.__defaults.copy()
189 d.update(sectdict)
190 option = string.lower(option)
191 try:
192 rawval = d[option]
193 except KeyError:
194 raise NoOptionError(option, section)
195 # do the string interpolation
196 if raw:
197 return rawval
198 try:
199 return rawval % d
200 except KeyError, key:
201 raise InterpolationError(key, option, section)
Guido van Rossum3d209861997-12-09 16:10:31 +0000202
203 def __get(self, section, conv, option):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000204 return conv(self.get(section, option))
Guido van Rossum3d209861997-12-09 16:10:31 +0000205
206 def getint(self, section, option):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000207 return self.__get(section, string.atoi, option)
Guido van Rossum3d209861997-12-09 16:10:31 +0000208
209 def getfloat(self, section, option):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000210 return self.__get(section, string.atof, option)
Guido van Rossum3d209861997-12-09 16:10:31 +0000211
212 def getboolean(self, section, option):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000213 v = self.get(section, option)
214 val = string.atoi(v)
215 if val not in (0, 1):
216 raise ValueError, 'Not a boolean: %s' % v
217 return val
Guido van Rossum3d209861997-12-09 16:10:31 +0000218
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000219 #
220 # Regular expressions for parsing section headers and options. Note a
221 # slight semantic change from the previous version, because of the use
222 # of \w, _ is allowed in section header names.
223 __SECTCRE = re.compile(
224 r'\[' # [
225 r'(?P<header>[-\w]+)' # `-', `_' or any alphanum
226 r'\]' # ]
227 )
228 __OPTCRE = re.compile(
229 r'(?P<option>[-.\w]+)' # - . _ alphanum
230 r'[ \t]*[:=][ \t]*' # any number of space/tab,
231 # followed by separator
232 # (either : or =), followed
233 # by any # space/tab
234 r'(?P<value>.*)$' # everything up to eol
235 )
236
Guido van Rossum3d209861997-12-09 16:10:31 +0000237 def __read(self, fp):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000238 """Parse a sectioned setup file.
Guido van Rossum3d209861997-12-09 16:10:31 +0000239
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000240 The sections in setup file contains a title line at the top,
241 indicated by a name in square brackets (`[]'), plus key/value
242 options lines, indicated by `name: value' format lines.
243 Continuation are represented by an embedded newline then
244 leading whitespace. Blank lines, lines beginning with a '#',
245 and just about everything else is ignored.
246 """
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000247 cursect = None # None, or a dictionary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000248 optname = None
249 lineno = 0
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000250 e = None # None, or an exception
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000251 while 1:
252 line = fp.readline()
253 if not line:
254 break
255 lineno = lineno + 1
256 # comment or blank line?
257 if string.strip(line) == '' or line[0] in '#;':
258 continue
259 if string.lower(string.split(line)[0]) == 'rem' \
260 and line[0] == "r": # no leading whitespace
261 continue
262 # continuation line?
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000263 if line[0] in ' \t' and cursect is not None and optname:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000264 value = string.strip(line)
265 if value:
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000266 cursect[optname] = cursect[optname] + '\n ' + value
267 # a section header or option header?
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000268 else:
Barry Warsawbfa3f6b1998-07-01 20:41:12 +0000269 # is it a section header?
270 mo = self.__SECTCRE.match(line)
271 if mo:
272 sectname = mo.group('header')
273 if self.__sections.has_key(sectname):
274 cursect = self.__sections[sectname]
275 elif sectname == DEFAULTSECT:
276 cursect = self.__defaults
277 else:
278 cursect = {}
279 self.__sections[sectname] = cursect
280 # So sections can't start with a continuation line
281 optname = None
282 # no section header in the file?
283 elif cursect is None:
284 raise MissingSectionHeaderError(fp.name, lineno, `line`)
285 # an option line?
286 else:
287 mo = self.__OPTCRE.match(line)
288 if mo:
289 optname, optval = mo.group('option', 'value')
290 optname = string.lower(optname)
291 optval = string.strip(optval)
292 # allow empty values
293 if optval == '""':
294 optval = ''
295 cursect[optname] = optval
296 else:
297 # a non-fatal parsing error occurred. set up the
298 # exception but keep going. the exception will be
299 # raised at the end of the file and will contain a
300 # list of all bogus lines
301 if not e:
302 e = ParsingError(fp.name)
303 e.append(lineno, `line`)
304 # if any parsing errors occurred, raise an exception
305 if e:
306 raise e