root / tags / v1_0_2_Build_904 / extensions / extScripting / scripts / jython / Lib / ConfigParser.py @ 10724
History | View | Annotate | Download (16.8 KB)
1 | 5782 | jmvivo | """Configuration file parser.
|
---|---|---|---|
2 |
|
||
3 | A setup file consists of sections, lead by a "[section]" header,
|
||
4 | and followed by "name: value" entries, with continuations and such in
|
||
5 | the style of RFC 822.
|
||
6 |
|
||
7 | The option values can contain format strings which refer to other values in
|
||
8 | the same section, or values in a special [DEFAULT] section.
|
||
9 |
|
||
10 | For example:
|
||
11 |
|
||
12 | something: %(dir)s/whatever
|
||
13 |
|
||
14 | would resolve the "%(dir)s" to the value of dir. All reference
|
||
15 | expansions are done late, on demand.
|
||
16 |
|
||
17 | Intrinsic defaults can be specified by passing them into the
|
||
18 | ConfigParser constructor as a dictionary.
|
||
19 |
|
||
20 | class:
|
||
21 |
|
||
22 | ConfigParser -- responsible for for parsing a list of
|
||
23 | configuration files, and managing the parsed database.
|
||
24 |
|
||
25 | methods:
|
||
26 |
|
||
27 | __init__(defaults=None)
|
||
28 | create the parser and specify a dictionary of intrinsic defaults. The
|
||
29 | keys must be strings, the values must be appropriate for %()s string
|
||
30 | interpolation. Note that `__name__' is always an intrinsic default;
|
||
31 | it's value is the section's name.
|
||
32 |
|
||
33 | sections()
|
||
34 | return all the configuration section names, sans DEFAULT
|
||
35 |
|
||
36 | has_section(section)
|
||
37 | return whether the given section exists
|
||
38 |
|
||
39 | has_option(section, option)
|
||
40 | return whether the given option exists in the given section
|
||
41 |
|
||
42 | options(section)
|
||
43 | return list of configuration options for the named section
|
||
44 |
|
||
45 | has_option(section, option)
|
||
46 | return whether the given section has the given option
|
||
47 |
|
||
48 | read(filenames)
|
||
49 | read and parse the list of named configuration files, given by
|
||
50 | name. A single filename is also allowed. Non-existing files
|
||
51 | are ignored.
|
||
52 |
|
||
53 | readfp(fp, filename=None)
|
||
54 | read and parse one configuration file, given as a file object.
|
||
55 | The filename defaults to fp.name; it is only used in error
|
||
56 | messages (if fp has no `name' attribute, the string `<???>' is used).
|
||
57 |
|
||
58 | get(section, option, raw=0, vars=None)
|
||
59 | return a string value for the named option. All % interpolations are
|
||
60 | expanded in the return values, based on the defaults passed into the
|
||
61 | constructor and the DEFAULT section. Additional substitutions may be
|
||
62 | provided using the `vars' argument, which must be a dictionary whose
|
||
63 | contents override any pre-existing defaults.
|
||
64 |
|
||
65 | getint(section, options)
|
||
66 | like get(), but convert value to an integer
|
||
67 |
|
||
68 | getfloat(section, options)
|
||
69 | like get(), but convert value to a float
|
||
70 |
|
||
71 | getboolean(section, options)
|
||
72 | like get(), but convert value to a boolean (currently defined as 0 or
|
||
73 | 1, only)
|
||
74 |
|
||
75 | remove_section(section)
|
||
76 | remove the given file section and all its options
|
||
77 |
|
||
78 | remove_option(section, option)
|
||
79 | remove the given option from the given section
|
||
80 |
|
||
81 | set(section, option, value)
|
||
82 | set the given option
|
||
83 |
|
||
84 | write(fp)
|
||
85 | write the configuration state in .ini format
|
||
86 | """
|
||
87 | |||
88 | import sys |
||
89 | import string |
||
90 | import re |
||
91 | |||
92 | __all__ = ["NoSectionError","DuplicateSectionError","NoOptionError", |
||
93 | "InterpolationError","InterpolationDepthError","ParsingError", |
||
94 | "MissingSectionHeaderError","ConfigParser", |
||
95 | "MAX_INTERPOLATION_DEPTH"]
|
||
96 | |||
97 | DEFAULTSECT = "DEFAULT"
|
||
98 | |||
99 | MAX_INTERPOLATION_DEPTH = 10
|
||
100 | |||
101 | |||
102 | |||
103 | # exception classes
|
||
104 | class Error(Exception): |
||
105 | def __init__(self, msg=''): |
||
106 | self._msg = msg
|
||
107 | Exception.__init__(self, msg) |
||
108 | def __repr__(self): |
||
109 | return self._msg |
||
110 | __str__ = __repr__ |
||
111 | |||
112 | class NoSectionError(Error): |
||
113 | def __init__(self, section): |
||
114 | Error.__init__(self, 'No section: %s' % section) |
||
115 | self.section = section
|
||
116 | |||
117 | class DuplicateSectionError(Error): |
||
118 | def __init__(self, section): |
||
119 | Error.__init__(self, "Section %s already exists" % section) |
||
120 | self.section = section
|
||
121 | |||
122 | class NoOptionError(Error): |
||
123 | def __init__(self, option, section): |
||
124 | Error.__init__(self, "No option `%s' in section: %s" % |
||
125 | (option, section)) |
||
126 | self.option = option
|
||
127 | self.section = section
|
||
128 | |||
129 | class InterpolationError(Error): |
||
130 | def __init__(self, reference, option, section, rawval): |
||
131 | Error.__init__(self,
|
||
132 | "Bad value substitution:\n"
|
||
133 | "\tsection: [%s]\n"
|
||
134 | "\toption : %s\n"
|
||
135 | "\tkey : %s\n"
|
||
136 | "\trawval : %s\n"
|
||
137 | % (section, option, reference, rawval)) |
||
138 | self.reference = reference
|
||
139 | self.option = option
|
||
140 | self.section = section
|
||
141 | |||
142 | class InterpolationDepthError(Error): |
||
143 | def __init__(self, option, section, rawval): |
||
144 | Error.__init__(self,
|
||
145 | "Value interpolation too deeply recursive:\n"
|
||
146 | "\tsection: [%s]\n"
|
||
147 | "\toption : %s\n"
|
||
148 | "\trawval : %s\n"
|
||
149 | % (section, option, rawval)) |
||
150 | self.option = option
|
||
151 | self.section = section
|
||
152 | |||
153 | class ParsingError(Error): |
||
154 | def __init__(self, filename): |
||
155 | Error.__init__(self, 'File contains parsing errors: %s' % filename) |
||
156 | self.filename = filename
|
||
157 | self.errors = []
|
||
158 | |||
159 | def append(self, lineno, line): |
||
160 | self.errors.append((lineno, line))
|
||
161 | self._msg = self._msg + '\n\t[line %2d]: %s' % (lineno, line) |
||
162 | |||
163 | class MissingSectionHeaderError(ParsingError): |
||
164 | def __init__(self, filename, lineno, line): |
||
165 | Error.__init__( |
||
166 | self,
|
||
167 | 'File contains no section headers.\nfile: %s, line: %d\n%s' %
|
||
168 | (filename, lineno, line)) |
||
169 | self.filename = filename
|
||
170 | self.lineno = lineno
|
||
171 | self.line = line
|
||
172 | |||
173 | |||
174 | |||
175 | class ConfigParser: |
||
176 | def __init__(self, defaults=None): |
||
177 | self.__sections = {}
|
||
178 | if defaults is None: |
||
179 | self.__defaults = {}
|
||
180 | else:
|
||
181 | self.__defaults = defaults
|
||
182 | |||
183 | def defaults(self): |
||
184 | return self.__defaults |
||
185 | |||
186 | def sections(self): |
||
187 | """Return a list of section names, excluding [DEFAULT]"""
|
||
188 | # self.__sections will never have [DEFAULT] in it
|
||
189 | return self.__sections.keys() |
||
190 | |||
191 | def add_section(self, section): |
||
192 | """Create a new section in the configuration.
|
||
193 |
|
||
194 | Raise DuplicateSectionError if a section by the specified name
|
||
195 | already exists.
|
||
196 | """
|
||
197 | if self.__sections.has_key(section): |
||
198 | raise DuplicateSectionError(section)
|
||
199 | self.__sections[section] = {}
|
||
200 | |||
201 | def has_section(self, section): |
||
202 | """Indicate whether the named section is present in the configuration.
|
||
203 |
|
||
204 | The DEFAULT section is not acknowledged.
|
||
205 | """
|
||
206 | return section in self.sections() |
||
207 | |||
208 | def options(self, section): |
||
209 | """Return a list of option names for the given section name."""
|
||
210 | try:
|
||
211 | opts = self.__sections[section].copy()
|
||
212 | except KeyError: |
||
213 | raise NoSectionError(section)
|
||
214 | opts.update(self.__defaults)
|
||
215 | if opts.has_key('__name__'): |
||
216 | del opts['__name__'] |
||
217 | return opts.keys()
|
||
218 | |||
219 | def has_option(self, section, option): |
||
220 | """Return whether the given section has the given option."""
|
||
221 | return option in self.options(section) |
||
222 | |||
223 | def read(self, filenames): |
||
224 | """Read and parse a filename or a list of filenames.
|
||
225 |
|
||
226 | Files that cannot be opened are silently ignored; this is
|
||
227 | designed so that you can specify a list of potential
|
||
228 | configuration file locations (e.g. current directory, user's
|
||
229 | home directory, systemwide directory), and all existing
|
||
230 | configuration files in the list will be read. A single
|
||
231 | filename may also be given.
|
||
232 | """
|
||
233 | if type(filenames) in [type(''), type(u'')]: |
||
234 | filenames = [filenames] |
||
235 | for filename in filenames: |
||
236 | try:
|
||
237 | fp = open(filename)
|
||
238 | except IOError: |
||
239 | continue
|
||
240 | self.__read(fp, filename)
|
||
241 | fp.close() |
||
242 | |||
243 | def readfp(self, fp, filename=None): |
||
244 | """Like read() but the argument must be a file-like object.
|
||
245 |
|
||
246 | The `fp' argument must have a `readline' method. Optional
|
||
247 | second argument is the `filename', which if not given, is
|
||
248 | taken from fp.name. If fp has no `name' attribute, `<???>' is
|
||
249 | used.
|
||
250 |
|
||
251 | """
|
||
252 | if filename is None: |
||
253 | try:
|
||
254 | filename = fp.name |
||
255 | except AttributeError: |
||
256 | filename = '<???>'
|
||
257 | self.__read(fp, filename)
|
||
258 | |||
259 | def get(self, section, option, raw=0, vars=None): |
||
260 | """Get an option value for a given section.
|
||
261 |
|
||
262 | All % interpolations are expanded in the return values, based on the
|
||
263 | defaults passed into the constructor, unless the optional argument
|
||
264 | `raw' is true. Additional substitutions may be provided using the
|
||
265 | `vars' argument, which must be a dictionary whose contents overrides
|
||
266 | any pre-existing defaults.
|
||
267 |
|
||
268 | The section DEFAULT is special.
|
||
269 | """
|
||
270 | try:
|
||
271 | sectdict = self.__sections[section].copy()
|
||
272 | except KeyError: |
||
273 | if section == DEFAULTSECT:
|
||
274 | sectdict = {} |
||
275 | else:
|
||
276 | raise NoSectionError(section)
|
||
277 | d = self.__defaults.copy()
|
||
278 | d.update(sectdict) |
||
279 | # Update with the entry specific variables
|
||
280 | if vars: |
||
281 | d.update(vars)
|
||
282 | option = self.optionxform(option)
|
||
283 | try:
|
||
284 | rawval = d[option] |
||
285 | except KeyError: |
||
286 | raise NoOptionError(option, section)
|
||
287 | |||
288 | if raw:
|
||
289 | return rawval
|
||
290 | |||
291 | # do the string interpolation
|
||
292 | value = rawval # Make it a pretty variable name
|
||
293 | depth = 0
|
||
294 | while depth < 10: # Loop through this until it's done |
||
295 | depth = depth + 1
|
||
296 | if value.find("%(") >= 0: |
||
297 | try:
|
||
298 | value = value % d |
||
299 | except KeyError, key: |
||
300 | raise InterpolationError(key, option, section, rawval)
|
||
301 | else:
|
||
302 | break
|
||
303 | if value.find("%(") >= 0: |
||
304 | raise InterpolationDepthError(option, section, rawval)
|
||
305 | return value
|
||
306 | |||
307 | def __get(self, section, conv, option): |
||
308 | return conv(self.get(section, option)) |
||
309 | |||
310 | def getint(self, section, option): |
||
311 | return self.__get(section, string.atoi, option) |
||
312 | |||
313 | def getfloat(self, section, option): |
||
314 | return self.__get(section, string.atof, option) |
||
315 | |||
316 | def getboolean(self, section, option): |
||
317 | v = self.get(section, option)
|
||
318 | val = int(v)
|
||
319 | if val not in (0, 1): |
||
320 | raise ValueError, 'Not a boolean: %s' % v |
||
321 | return val
|
||
322 | |||
323 | def optionxform(self, optionstr): |
||
324 | return optionstr.lower()
|
||
325 | |||
326 | def has_option(self, section, option): |
||
327 | """Check for the existence of a given option in a given section."""
|
||
328 | if not section or section == "DEFAULT": |
||
329 | return self.__defaults.has_key(option) |
||
330 | elif not self.has_section(section): |
||
331 | return 0 |
||
332 | else:
|
||
333 | option = self.optionxform(option)
|
||
334 | return self.__sections[section].has_key(option) |
||
335 | |||
336 | def set(self, section, option, value): |
||
337 | """Set an option."""
|
||
338 | if not section or section == "DEFAULT": |
||
339 | sectdict = self.__defaults
|
||
340 | else:
|
||
341 | try:
|
||
342 | sectdict = self.__sections[section]
|
||
343 | except KeyError: |
||
344 | raise NoSectionError(section)
|
||
345 | option = self.optionxform(option)
|
||
346 | sectdict[option] = value |
||
347 | |||
348 | def write(self, fp): |
||
349 | """Write an .ini-format representation of the configuration state."""
|
||
350 | if self.__defaults: |
||
351 | fp.write("[DEFAULT]\n")
|
||
352 | for (key, value) in self.__defaults.items(): |
||
353 | fp.write("%s = %s\n" % (key, value))
|
||
354 | fp.write("\n")
|
||
355 | for section in self.sections(): |
||
356 | fp.write("[" + section + "]\n") |
||
357 | sectdict = self.__sections[section]
|
||
358 | for (key, value) in sectdict.items(): |
||
359 | if key == "__name__": |
||
360 | continue
|
||
361 | fp.write("%s = %s\n" % (key, value))
|
||
362 | fp.write("\n")
|
||
363 | |||
364 | def remove_option(self, section, option): |
||
365 | """Remove an option."""
|
||
366 | if not section or section == "DEFAULT": |
||
367 | sectdict = self.__defaults
|
||
368 | else:
|
||
369 | try:
|
||
370 | sectdict = self.__sections[section]
|
||
371 | except KeyError: |
||
372 | raise NoSectionError(section)
|
||
373 | option = self.optionxform(option)
|
||
374 | existed = sectdict.has_key(option) |
||
375 | if existed:
|
||
376 | del sectdict[option]
|
||
377 | return existed
|
||
378 | |||
379 | def remove_section(self, section): |
||
380 | """Remove a file section."""
|
||
381 | if self.__sections.has_key(section): |
||
382 | del self.__sections[section] |
||
383 | return 1 |
||
384 | else:
|
||
385 | return 0 |
||
386 | |||
387 | #
|
||
388 | # Regular expressions for parsing section headers and options. Note a
|
||
389 | # slight semantic change from the previous version, because of the use
|
||
390 | # of \w, _ is allowed in section header names.
|
||
391 | SECTCRE = re.compile( |
||
392 | r'\[' # [ |
||
393 | r'(?P<header>[^]]+)' # very permissive! |
||
394 | r'\]' # ] |
||
395 | ) |
||
396 | OPTCRE = re.compile( |
||
397 | r'(?P<option>[]\-[\w_.*,(){}]+)' # a lot of stuff found by IvL |
||
398 | r'[ \t]*(?P<vi>[:=])[ \t]*' # any number of space/tab, |
||
399 | # followed by separator
|
||
400 | # (either : or =), followed
|
||
401 | # by any # space/tab
|
||
402 | r'(?P<value>.*)$' # everything up to eol |
||
403 | ) |
||
404 | |||
405 | def __read(self, fp, fpname): |
||
406 | """Parse a sectioned setup file.
|
||
407 |
|
||
408 | The sections in setup file contains a title line at the top,
|
||
409 | indicated by a name in square brackets (`[]'), plus key/value
|
||
410 | options lines, indicated by `name: value' format lines.
|
||
411 | Continuation are represented by an embedded newline then
|
||
412 | leading whitespace. Blank lines, lines beginning with a '#',
|
||
413 | and just about everything else is ignored.
|
||
414 | """
|
||
415 | cursect = None # None, or a dictionary |
||
416 | optname = None
|
||
417 | lineno = 0
|
||
418 | e = None # None, or an exception |
||
419 | while 1: |
||
420 | line = fp.readline() |
||
421 | if not line: |
||
422 | break
|
||
423 | lineno = lineno + 1
|
||
424 | # comment or blank line?
|
||
425 | if line.strip() == '' or line[0] in '#;': |
||
426 | continue
|
||
427 | if line.split()[0].lower() == 'rem' \ |
||
428 | and line[0] in "rR": # no leading whitespace |
||
429 | continue
|
||
430 | # continuation line?
|
||
431 | if line[0] in ' \t' and cursect is not None and optname: |
||
432 | value = line.strip() |
||
433 | if value:
|
||
434 | k = self.optionxform(optname)
|
||
435 | cursect[k] = "%s\n%s" % (cursect[k], value)
|
||
436 | # a section header or option header?
|
||
437 | else:
|
||
438 | # is it a section header?
|
||
439 | mo = self.SECTCRE.match(line)
|
||
440 | if mo:
|
||
441 | sectname = mo.group('header')
|
||
442 | if self.__sections.has_key(sectname): |
||
443 | cursect = self.__sections[sectname]
|
||
444 | elif sectname == DEFAULTSECT:
|
||
445 | cursect = self.__defaults
|
||
446 | else:
|
||
447 | cursect = {'__name__': sectname}
|
||
448 | self.__sections[sectname] = cursect
|
||
449 | # So sections can't start with a continuation line
|
||
450 | optname = None
|
||
451 | # no section header in the file?
|
||
452 | elif cursect is None: |
||
453 | raise MissingSectionHeaderError(fpname, lineno, `line`)
|
||
454 | # an option line?
|
||
455 | else:
|
||
456 | mo = self.OPTCRE.match(line)
|
||
457 | if mo:
|
||
458 | optname, vi, optval = mo.group('option', 'vi', 'value') |
||
459 | if vi in ('=', ':') and ';' in optval: |
||
460 | # ';' is a comment delimiter only if it follows
|
||
461 | # a spacing character
|
||
462 | pos = optval.find(';')
|
||
463 | if pos and optval[pos-1] in string.whitespace: |
||
464 | optval = optval[:pos] |
||
465 | optval = optval.strip() |
||
466 | # allow empty values
|
||
467 | if optval == '""': |
||
468 | optval = ''
|
||
469 | cursect[self.optionxform(optname)] = optval
|
||
470 | else:
|
||
471 | # a non-fatal parsing error occurred. set up the
|
||
472 | # exception but keep going. the exception will be
|
||
473 | # raised at the end of the file and will contain a
|
||
474 | # list of all bogus lines
|
||
475 | if not e: |
||
476 | e = ParsingError(fpname) |
||
477 | e.append(lineno, `line`) |
||
478 | # if any parsing errors occurred, raise an exception
|
||
479 | if e:
|
||
480 | raise e |