Changeset 391 for python/trunk/Lib/ConfigParser.py
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Lib/ConfigParser.py
r2 r391 88 88 """ 89 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 90 96 import re 91 97 … … 137 143 Error.__init__(self, 'No section: %r' % (section,)) 138 144 self.section = section 145 self.args = (section, ) 139 146 140 147 class DuplicateSectionError(Error): … … 144 151 Error.__init__(self, "Section %r already exists" % section) 145 152 self.section = section 153 self.args = (section, ) 146 154 147 155 class NoOptionError(Error): … … 153 161 self.option = option 154 162 self.section = section 163 self.args = (option, section) 155 164 156 165 class InterpolationError(Error): … … 161 170 self.option = option 162 171 self.section = section 172 self.args = (option, section, msg) 163 173 164 174 class InterpolationMissingOptionError(InterpolationError): … … 174 184 InterpolationError.__init__(self, option, section, msg) 175 185 self.reference = reference 186 self.args = (option, section, rawval, reference) 176 187 177 188 class InterpolationSyntaxError(InterpolationError): … … 189 200 % (section, option, rawval)) 190 201 InterpolationError.__init__(self, option, section, msg) 202 self.args = (option, section, rawval) 191 203 192 204 class ParsingError(Error): … … 197 209 self.filename = filename 198 210 self.errors = [] 211 self.args = (filename, ) 199 212 200 213 def append(self, lineno, line): … … 213 226 self.lineno = lineno 214 227 self.line = line 228 self.args = (filename, lineno, line) 215 229 216 230 217 231 class RawConfigParser: 218 def __init__(self, defaults=None, dict_type=dict): 232 def __init__(self, defaults=None, dict_type=_default_dict, 233 allow_no_value=False): 219 234 self._dict = dict_type 220 235 self._sections = self._dict() 221 236 self._defaults = self._dict() 237 if allow_no_value: 238 self._optcre = self.OPTCRE_NV 239 else: 240 self._optcre = self.OPTCRE 222 241 if defaults: 223 242 for key, value in defaults.items(): … … 367 386 or option in self._defaults) 368 387 369 def set(self, section, option, value ):388 def set(self, section, option, value=None): 370 389 """Set an option.""" 371 390 if not section or section == DEFAULTSECT: … … 388 407 fp.write("[%s]\n" % section) 389 408 for (key, value) in self._sections[section].items(): 390 if key != "__name__": 391 fp.write("%s = %s\n" % 392 (key, str(value).replace('\n', '\n\t'))) 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)) 393 414 fp.write("\n") 394 415 … … 431 452 r'(?P<value>.*)$' # everything up to eol 432 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 ) 433 463 434 464 def _read(self, fp, fpname): … … 442 472 and just about everything else are ignored. 443 473 """ 444 cursect = None 474 cursect = None # None, or a dictionary 445 475 optname = None 446 476 lineno = 0 447 e = None 477 e = None # None, or an exception 448 478 while True: 449 479 line = fp.readline() … … 461 491 value = line.strip() 462 492 if value: 463 cursect[optname] = "%s\n%s" % (cursect[optname],value)493 cursect[optname].append(value) 464 494 # a section header or option header? 465 495 else: … … 483 513 # an option line? 484 514 else: 485 mo = self. OPTCRE.match(line)515 mo = self._optcre.match(line) 486 516 if mo: 487 517 optname, vi, optval = mo.group('option', 'vi', 'value') 488 if vi in ('=', ':') and ';' in optval:489 # ';' is a comment delimiter only if it follows490 # a spacing character491 pos = optval.find(';')492 if pos != -1 and optval[pos-1].isspace():493 optval = optval[:pos]494 optval = optval.strip()495 # allow empty values496 if optval == '""':497 optval = ''498 518 optname = self.optionxform(optname.rstrip()) 499 cursect[optname] = optval 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 500 536 else: 501 537 # a non-fatal parsing error occurred. set up the … … 510 546 raise e 511 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 512 587 513 588 class ConfigParser(RawConfigParser): … … 516 591 """Get an option value for a given section. 517 592 518 All % interpolations are expanded in the return values, based on the 519 defaults passed into the constructor, unless the optional argument 520 `raw' is true. Additional substitutions may be provided using the 521 `vars' argument, which must be a dictionary whose contents overrides 522 any pre-existing defaults. 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. 523 599 524 600 The section DEFAULT is special. 525 601 """ 526 d = self._defaults.copy()602 sectiondict = {} 527 603 try: 528 d.update(self._sections[section])604 sectiondict = self._sections[section] 529 605 except KeyError: 530 606 if section != DEFAULTSECT: 531 607 raise NoSectionError(section) 532 608 # Update with the entry specific variables 609 vardict = {} 533 610 if vars: 534 611 for key, value in vars.items(): 535 d[self.optionxform(key)] = value 612 vardict[self.optionxform(key)] = value 613 d = _Chainmap(vardict, sectiondict, self._defaults) 536 614 option = self.optionxform(option) 537 615 try: … … 540 618 raise NoOptionError(option, section) 541 619 542 if raw :620 if raw or value is None: 543 621 return value 544 622 else: … … 583 661 while depth: # Loop through this until it's done 584 662 depth -= 1 585 if "%(" in value:663 if value and "%(" in value: 586 664 value = self._KEYCRE.sub(self._interpolation_replace, value) 587 665 try: … … 592 670 else: 593 671 break 594 if "%(" in value:672 if value and "%(" in value: 595 673 raise InterpolationDepthError(option, section, rawval) 596 674 return value … … 654 732 "'%%' must be followed by '%%' or '(', found: %r" % (rest,)) 655 733 656 def set(self, section, option, value ):734 def set(self, section, option, value=None): 657 735 """Set an option. Extend ConfigParser.set: check for string values.""" 658 if not isinstance(value, basestring): 659 raise TypeError("option values must be strings") 660 # check for bad percent signs: 661 # first, replace all "good" interpolations 662 tmp_value = value.replace('%%', '') 663 tmp_value = self._interpvar_re.sub('', tmp_value) 664 # then, check if there's a lone percent sign left 665 percent_index = tmp_value.find('%') 666 if percent_index != -1: 667 raise ValueError("invalid interpolation syntax in %r at " 668 "position %d" % (value, percent_index)) 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('%'))) 669 753 ConfigParser.set(self, section, option, value)
Note:
See TracChangeset
for help on using the changeset viewer.