Home | History | Annotate | Download | only in python2.7
      1 """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 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         its 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     read(filenames)
     46         read and parse the list of named configuration files, given by
     47         name.  A single filename is also allowed.  Non-existing files
     48         are ignored.  Return list of successfully read files.
     49 
     50     readfp(fp, filename=None)
     51         read and parse one configuration file, given as a file object.
     52         The filename defaults to fp.name; it is only used in error
     53         messages (if fp has no `name' attribute, the string `<???>' is used).
     54 
     55     get(section, option, raw=False, vars=None)
     56         return a string value for the named option.  All % interpolations are
     57         expanded in the return values, based on the defaults passed into the
     58         constructor and the DEFAULT section.  Additional substitutions may be
     59         provided using the `vars' argument, which must be a dictionary whose
     60         contents override any pre-existing defaults.
     61 
     62     getint(section, options)
     63         like get(), but convert value to an integer
     64 
     65     getfloat(section, options)
     66         like get(), but convert value to a float
     67 
     68     getboolean(section, options)
     69         like get(), but convert value to a boolean (currently case
     70         insensitively defined as 0, false, no, off for False, and 1, true,
     71         yes, on for True).  Returns False or True.
     72 
     73     items(section, raw=False, vars=None)
     74         return a list of tuples with (name, value) for each option
     75         in the section.
     76 
     77     remove_section(section)
     78         remove the given file section and all its options
     79 
     80     remove_option(section, option)
     81         remove the given option from the given section
     82 
     83     set(section, option, value)
     84         set the given option
     85 
     86     write(fp)
     87         write the configuration state in .ini format
     88 """
     89 
     90 try:
     91     from collections import OrderedDict as _default_dict
     92 except ImportError:
     93     # fallback for setup.py which hasn't yet built _collections
     94     _default_dict = dict
     95 
     96 import re
     97 
     98 __all__ = ["NoSectionError", "DuplicateSectionError", "NoOptionError",
     99            "InterpolationError", "InterpolationDepthError",
    100            "InterpolationSyntaxError", "ParsingError",
    101            "MissingSectionHeaderError",
    102            "ConfigParser", "SafeConfigParser", "RawConfigParser",
    103            "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"]
    104 
    105 DEFAULTSECT = "DEFAULT"
    106 
    107 MAX_INTERPOLATION_DEPTH = 10
    108 
    109 
    110 
    111 # exception classes
    112 class Error(Exception):
    113     """Base class for ConfigParser exceptions."""
    114 
    115     def _get_message(self):
    116         """Getter for 'message'; needed only to override deprecation in
    117         BaseException."""
    118         return self.__message
    119 
    120     def _set_message(self, value):
    121         """Setter for 'message'; needed only to override deprecation in
    122         BaseException."""
    123         self.__message = value
    124 
    125     # BaseException.message has been deprecated since Python 2.6.  To prevent
    126     # DeprecationWarning from popping up over this pre-existing attribute, use
    127     # a new property that takes lookup precedence.
    128     message = property(_get_message, _set_message)
    129 
    130     def __init__(self, msg=''):
    131         self.message = msg
    132         Exception.__init__(self, msg)
    133 
    134     def __repr__(self):
    135         return self.message
    136 
    137     __str__ = __repr__
    138 
    139 class NoSectionError(Error):
    140     """Raised when no section matches a requested option."""
    141 
    142     def __init__(self, section):
    143         Error.__init__(self, 'No section: %r' % (section,))
    144         self.section = section
    145         self.args = (section, )
    146 
    147 class DuplicateSectionError(Error):
    148     """Raised when a section is multiply-created."""
    149 
    150     def __init__(self, section):
    151         Error.__init__(self, "Section %r already exists" % section)
    152         self.section = section
    153         self.args = (section, )
    154 
    155 class NoOptionError(Error):
    156     """A requested option was not found."""
    157 
    158     def __init__(self, option, section):
    159         Error.__init__(self, "No option %r in section: %r" %
    160                        (option, section))
    161         self.option = option
    162         self.section = section
    163         self.args = (option, section)
    164 
    165 class InterpolationError(Error):
    166     """Base class for interpolation-related exceptions."""
    167 
    168     def __init__(self, option, section, msg):
    169         Error.__init__(self, msg)
    170         self.option = option
    171         self.section = section
    172         self.args = (option, section, msg)
    173 
    174 class InterpolationMissingOptionError(InterpolationError):
    175     """A string substitution required a setting which was not available."""
    176 
    177     def __init__(self, option, section, rawval, reference):
    178         msg = ("Bad value substitution:\n"
    179                "\tsection: [%s]\n"
    180                "\toption : %s\n"
    181                "\tkey    : %s\n"
    182                "\trawval : %s\n"
    183                % (section, option, reference, rawval))
    184         InterpolationError.__init__(self, option, section, msg)
    185         self.reference = reference
    186         self.args = (option, section, rawval, reference)
    187 
    188 class InterpolationSyntaxError(InterpolationError):
    189     """Raised when the source text into which substitutions are made
    190     does not conform to the required syntax."""
    191 
    192 class InterpolationDepthError(InterpolationError):
    193     """Raised when substitutions are nested too deeply."""
    194 
    195     def __init__(self, option, section, rawval):
    196         msg = ("Value interpolation too deeply recursive:\n"
    197                "\tsection: [%s]\n"
    198                "\toption : %s\n"
    199                "\trawval : %s\n"
    200                % (section, option, rawval))
    201         InterpolationError.__init__(self, option, section, msg)
    202         self.args = (option, section, rawval)
    203 
    204 class ParsingError(Error):
    205     """Raised when a configuration file does not follow legal syntax."""
    206 
    207     def __init__(self, filename):
    208         Error.__init__(self, 'File contains parsing errors: %s' % filename)
    209         self.filename = filename
    210         self.errors = []
    211         self.args = (filename, )
    212 
    213     def append(self, lineno, line):
    214         self.errors.append((lineno, line))
    215         self.message += '\n\t[line %2d]: %s' % (lineno, line)
    216 
    217 class MissingSectionHeaderError(ParsingError):
    218     """Raised when a key-value pair is found before any section header."""
    219 
    220     def __init__(self, filename, lineno, line):
    221         Error.__init__(
    222             self,
    223             'File contains no section headers.\nfile: %s, line: %d\n%r' %
    224             (filename, lineno, line))
    225         self.filename = filename
    226         self.lineno = lineno
    227         self.line = line
    228         self.args = (filename, lineno, line)
    229 
    230 
    231 class RawConfigParser:
    232     def __init__(self, defaults=None, dict_type=_default_dict,
    233                  allow_no_value=False):
    234         self._dict = dict_type
    235         self._sections = self._dict()
    236         self._defaults = self._dict()
    237         if allow_no_value:
    238             self._optcre = self.OPTCRE_NV
    239         else:
    240             self._optcre = self.OPTCRE
    241         if defaults:
    242             for key, value in defaults.items():
    243                 self._defaults[self.optionxform(key)] = value
    244 
    245     def defaults(self):
    246         return self._defaults
    247 
    248     def sections(self):
    249         """Return a list of section names, excluding [DEFAULT]"""
    250         # self._sections will never have [DEFAULT] in it
    251         return self._sections.keys()
    252 
    253     def add_section(self, section):
    254         """Create a new section in the configuration.
    255 
    256         Raise DuplicateSectionError if a section by the specified name
    257         already exists. Raise ValueError if name is DEFAULT or any of it's
    258         case-insensitive variants.
    259         """
    260         if section.lower() == "default":
    261             raise ValueError, 'Invalid section name: %s' % section
    262 
    263         if section in self._sections:
    264             raise DuplicateSectionError(section)
    265         self._sections[section] = self._dict()
    266 
    267     def has_section(self, section):
    268         """Indicate whether the named section is present in the configuration.
    269 
    270         The DEFAULT section is not acknowledged.
    271         """
    272         return section in self._sections
    273 
    274     def options(self, section):
    275         """Return a list of option names for the given section name."""
    276         try:
    277             opts = self._sections[section].copy()
    278         except KeyError:
    279             raise NoSectionError(section)
    280         opts.update(self._defaults)
    281         if '__name__' in opts:
    282             del opts['__name__']
    283         return opts.keys()
    284 
    285     def read(self, filenames):
    286         """Read and parse a filename or a list of filenames.
    287 
    288         Files that cannot be opened are silently ignored; this is
    289         designed so that you can specify a list of potential
    290         configuration file locations (e.g. current directory, user's
    291         home directory, systemwide directory), and all existing
    292         configuration files in the list will be read.  A single
    293         filename may also be given.
    294 
    295         Return list of successfully read files.
    296         """
    297         if isinstance(filenames, basestring):
    298             filenames = [filenames]
    299         read_ok = []
    300         for filename in filenames:
    301             try:
    302                 fp = open(filename)
    303             except IOError:
    304                 continue
    305             self._read(fp, filename)
    306             fp.close()
    307             read_ok.append(filename)
    308         return read_ok
    309 
    310     def readfp(self, fp, filename=None):
    311         """Like read() but the argument must be a file-like object.
    312 
    313         The `fp' argument must have a `readline' method.  Optional
    314         second argument is the `filename', which if not given, is
    315         taken from fp.name.  If fp has no `name' attribute, `<???>' is
    316         used.
    317 
    318         """
    319         if filename is None:
    320             try:
    321                 filename = fp.name
    322             except AttributeError:
    323                 filename = '<???>'
    324         self._read(fp, filename)
    325 
    326     def get(self, section, option):
    327         opt = self.optionxform(option)
    328         if section not in self._sections:
    329             if section != DEFAULTSECT:
    330                 raise NoSectionError(section)
    331             if opt in self._defaults:
    332                 return self._defaults[opt]
    333             else:
    334                 raise NoOptionError(option, section)
    335         elif opt in self._sections[section]:
    336             return self._sections[section][opt]
    337         elif opt in self._defaults:
    338             return self._defaults[opt]
    339         else:
    340             raise NoOptionError(option, section)
    341 
    342     def items(self, section):
    343         try:
    344             d2 = self._sections[section]
    345         except KeyError:
    346             if section != DEFAULTSECT:
    347                 raise NoSectionError(section)
    348             d2 = self._dict()
    349         d = self._defaults.copy()
    350         d.update(d2)
    351         if "__name__" in d:
    352             del d["__name__"]
    353         return d.items()
    354 
    355     def _get(self, section, conv, option):
    356         return conv(self.get(section, option))
    357 
    358     def getint(self, section, option):
    359         return self._get(section, int, option)
    360 
    361     def getfloat(self, section, option):
    362         return self._get(section, float, option)
    363 
    364     _boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
    365                        '0': False, 'no': False, 'false': False, 'off': False}
    366 
    367     def getboolean(self, section, option):
    368         v = self.get(section, option)
    369         if v.lower() not in self._boolean_states:
    370             raise ValueError, 'Not a boolean: %s' % v
    371         return self._boolean_states[v.lower()]
    372 
    373     def optionxform(self, optionstr):
    374         return optionstr.lower()
    375 
    376     def has_option(self, section, option):
    377         """Check for the existence of a given option in a given section."""
    378         if not section or section == DEFAULTSECT:
    379             option = self.optionxform(option)
    380             return option in self._defaults
    381         elif section not in self._sections:
    382             return False
    383         else:
    384             option = self.optionxform(option)
    385             return (option in self._sections[section]
    386                     or option in self._defaults)
    387 
    388     def set(self, section, option, value=None):
    389         """Set an option."""
    390         if not section or section == DEFAULTSECT:
    391             sectdict = self._defaults
    392         else:
    393             try:
    394                 sectdict = self._sections[section]
    395             except KeyError:
    396                 raise NoSectionError(section)
    397         sectdict[self.optionxform(option)] = value
    398 
    399     def write(self, fp):
    400         """Write an .ini-format representation of the configuration state."""
    401         if self._defaults:
    402             fp.write("[%s]\n" % DEFAULTSECT)
    403             for (key, value) in self._defaults.items():
    404                 fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
    405             fp.write("\n")
    406         for section in self._sections:
    407             fp.write("[%s]\n" % section)
    408             for (key, value) in self._sections[section].items():
    409                 if key == "__name__":
    410                     continue
    411                 if (value is not None) or (self._optcre == self.OPTCRE):
    412                     key = " = ".join((key, str(value).replace('\n', '\n\t')))
    413                 fp.write("%s\n" % (key))
    414             fp.write("\n")
    415 
    416     def remove_option(self, section, option):
    417         """Remove an option."""
    418         if not section or section == DEFAULTSECT:
    419             sectdict = self._defaults
    420         else:
    421             try:
    422                 sectdict = self._sections[section]
    423             except KeyError:
    424                 raise NoSectionError(section)
    425         option = self.optionxform(option)
    426         existed = option in sectdict
    427         if existed:
    428             del sectdict[option]
    429         return existed
    430 
    431     def remove_section(self, section):
    432         """Remove a file section."""
    433         existed = section in self._sections
    434         if existed:
    435             del self._sections[section]
    436         return existed
    437 
    438     #
    439     # Regular expressions for parsing section headers and options.
    440     #
    441     SECTCRE = re.compile(
    442         r'\['                                 # [
    443         r'(?P<header>[^]]+)'                  # very permissive!
    444         r'\]'                                 # ]
    445         )
    446     OPTCRE = re.compile(
    447         r'(?P<option>[^:=\s][^:=]*)'          # very permissive!
    448         r'\s*(?P<vi>[:=])\s*'                 # any number of space/tab,
    449                                               # followed by separator
    450                                               # (either : or =), followed
    451                                               # by any # space/tab
    452         r'(?P<value>.*)$'                     # everything up to eol
    453         )
    454     OPTCRE_NV = re.compile(
    455         r'(?P<option>[^:=\s][^:=]*)'          # very permissive!
    456         r'\s*(?:'                             # any number of space/tab,
    457         r'(?P<vi>[:=])\s*'                    # optionally followed by
    458                                               # separator (either : or
    459                                               # =), followed by any #
    460                                               # space/tab
    461         r'(?P<value>.*))?$'                   # everything up to eol
    462         )
    463 
    464     def _read(self, fp, fpname):
    465         """Parse a sectioned setup file.
    466 
    467         The sections in setup file contains a title line at the top,
    468         indicated by a name in square brackets (`[]'), plus key/value
    469         options lines, indicated by `name: value' format lines.
    470         Continuations are represented by an embedded newline then
    471         leading whitespace.  Blank lines, lines beginning with a '#',
    472         and just about everything else are ignored.
    473         """
    474         cursect = None                        # None, or a dictionary
    475         optname = None
    476         lineno = 0
    477         e = None                              # None, or an exception
    478         while True:
    479             line = fp.readline()
    480             if not line:
    481                 break
    482             lineno = lineno + 1
    483             # comment or blank line?
    484             if line.strip() == '' or line[0] in '#;':
    485                 continue
    486             if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
    487                 # no leading whitespace
    488                 continue
    489             # continuation line?
    490             if line[0].isspace() and cursect is not None and optname:
    491                 value = line.strip()
    492                 if value:
    493                     cursect[optname].append(value)
    494             # a section header or option header?
    495             else:
    496                 # is it a section header?
    497                 mo = self.SECTCRE.match(line)
    498                 if mo:
    499                     sectname = mo.group('header')
    500                     if sectname in self._sections:
    501                         cursect = self._sections[sectname]
    502                     elif sectname == DEFAULTSECT:
    503                         cursect = self._defaults
    504                     else:
    505                         cursect = self._dict()
    506                         cursect['__name__'] = sectname
    507                         self._sections[sectname] = cursect
    508                     # So sections can't start with a continuation line
    509                     optname = None
    510                 # no section header in the file?
    511                 elif cursect is None:
    512                     raise MissingSectionHeaderError(fpname, lineno, line)
    513                 # an option line?
    514                 else:
    515                     mo = self._optcre.match(line)
    516                     if mo:
    517                         optname, vi, optval = mo.group('option', 'vi', 'value')
    518                         optname = self.optionxform(optname.rstrip())
    519                         # This check is fine because the OPTCRE cannot
    520                         # match if it would set optval to None
    521                         if optval is not None:
    522                             if vi in ('=', ':') and ';' in optval:
    523                                 # ';' is a comment delimiter only if it follows
    524                                 # a spacing character
    525                                 pos = optval.find(';')
    526                                 if pos != -1 and optval[pos-1].isspace():
    527                                     optval = optval[:pos]
    528                             optval = optval.strip()
    529                             # allow empty values
    530                             if optval == '""':
    531                                 optval = ''
    532                             cursect[optname] = [optval]
    533                         else:
    534                             # valueless option handling
    535                             cursect[optname] = optval
    536                     else:
    537                         # a non-fatal parsing error occurred.  set up the
    538                         # exception but keep going. the exception will be
    539                         # raised at the end of the file and will contain a
    540                         # list of all bogus lines
    541                         if not e:
    542                             e = ParsingError(fpname)
    543                         e.append(lineno, repr(line))
    544         # if any parsing errors occurred, raise an exception
    545         if e:
    546             raise e
    547 
    548         # join the multi-line values collected while reading
    549         all_sections = [self._defaults]
    550         all_sections.extend(self._sections.values())
    551         for options in all_sections:
    552             for name, val in options.items():
    553                 if isinstance(val, list):
    554                     options[name] = '\n'.join(val)
    555 
    556 import UserDict as _UserDict
    557 
    558 class _Chainmap(_UserDict.DictMixin):
    559     """Combine multiple mappings for successive lookups.
    560 
    561     For example, to emulate Python's normal lookup sequence:
    562 
    563         import __builtin__
    564         pylookup = _Chainmap(locals(), globals(), vars(__builtin__))
    565     """
    566 
    567     def __init__(self, *maps):
    568         self._maps = maps
    569 
    570     def __getitem__(self, key):
    571         for mapping in self._maps:
    572             try:
    573                 return mapping[key]
    574             except KeyError:
    575                 pass
    576         raise KeyError(key)
    577 
    578     def keys(self):
    579         result = []
    580         seen = set()
    581         for mapping in self._maps:
    582             for key in mapping:
    583                 if key not in seen:
    584                     result.append(key)
    585                     seen.add(key)
    586         return result
    587 
    588 class ConfigParser(RawConfigParser):
    589 
    590     def get(self, section, option, raw=False, vars=None):
    591         """Get an option value for a given section.
    592 
    593         If `vars' is provided, it must be a dictionary. The option is looked up
    594         in `vars' (if provided), `section', and in `defaults' in that order.
    595 
    596         All % interpolations are expanded in the return values, unless the
    597         optional argument `raw' is true. Values for interpolation keys are
    598         looked up in the same manner as the option.
    599 
    600         The section DEFAULT is special.
    601         """
    602         sectiondict = {}
    603         try:
    604             sectiondict = self._sections[section]
    605         except KeyError:
    606             if section != DEFAULTSECT:
    607                 raise NoSectionError(section)
    608         # Update with the entry specific variables
    609         vardict = {}
    610         if vars:
    611             for key, value in vars.items():
    612                 vardict[self.optionxform(key)] = value
    613         d = _Chainmap(vardict, sectiondict, self._defaults)
    614         option = self.optionxform(option)
    615         try:
    616             value = d[option]
    617         except KeyError:
    618             raise NoOptionError(option, section)
    619 
    620         if raw or value is None:
    621             return value
    622         else:
    623             return self._interpolate(section, option, value, d)
    624 
    625     def items(self, section, raw=False, vars=None):
    626         """Return a list of tuples with (name, value) for each option
    627         in the section.
    628 
    629         All % interpolations are expanded in the return values, based on the
    630         defaults passed into the constructor, unless the optional argument
    631         `raw' is true.  Additional substitutions may be provided using the
    632         `vars' argument, which must be a dictionary whose contents overrides
    633         any pre-existing defaults.
    634 
    635         The section DEFAULT is special.
    636         """
    637         d = self._defaults.copy()
    638         try:
    639             d.update(self._sections[section])
    640         except KeyError:
    641             if section != DEFAULTSECT:
    642                 raise NoSectionError(section)
    643         # Update with the entry specific variables
    644         if vars:
    645             for key, value in vars.items():
    646                 d[self.optionxform(key)] = value
    647         options = d.keys()
    648         if "__name__" in options:
    649             options.remove("__name__")
    650         if raw:
    651             return [(option, d[option])
    652                     for option in options]
    653         else:
    654             return [(option, self._interpolate(section, option, d[option], d))
    655                     for option in options]
    656 
    657     def _interpolate(self, section, option, rawval, vars):
    658         # do the string interpolation
    659         value = rawval
    660         depth = MAX_INTERPOLATION_DEPTH
    661         while depth:                    # Loop through this until it's done
    662             depth -= 1
    663             if value and "%(" in value:
    664                 value = self._KEYCRE.sub(self._interpolation_replace, value)
    665                 try:
    666                     value = value % vars
    667                 except KeyError, e:
    668                     raise InterpolationMissingOptionError(
    669                         option, section, rawval, e.args[0])
    670             else:
    671                 break
    672         if value and "%(" in value:
    673             raise InterpolationDepthError(option, section, rawval)
    674         return value
    675 
    676     _KEYCRE = re.compile(r"%\(([^)]*)\)s|.")
    677 
    678     def _interpolation_replace(self, match):
    679         s = match.group(1)
    680         if s is None:
    681             return match.group()
    682         else:
    683             return "%%(%s)s" % self.optionxform(s)
    684 
    685 
    686 class SafeConfigParser(ConfigParser):
    687 
    688     def _interpolate(self, section, option, rawval, vars):
    689         # do the string interpolation
    690         L = []
    691         self._interpolate_some(option, L, rawval, section, vars, 1)
    692         return ''.join(L)
    693 
    694     _interpvar_re = re.compile(r"%\(([^)]+)\)s")
    695 
    696     def _interpolate_some(self, option, accum, rest, section, map, depth):
    697         if depth > MAX_INTERPOLATION_DEPTH:
    698             raise InterpolationDepthError(option, section, rest)
    699         while rest:
    700             p = rest.find("%")
    701             if p < 0:
    702                 accum.append(rest)
    703                 return
    704             if p > 0:
    705                 accum.append(rest[:p])
    706                 rest = rest[p:]
    707             # p is no longer used
    708             c = rest[1:2]
    709             if c == "%":
    710                 accum.append("%")
    711                 rest = rest[2:]
    712             elif c == "(":
    713                 m = self._interpvar_re.match(rest)
    714                 if m is None:
    715                     raise InterpolationSyntaxError(option, section,
    716                         "bad interpolation variable reference %r" % rest)
    717                 var = self.optionxform(m.group(1))
    718                 rest = rest[m.end():]
    719                 try:
    720                     v = map[var]
    721                 except KeyError:
    722                     raise InterpolationMissingOptionError(
    723                         option, section, rest, var)
    724                 if "%" in v:
    725                     self._interpolate_some(option, accum, v,
    726                                            section, map, depth + 1)
    727                 else:
    728                     accum.append(v)
    729             else:
    730                 raise InterpolationSyntaxError(
    731                     option, section,
    732                     "'%%' must be followed by '%%' or '(', found: %r" % (rest,))
    733 
    734     def set(self, section, option, value=None):
    735         """Set an option.  Extend ConfigParser.set: check for string values."""
    736         # The only legal non-string value if we allow valueless
    737         # options is None, so we need to check if the value is a
    738         # string if:
    739         # - we do not allow valueless options, or
    740         # - we allow valueless options but the value is not None
    741         if self._optcre is self.OPTCRE or value:
    742             if not isinstance(value, basestring):
    743                 raise TypeError("option values must be strings")
    744         if value is not None:
    745             # check for bad percent signs:
    746             # first, replace all "good" interpolations
    747             tmp_value = value.replace('%%', '')
    748             tmp_value = self._interpvar_re.sub('', tmp_value)
    749             # then, check if there's a lone percent sign left
    750             if '%' in tmp_value:
    751                 raise ValueError("invalid interpolation syntax in %r at "
    752                                 "position %d" % (value, tmp_value.find('%')))
    753         ConfigParser.set(self, section, option, value)
    754