| | 35 | class OrderedConfigParser(ConfigParser): |
| | 36 | """ """ |
| | 37 | def __init__(self, defaults=None): |
| | 38 | """Override default constructor""" |
| | 39 | self._sections = OrderedDict() |
| | 40 | if defaults is None: |
| | 41 | self._defaults = OrderedDict() |
| | 42 | else: |
| | 43 | self._defaults = defaults |
| | 44 | |
| | 45 | def add_section(self, section): |
| | 46 | """Override RawConfigParser method""" |
| | 47 | if section in self._sections: |
| | 48 | raise DuplicateSectionError(section) |
| | 49 | self._sections[section] = OrderedDict() |
| | 50 | |
| | 51 | def _read(self, fp, fpname): |
| | 52 | """Override RawConfigParser method""" |
| | 53 | cursect = None # None, or a dictionary |
| | 54 | optname = None |
| | 55 | lineno = 0 |
| | 56 | e = None # None, or an exception |
| | 57 | while True: |
| | 58 | line = fp.readline() |
| | 59 | if not line: |
| | 60 | break |
| | 61 | lineno = lineno + 1 |
| | 62 | # comment or blank line? |
| | 63 | if line.strip() == '' or line[0] in '#;': |
| | 64 | continue |
| | 65 | if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR": |
| | 66 | # no leading whitespace |
| | 67 | continue |
| | 68 | # continuation line? |
| | 69 | if line[0].isspace() and cursect is not None and optname: |
| | 70 | value = line.strip() |
| | 71 | if value: |
| | 72 | cursect[optname] = "%s\n%s" % (cursect[optname], value) |
| | 73 | # a section header or option header? |
| | 74 | else: |
| | 75 | # is it a section header? |
| | 76 | mo = self.SECTCRE.match(line) |
| | 77 | if mo: |
| | 78 | sectname = mo.group('header') |
| | 79 | if sectname in self._sections: |
| | 80 | cursect = self._sections[sectname] |
| | 81 | elif sectname == DEFAULTSECT: |
| | 82 | cursect = self._defaults |
| | 83 | else: |
| | 84 | cursect = OrderedDict() |
| | 85 | cursect['__name__'] = sectname |
| | 86 | self._sections[sectname] = cursect |
| | 87 | # So sections can't start with a continuation line |
| | 88 | optname = None |
| | 89 | # no section header in the file? |
| | 90 | elif cursect is None: |
| | 91 | raise MissingSectionHeaderError(fpname, lineno, `line`) |
| | 92 | # an option line? |
| | 93 | else: |
| | 94 | mo = self.OPTCRE.match(line) |
| | 95 | if mo: |
| | 96 | optname, vi, optval = mo.group('option', 'vi', 'value') |
| | 97 | if vi in ('=', ':') and ';' in optval: |
| | 98 | # ';' is a comment delimiter only if it follows |
| | 99 | # a spacing character |
| | 100 | pos = optval.find(';') |
| | 101 | if pos != -1 and optval[pos-1].isspace(): |
| | 102 | optval = optval[:pos] |
| | 103 | optval = optval.strip() |
| | 104 | # allow empty values |
| | 105 | if optval == '""': |
| | 106 | optval = '' |
| | 107 | optname = self.optionxform(optname.rstrip()) |
| | 108 | cursect[optname] = optval |
| | 109 | else: |
| | 110 | # a non-fatal parsing error occurred. set up the |
| | 111 | # exception but keep going. the exception will be |
| | 112 | # raised at the end of the file and will contain a |
| | 113 | # list of all bogus lines |
| | 114 | if not e: |
| | 115 | e = ParsingError(fpname) |
| | 116 | e.append(lineno, `line`) |
| | 117 | # if any parsing errors occurred, raise an exception |
| | 118 | if e: |
| | 119 | raise e |
| 152 | | if current is not False and current != default: |
| 153 | | if not config.has_section(section): |
| 154 | | config.add_section(section) |
| 155 | | config.set(section, option, current or '') |
| | 238 | if default and current and current == default: |
| | 239 | self.parser.remove_option(section, option) |
| | 240 | if not self.parser.options(section): |
| | 241 | empty_sections.append(section) |
| | 242 | if empty_sections: |
| | 243 | map(self.parser.remove_section, empty_sections) |