1   
   2   
   3   
   4   
   5   
   6   
   7   
   8   
   9   
  10   
  11   
  12   
  13   
  14   
  15   
  16   
  17   
  18   
  19  from __future__ import generators 
  20   
  21  import os 
  22  import re 
  23  import sys 
  24   
  25  from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE 
  26   
  27   
  28   
  29  compiler = None 
  30   
  31   
  32   
  33   
  34  BOMS = { 
  35      BOM_UTF8: ('utf_8', None), 
  36      BOM_UTF16_BE: ('utf16_be', 'utf_16'), 
  37      BOM_UTF16_LE: ('utf16_le', 'utf_16'), 
  38      BOM_UTF16: ('utf_16', 'utf_16'), 
  39      } 
  40   
  41   
  42   
  43  BOM_LIST = { 
  44      'utf_16': 'utf_16', 
  45      'u16': 'utf_16', 
  46      'utf16': 'utf_16', 
  47      'utf-16': 'utf_16', 
  48      'utf16_be': 'utf16_be', 
  49      'utf_16_be': 'utf16_be', 
  50      'utf-16be': 'utf16_be', 
  51      'utf16_le': 'utf16_le', 
  52      'utf_16_le': 'utf16_le', 
  53      'utf-16le': 'utf16_le', 
  54      'utf_8': 'utf_8', 
  55      'u8': 'utf_8', 
  56      'utf': 'utf_8', 
  57      'utf8': 'utf_8', 
  58      'utf-8': 'utf_8', 
  59      } 
  60   
  61   
  62  BOM_SET = { 
  63      'utf_8': BOM_UTF8, 
  64      'utf_16': BOM_UTF16, 
  65      'utf16_be': BOM_UTF16_BE, 
  66      'utf16_le': BOM_UTF16_LE, 
  67      None: BOM_UTF8 
  68      } 
  69   
  70   
  73   
  74   
  75   
  76  squot = "'%s'" 
  77  dquot = '"%s"' 
  78  noquot = "%s" 
  79  wspace_plus = ' \r\n\v\t\'"' 
  80  tsquot = '"""%s"""' 
  81  tdquot = "'''%s'''" 
  82   
  83   
  84  MISSING = object() 
  85   
  86  __version__ = '4.7.2' 
  87   
  88  try: 
  89      any 
  90  except NameError: 
  92          for entry in iterable: 
  93              if entry: 
  94                  return True 
  95          return False 
   96   
  97   
  98  __all__ = ( 
  99      '__version__', 
 100      'DEFAULT_INDENT_TYPE', 
 101      'DEFAULT_INTERPOLATION', 
 102      'ConfigObjError', 
 103      'NestingError', 
 104      'ParseError', 
 105      'DuplicateError', 
 106      'ConfigspecError', 
 107      'ConfigObj', 
 108      'SimpleVal', 
 109      'InterpolationError', 
 110      'InterpolationLoopError', 
 111      'MissingInterpolationOption', 
 112      'RepeatSectionError', 
 113      'ReloadError', 
 114      'UnreprError', 
 115      'UnknownType', 
 116      'flatten_errors', 
 117      'get_extra_values' 
 118  ) 
 119   
 120  DEFAULT_INTERPOLATION = 'configparser' 
 121  DEFAULT_INDENT_TYPE = '    ' 
 122  MAX_INTERPOL_DEPTH = 10 
 123   
 124  OPTION_DEFAULTS = { 
 125      'interpolation': True, 
 126      'raise_errors': False, 
 127      'list_values': True, 
 128      'create_empty': False, 
 129      'file_error': False, 
 130      'configspec': None, 
 131      'stringify': True, 
 132       
 133      'indent_type': None, 
 134      'encoding': None, 
 135      'default_encoding': None, 
 136      'unrepr': False, 
 137      'write_empty_values': False, 
 138  } 
 139   
 140   
 141   
 143      global compiler 
 144      if compiler is None: 
 145          import compiler 
 146      s = "a=" + s 
 147      p = compiler.parse(s) 
 148      return p.getChildren()[1].getChildren()[0].getChildren()[1] 
  149   
 150   
 153   
 154   
 156       
 158          m = getattr(self, 'build_' + o.__class__.__name__, None) 
 159          if m is None: 
 160              raise UnknownType(o.__class__.__name__) 
 161          return m(o) 
  162       
 164          return map(self.build, o.getChildren()) 
  165       
 168       
 170          d = {} 
 171          i = iter(map(self.build, o.getChildren())) 
 172          for el in i: 
 173              d[el] = i.next() 
 174          return d 
  175       
 178       
 180          if o.name == 'None': 
 181              return None 
 182          if o.name == 'True': 
 183              return True 
 184          if o.name == 'False': 
 185              return False 
 186           
 187           
 188          raise UnknownType('Undefined Name') 
  189       
 191          real, imag = map(self.build_Const, o.getChildren()) 
 192          try: 
 193              real = float(real) 
 194          except TypeError: 
 195              raise UnknownType('Add') 
 196          if not isinstance(imag, complex) or imag.real != 0.0: 
 197              raise UnknownType('Add') 
 198          return real+imag 
  199       
 201          parent = self.build(o.expr) 
 202          return getattr(parent, o.attrname) 
  203       
 206       
  209   
 210   
 211  _builder = Builder() 
 212   
 213   
 218   
 219   
 220   
 222      """ 
 223      This is the base class for all errors that ConfigObj raises. 
 224      It is a subclass of SyntaxError. 
 225      """ 
 226 -    def __init__(self, message='', line_number=None, line=''): 
  227          self.line = line 
 228          self.line_number = line_number 
 229          SyntaxError.__init__(self, message) 
   230   
 231   
 233      """ 
 234      This error indicates a level of nesting that doesn't match. 
 235      """ 
  236   
 237   
 239      """ 
 240      This error indicates that a line is badly written. 
 241      It is neither a valid ``key = value`` line, 
 242      nor a valid section marker line. 
 243      """ 
  244   
 245   
 247      """ 
 248      A 'reload' operation failed. 
 249      This exception is a subclass of ``IOError``. 
 250      """ 
 252          IOError.__init__(self, 'reload failed, filename is not set.') 
   253   
 254   
 256      """ 
 257      The keyword or section specified already exists. 
 258      """ 
  259   
 260   
 262      """ 
 263      An error occured whilst parsing a configspec. 
 264      """ 
  265   
 266   
 268      """Base class for the two interpolation errors.""" 
  269   
 270   
 272      """Maximum interpolation depth exceeded in string interpolation.""" 
 273   
  278   
 279   
 281      """ 
 282      This error indicates additional sections in a section with a 
 283      ``__many__`` (repeated) section. 
 284      """ 
  285   
 286   
 288      """A value specified for interpolation was missing.""" 
  292   
 293   
 295      """An error parsing in unrepr mode.""" 
  296   
 297   
 298   
 300      """ 
 301      A helper class to help perform string interpolation. 
 302   
 303      This class is an abstract base class; its descendants perform 
 304      the actual work. 
 305      """ 
 306   
 307       
 308      _KEYCRE = re.compile(r"%\(([^)]*)\)s") 
 309      _cookie = '%' 
 310   
 312           
 313          self.section = section 
  314   
 315   
 317           
 318          if not self._cookie in value: 
 319              return value 
 320           
 321          def recursive_interpolate(key, value, section, backtrail): 
 322              """The function that does the actual work. 
 323   
 324              ``value``: the string we're trying to interpolate. 
 325              ``section``: the section in which that string was found 
 326              ``backtrail``: a dict to keep track of where we've been, 
 327              to detect and prevent infinite recursion loops 
 328   
 329              This is similar to a depth-first-search algorithm. 
 330              """ 
 331               
 332              if (key, section.name) in backtrail: 
 333                   
 334                  raise InterpolationLoopError(key) 
 335               
 336              backtrail[(key, section.name)] = 1 
 337   
 338               
 339              match = self._KEYCRE.search(value) 
 340              while match: 
 341                   
 342                   
 343                  k, v, s = self._parse_match(match) 
 344                  if k is None: 
 345                       
 346                      replacement = v 
 347                  else: 
 348                       
 349                      replacement = recursive_interpolate(k, v, s, backtrail) 
 350                   
 351                  start, end = match.span() 
 352                  value = ''.join((value[:start], replacement, value[end:])) 
 353                  new_search_start = start + len(replacement) 
 354                   
 355                   
 356                  match = self._KEYCRE.search(value, new_search_start) 
 357   
 358               
 359              del backtrail[(key, section.name)] 
 360   
 361              return value 
  362   
 363           
 364           
 365          value = recursive_interpolate(key, value, self.section, {}) 
 366          return value 
  367   
 368   
 370          """Helper function to fetch values from owning section. 
 371   
 372          Returns a 2-tuple: the value, and the section where it was found. 
 373          """ 
 374           
 375          save_interp = self.section.main.interpolation 
 376          self.section.main.interpolation = False 
 377   
 378           
 379          current_section = self.section 
 380          while True: 
 381               
 382              val = current_section.get(key) 
 383              if val is not None and not isinstance(val, Section): 
 384                  break 
 385               
 386              val = current_section.get('DEFAULT', {}).get(key) 
 387              if val is not None and not isinstance(val, Section): 
 388                  break 
 389               
 390               
 391              if current_section.parent is current_section: 
 392                   
 393                  break 
 394              current_section = current_section.parent 
 395   
 396           
 397          self.section.main.interpolation = save_interp 
 398          if val is None: 
 399              raise MissingInterpolationOption(key) 
 400          return val, current_section 
  401   
 402   
 404          """Implementation-dependent helper function. 
 405   
 406          Will be passed a match object corresponding to the interpolation 
 407          key we just found (e.g., "%(foo)s" or "$foo"). Should look up that 
 408          key in the appropriate config file section (using the ``_fetch()`` 
 409          helper function) and return a 3-tuple: (key, value, section) 
 410   
 411          ``key`` is the name of the key we're looking for 
 412          ``value`` is the value found for that key 
 413          ``section`` is a reference to the section where it was found 
 414   
 415          ``key`` and ``section`` should be None if no further 
 416          interpolation should be performed on the resulting value 
 417          (e.g., if we interpolated "$$" and returned "$"). 
 418          """ 
 419          raise NotImplementedError() 
  420       
 421   
 422   
 424      """Behaves like ConfigParser.""" 
 425      _cookie = '%' 
 426      _KEYCRE = re.compile(r"%\(([^)]*)\)s") 
 427   
 429          key = match.group(1) 
 430          value, section = self._fetch(key) 
 431          return key, value, section 
   432   
 433   
 434   
 436      """Behaves like string.Template.""" 
 437      _cookie = '$' 
 438      _delimiter = '$' 
 439      _KEYCRE = re.compile(r""" 
 440          \$(?: 
 441            (?P<escaped>\$)              |   # Two $ signs 
 442            (?P<named>[_a-z][_a-z0-9]*)  |   # $name format 
 443            {(?P<braced>[^}]*)}              # ${name} format 
 444          ) 
 445          """, re.IGNORECASE | re.VERBOSE) 
 446   
 448           
 449          key = match.group('named') or match.group('braced') 
 450          if key is not None: 
 451              value, section = self._fetch(key) 
 452              return key, value, section 
 453           
 454          if match.group('escaped') is not None: 
 455               
 456              return None, self._delimiter, None 
 457           
 458          return None, match.group(), None 
   459   
 460   
 461  interpolation_engines = { 
 462      'configparser': ConfigParserInterpolation, 
 463      'template': TemplateInterpolation, 
 464  } 
 465   
 466   
 468       
 469      return cls.__new__(cls, *args)  
  470   
 472      """ 
 473      A dictionary-like object that represents a section in a config file. 
 474       
 475      It does string interpolation if the 'interpolation' attribute 
 476      of the 'main' object is set to True. 
 477       
 478      Interpolation is tried first from this object, then from the 'DEFAULT' 
 479      section of this object, next from the parent and its 'DEFAULT' section, 
 480      and so on until the main object is reached. 
 481       
 482      A Section will behave like an ordered dictionary - following the 
 483      order of the ``scalars`` and ``sections`` attributes. 
 484      You can use this to change the order of members. 
 485       
 486      Iteration follows the order: scalars, then sections. 
 487      """ 
 488   
 489       
 493   
 495          state = (dict(self), self.__dict__) 
 496          return (__newobj__, (self.__class__,), state) 
  497       
 498       
 499 -    def __init__(self, parent, depth, main, indict=None, name=None): 
  500          """ 
 501          * parent is the section above 
 502          * depth is the depth level of this section 
 503          * main is the main ConfigObj 
 504          * indict is a dictionary to initialise the section with 
 505          """ 
 506          if indict is None: 
 507              indict = {} 
 508          dict.__init__(self) 
 509           
 510          self.parent = parent 
 511           
 512          self.main = main 
 513           
 514          self.depth = depth 
 515           
 516          self.name = name 
 517           
 518          self._initialise() 
 519           
 520           
 521          for entry, value in indict.iteritems(): 
 522              self[entry] = value 
  523               
 524               
 526           
 527          self.scalars = [] 
 528           
 529          self.sections = [] 
 530           
 531          self.comments = {} 
 532          self.inline_comments = {} 
 533           
 534          self.configspec = None 
 535           
 536          self.defaults = [] 
 537          self.default_values = {} 
 538          self.extra_values = [] 
 539          self._created = False 
  540   
 541   
 543          try: 
 544               
 545              engine = self._interpolation_engine 
 546          except AttributeError: 
 547               
 548              name = self.main.interpolation 
 549              if name == True:   
 550                   
 551                  name = DEFAULT_INTERPOLATION 
 552              name = name.lower()   
 553              class_ = interpolation_engines.get(name, None) 
 554              if class_ is None: 
 555                   
 556                  self.main.interpolation = False 
 557                  return value 
 558              else: 
 559                   
 560                  engine = self._interpolation_engine = class_(self) 
 561           
 562          return engine.interpolate(key, value) 
  563   
 564   
 566          """Fetch the item and do string interpolation.""" 
 567          val = dict.__getitem__(self, key) 
 568          if self.main.interpolation:  
 569              if isinstance(val, basestring): 
 570                  return self._interpolate(key, val) 
 571              if isinstance(val, list): 
 572                  def _check(entry): 
 573                      if isinstance(entry, basestring): 
 574                          return self._interpolate(key, entry) 
 575                      return entry 
  576                  new = [_check(entry) for entry in val] 
 577                  if new != val: 
 578                      return new 
 579          return val 
  580   
 581   
 583          """ 
 584          Correctly set a value. 
 585           
 586          Making dictionary values Section instances. 
 587          (We have to special case 'Section' instances - which are also dicts) 
 588           
 589          Keys must be strings. 
 590          Values need only be strings (or lists of strings) if 
 591          ``main.stringify`` is set. 
 592           
 593          ``unrepr`` must be set when setting a value to a dictionary, without 
 594          creating a new sub-section. 
 595          """ 
 596          if not isinstance(key, basestring): 
 597              raise ValueError('The key "%s" is not a string.' % key) 
 598           
 599           
 600          if key not in self.comments: 
 601              self.comments[key] = [] 
 602              self.inline_comments[key] = '' 
 603           
 604          if key in self.defaults: 
 605              self.defaults.remove(key) 
 606           
 607          if isinstance(value, Section): 
 608              if key not in self: 
 609                  self.sections.append(key) 
 610              dict.__setitem__(self, key, value) 
 611          elif isinstance(value, dict) and not unrepr: 
 612               
 613               
 614              if key not in self: 
 615                  self.sections.append(key) 
 616              new_depth = self.depth + 1 
 617              dict.__setitem__( 
 618                  self, 
 619                  key, 
 620                  Section( 
 621                      self, 
 622                      new_depth, 
 623                      self.main, 
 624                      indict=value, 
 625                      name=key)) 
 626          else: 
 627              if key not in self: 
 628                  self.scalars.append(key) 
 629              if not self.main.stringify: 
 630                  if isinstance(value, basestring): 
 631                      pass 
 632                  elif isinstance(value, (list, tuple)): 
 633                      for entry in value: 
 634                          if not isinstance(entry, basestring): 
 635                              raise TypeError('Value is not a string "%s".' % entry) 
 636                  else: 
 637                      raise TypeError('Value is not a string "%s".' % value) 
 638              dict.__setitem__(self, key, value) 
  639   
 640   
 642          """Remove items from the sequence when deleting.""" 
 643          dict. __delitem__(self, key) 
 644          if key in self.scalars: 
 645              self.scalars.remove(key) 
 646          else: 
 647              self.sections.remove(key) 
 648          del self.comments[key] 
 649          del self.inline_comments[key] 
  650   
 651   
 652 -    def get(self, key, default=None): 
  653          """A version of ``get`` that doesn't bypass string interpolation.""" 
 654          try: 
 655              return self[key] 
 656          except KeyError: 
 657              return default 
  658   
 659   
 661          """ 
 662          A version of update that uses our ``__setitem__``. 
 663          """ 
 664          for entry in indict: 
 665              self[entry] = indict[entry] 
  666   
 667   
 669          """ 
 670          'D.pop(k[,d]) -> v, remove specified key and return the corresponding value. 
 671          If key is not found, d is returned if given, otherwise KeyError is raised' 
 672          """ 
 673          try: 
 674              val = self[key] 
 675          except KeyError: 
 676              if default is MISSING: 
 677                  raise 
 678              val = default 
 679          else: 
 680              del self[key] 
 681          return val 
  682   
 683   
 685          """Pops the first (key,val)""" 
 686          sequence = (self.scalars + self.sections) 
 687          if not sequence: 
 688              raise KeyError(": 'popitem(): dictionary is empty'") 
 689          key = sequence[0] 
 690          val =  self[key] 
 691          del self[key] 
 692          return key, val 
  693   
 694   
 696          """ 
 697          A version of clear that also affects scalars/sections 
 698          Also clears comments and configspec. 
 699           
 700          Leaves other attributes alone : 
 701              depth/main/parent are not affected 
 702          """ 
 703          dict.clear(self) 
 704          self.scalars = [] 
 705          self.sections = [] 
 706          self.comments = {} 
 707          self.inline_comments = {} 
 708          self.configspec = None 
 709          self.defaults = [] 
 710          self.extra_values = [] 
  711   
 712   
 714          """A version of setdefault that sets sequence if appropriate.""" 
 715          try: 
 716              return self[key] 
 717          except KeyError: 
 718              self[key] = default 
 719              return self[key] 
  720   
 721   
 723          """D.items() -> list of D's (key, value) pairs, as 2-tuples""" 
 724          return zip((self.scalars + self.sections), self.values()) 
  725   
 726   
 728          """D.keys() -> list of D's keys""" 
 729          return (self.scalars + self.sections) 
  730   
 731   
 733          """D.values() -> list of D's values""" 
 734          return [self[key] for key in (self.scalars + self.sections)] 
  735   
 736   
 738          """D.iteritems() -> an iterator over the (key, value) items of D""" 
 739          return iter(self.items()) 
  740   
 741   
 743          """D.iterkeys() -> an iterator over the keys of D""" 
 744          return iter((self.scalars + self.sections)) 
  745   
 746      __iter__ = iterkeys 
 747   
 748   
 750          """D.itervalues() -> an iterator over the values of D""" 
 751          return iter(self.values()) 
  752   
 753   
 761          return '{%s}' % ', '.join([('%s: %s' % (repr(key), repr(_getval(key)))) 
 762              for key in (self.scalars + self.sections)]) 
 763   
 764      __str__ = __repr__ 
 765      __str__.__doc__ = "x.__str__() <==> str(x)" 
 766   
 767   
 768       
 769   
 771          """ 
 772          Return a deepcopy of self as a dictionary. 
 773           
 774          All members that are ``Section`` instances are recursively turned to 
 775          ordinary dictionaries - by calling their ``dict`` method. 
 776           
 777          >>> n = a.dict() 
 778          >>> n == a 
 779          1 
 780          >>> n is a 
 781          0 
 782          """ 
 783          newdict = {} 
 784          for entry in self: 
 785              this_entry = self[entry] 
 786              if isinstance(this_entry, Section): 
 787                  this_entry = this_entry.dict() 
 788              elif isinstance(this_entry, list): 
 789                   
 790                  this_entry = list(this_entry) 
 791              elif isinstance(this_entry, tuple): 
 792                   
 793                  this_entry = tuple(this_entry) 
 794              newdict[entry] = this_entry 
 795          return newdict 
  796   
 797   
 798 -    def merge(self, indict): 
  799          """ 
 800          A recursive update - useful for merging config files. 
 801           
 802          >>> a = '''[section1] 
 803          ...     option1 = True 
 804          ...     [[subsection]] 
 805          ...     more_options = False 
 806          ...     # end of file'''.splitlines() 
 807          >>> b = '''# File is user.ini 
 808          ...     [section1] 
 809          ...     option1 = False 
 810          ...     # end of file'''.splitlines() 
 811          >>> c1 = ConfigObj(b) 
 812          >>> c2 = ConfigObj(a) 
 813          >>> c2.merge(c1) 
 814          >>> c2 
 815          ConfigObj({'section1': {'option1': 'False', 'subsection': {'more_options': 'False'}}}) 
 816          """ 
 817          for key, val in indict.items(): 
 818              if (key in self and isinstance(self[key], dict) and 
 819                                  isinstance(val, dict)): 
 820                  self[key].merge(val) 
 821              else:    
 822                  self[key] = val 
  823   
 824   
 825 -    def rename(self, oldkey, newkey): 
  826          """ 
 827          Change a keyname to another, without changing position in sequence. 
 828           
 829          Implemented so that transformations can be made on keys, 
 830          as well as on values. (used by encode and decode) 
 831           
 832          Also renames comments. 
 833          """ 
 834          if oldkey in self.scalars: 
 835              the_list = self.scalars 
 836          elif oldkey in self.sections: 
 837              the_list = self.sections 
 838          else: 
 839              raise KeyError('Key "%s" not found.' % oldkey) 
 840          pos = the_list.index(oldkey) 
 841           
 842          val = self[oldkey] 
 843          dict.__delitem__(self, oldkey) 
 844          dict.__setitem__(self, newkey, val) 
 845          the_list.remove(oldkey) 
 846          the_list.insert(pos, newkey) 
 847          comm = self.comments[oldkey] 
 848          inline_comment = self.inline_comments[oldkey] 
 849          del self.comments[oldkey] 
 850          del self.inline_comments[oldkey] 
 851          self.comments[newkey] = comm 
 852          self.inline_comments[newkey] = inline_comment 
  853   
 854   
 855 -    def walk(self, function, raise_errors=True, 
 856              call_on_sections=False, **keywargs): 
  857          """ 
 858          Walk every member and call a function on the keyword and value. 
 859           
 860          Return a dictionary of the return values 
 861           
 862          If the function raises an exception, raise the errror 
 863          unless ``raise_errors=False``, in which case set the return value to 
 864          ``False``. 
 865           
 866          Any unrecognised keyword arguments you pass to walk, will be pased on 
 867          to the function you pass in. 
 868           
 869          Note: if ``call_on_sections`` is ``True`` then - on encountering a 
 870          subsection, *first* the function is called for the *whole* subsection, 
 871          and then recurses into it's members. This means your function must be 
 872          able to handle strings, dictionaries and lists. This allows you 
 873          to change the key of subsections as well as for ordinary members. The 
 874          return value when called on the whole subsection has to be discarded. 
 875           
 876          See  the encode and decode methods for examples, including functions. 
 877           
 878          .. admonition:: caution 
 879           
 880              You can use ``walk`` to transform the names of members of a section 
 881              but you mustn't add or delete members. 
 882           
 883          >>> config = '''[XXXXsection] 
 884          ... XXXXkey = XXXXvalue'''.splitlines() 
 885          >>> cfg = ConfigObj(config) 
 886          >>> cfg 
 887          ConfigObj({'XXXXsection': {'XXXXkey': 'XXXXvalue'}}) 
 888          >>> def transform(section, key): 
 889          ...     val = section[key] 
 890          ...     newkey = key.replace('XXXX', 'CLIENT1') 
 891          ...     section.rename(key, newkey) 
 892          ...     if isinstance(val, (tuple, list, dict)): 
 893          ...         pass 
 894          ...     else: 
 895          ...         val = val.replace('XXXX', 'CLIENT1') 
 896          ...         section[newkey] = val 
 897          >>> cfg.walk(transform, call_on_sections=True) 
 898          {'CLIENT1section': {'CLIENT1key': None}} 
 899          >>> cfg 
 900          ConfigObj({'CLIENT1section': {'CLIENT1key': 'CLIENT1value'}}) 
 901          """ 
 902          out = {} 
 903           
 904          for i in range(len(self.scalars)): 
 905              entry = self.scalars[i] 
 906              try: 
 907                  val = function(self, entry, **keywargs) 
 908                   
 909                  entry = self.scalars[i] 
 910                  out[entry] = val 
 911              except Exception: 
 912                  if raise_errors: 
 913                      raise 
 914                  else: 
 915                      entry = self.scalars[i] 
 916                      out[entry] = False 
 917           
 918          for i in range(len(self.sections)): 
 919              entry = self.sections[i] 
 920              if call_on_sections: 
 921                  try: 
 922                      function(self, entry, **keywargs) 
 923                  except Exception: 
 924                      if raise_errors: 
 925                          raise 
 926                      else: 
 927                          entry = self.sections[i] 
 928                          out[entry] = False 
 929                   
 930                  entry = self.sections[i] 
 931               
 932              out[entry] = self[entry].walk( 
 933                  function, 
 934                  raise_errors=raise_errors, 
 935                  call_on_sections=call_on_sections, 
 936                  **keywargs) 
 937          return out 
  938   
 939   
 941          """ 
 942          Accepts a key as input. The corresponding value must be a string or 
 943          the objects (``True`` or 1) or (``False`` or 0). We allow 0 and 1 to 
 944          retain compatibility with Python 2.2. 
 945           
 946          If the string is one of  ``True``, ``On``, ``Yes``, or ``1`` it returns  
 947          ``True``. 
 948           
 949          If the string is one of  ``False``, ``Off``, ``No``, or ``0`` it returns  
 950          ``False``. 
 951           
 952          ``as_bool`` is not case sensitive. 
 953           
 954          Any other input will raise a ``ValueError``. 
 955           
 956          >>> a = ConfigObj() 
 957          >>> a['a'] = 'fish' 
 958          >>> a.as_bool('a') 
 959          Traceback (most recent call last): 
 960          ValueError: Value "fish" is neither True nor False 
 961          >>> a['b'] = 'True' 
 962          >>> a.as_bool('b') 
 963          1 
 964          >>> a['b'] = 'off' 
 965          >>> a.as_bool('b') 
 966          0 
 967          """ 
 968          val = self[key] 
 969          if val == True: 
 970              return True 
 971          elif val == False: 
 972              return False 
 973          else: 
 974              try: 
 975                  if not isinstance(val, basestring): 
 976                       
 977                      raise KeyError() 
 978                  else: 
 979                      return self.main._bools[val.lower()] 
 980              except KeyError: 
 981                  raise ValueError('Value "%s" is neither True nor False' % val) 
  982   
 983   
 985          """ 
 986          A convenience method which coerces the specified value to an integer. 
 987           
 988          If the value is an invalid literal for ``int``, a ``ValueError`` will 
 989          be raised. 
 990           
 991          >>> a = ConfigObj() 
 992          >>> a['a'] = 'fish' 
 993          >>> a.as_int('a') 
 994          Traceback (most recent call last): 
 995          ValueError: invalid literal for int() with base 10: 'fish' 
 996          >>> a['b'] = '1' 
 997          >>> a.as_int('b') 
 998          1 
 999          >>> a['b'] = '3.2' 
1000          >>> a.as_int('b') 
1001          Traceback (most recent call last): 
1002          ValueError: invalid literal for int() with base 10: '3.2' 
1003          """ 
1004          return int(self[key]) 
 1005   
1006   
1008          """ 
1009          A convenience method which coerces the specified value to a float. 
1010           
1011          If the value is an invalid literal for ``float``, a ``ValueError`` will 
1012          be raised. 
1013          """ 
1014          return float(self[key]) 
 1015       
1016       
1018          """ 
1019          A convenience method which fetches the specified value, guaranteeing 
1020          that it is a list. 
1021           
1022          >>> a = ConfigObj() 
1023          >>> a['a'] = 1 
1024          >>> a.as_list('a') 
1025          [1] 
1026          >>> a['a'] = (1,) 
1027          >>> a.as_list('a') 
1028          [1] 
1029          >>> a['a'] = [1] 
1030          >>> a.as_list('a') 
1031          [1] 
1032          """ 
1033          result = self[key] 
1034          if isinstance(result, (tuple, list)): 
1035              return list(result) 
1036          return [result] 
 1037           
1038   
1040          """ 
1041          Restore (and return) default value for the specified key. 
1042           
1043          This method will only work for a ConfigObj that was created 
1044          with a configspec and has been validated. 
1045           
1046          If there is no default value for this key, ``KeyError`` is raised. 
1047          """ 
1048          default = self.default_values[key] 
1049          dict.__setitem__(self, key, default) 
1050          if key not in self.defaults: 
1051              self.defaults.append(key) 
1052          return default 
 1053   
1054       
1056          """ 
1057          Recursively restore default values to all members 
1058          that have them. 
1059           
1060          This method will only work for a ConfigObj that was created 
1061          with a configspec and has been validated. 
1062           
1063          It doesn't delete or modify entries without default values. 
1064          """ 
1065          for key in self.default_values: 
1066              self.restore_default(key) 
1067               
1068          for section in self.sections: 
1069              self[section].restore_defaults() 
 1070   
1071   
1073      """An object to read, create, and write config files.""" 
1074   
1075      _keyword = re.compile(r'''^ # line start 
1076          (\s*)                   # indentation 
1077          (                       # keyword 
1078              (?:".*?")|          # double quotes 
1079              (?:'.*?')|          # single quotes 
1080              (?:[^'"=].*?)       # no quotes 
1081          ) 
1082          \s*=\s*                 # divider 
1083          (.*)                    # value (including list values and comments) 
1084          $   # line end 
1085          ''', 
1086          re.VERBOSE) 
1087   
1088      _sectionmarker = re.compile(r'''^ 
1089          (\s*)                     # 1: indentation 
1090          ((?:\[\s*)+)              # 2: section marker open 
1091          (                         # 3: section name open 
1092              (?:"\s*\S.*?\s*")|    # at least one non-space with double quotes 
1093              (?:'\s*\S.*?\s*')|    # at least one non-space with single quotes 
1094              (?:[^'"\s].*?)        # at least one non-space unquoted 
1095          )                         # section name close 
1096          ((?:\s*\])+)              # 4: section marker close 
1097          \s*(\#.*)?                # 5: optional comment 
1098          $''', 
1099          re.VERBOSE) 
1100   
1101       
1102       
1103       
1104       
1105      _valueexp = re.compile(r'''^ 
1106          (?: 
1107              (?: 
1108                  ( 
1109                      (?: 
1110                          (?: 
1111                              (?:".*?")|              # double quotes 
1112                              (?:'.*?')|              # single quotes 
1113                              (?:[^'",\#][^,\#]*?)    # unquoted 
1114                          ) 
1115                          \s*,\s*                     # comma 
1116                      )*      # match all list items ending in a comma (if any) 
1117                  ) 
1118                  ( 
1119                      (?:".*?")|                      # double quotes 
1120                      (?:'.*?')|                      # single quotes 
1121                      (?:[^'",\#\s][^,]*?)|           # unquoted 
1122                      (?:(?<!,))                      # Empty value 
1123                  )?          # last item in a list - or string value 
1124              )| 
1125              (,)             # alternatively a single comma - empty list 
1126          ) 
1127          \s*(\#.*)?          # optional comment 
1128          $''', 
1129          re.VERBOSE) 
1130   
1131       
1132      _listvalueexp = re.compile(r''' 
1133          ( 
1134              (?:".*?")|          # double quotes 
1135              (?:'.*?')|          # single quotes 
1136              (?:[^'",\#]?.*?)       # unquoted 
1137          ) 
1138          \s*,\s*                 # comma 
1139          ''', 
1140          re.VERBOSE) 
1141   
1142       
1143       
1144      _nolistvalue = re.compile(r'''^ 
1145          ( 
1146              (?:".*?")|          # double quotes 
1147              (?:'.*?')|          # single quotes 
1148              (?:[^'"\#].*?)|     # unquoted 
1149              (?:)                # Empty value 
1150          ) 
1151          \s*(\#.*)?              # optional comment 
1152          $''', 
1153          re.VERBOSE) 
1154   
1155       
1156      _single_line_single = re.compile(r"^'''(.*?)'''\s*(#.*)?$") 
1157      _single_line_double = re.compile(r'^"""(.*?)"""\s*(#.*)?$') 
1158      _multi_line_single = re.compile(r"^(.*?)'''\s*(#.*)?$") 
1159      _multi_line_double = re.compile(r'^(.*?)"""\s*(#.*)?$') 
1160   
1161      _triple_quote = { 
1162          "'''": (_single_line_single, _multi_line_single), 
1163          '"""': (_single_line_double, _multi_line_double), 
1164      } 
1165   
1166       
1167      _bools = { 
1168          'yes': True, 'no': False, 
1169          'on': True, 'off': False, 
1170          '1': True, '0': False, 
1171          'true': True, 'false': False, 
1172          } 
1173   
1174   
1175 -    def __init__(self, infile=None, options=None, configspec=None, encoding=None, 
1176                   interpolation=True, raise_errors=False, list_values=True, 
1177                   create_empty=False, file_error=False, stringify=True, 
1178                   indent_type=None, default_encoding=None, unrepr=False, 
1179                   write_empty_values=False, _inspec=False): 
 1180          """ 
1181          Parse a config file or create a config file object. 
1182           
1183          ``ConfigObj(infile=None, configspec=None, encoding=None, 
1184                      interpolation=True, raise_errors=False, list_values=True, 
1185                      create_empty=False, file_error=False, stringify=True, 
1186                      indent_type=None, default_encoding=None, unrepr=False, 
1187                      write_empty_values=False, _inspec=False)`` 
1188          """ 
1189          self._inspec = _inspec 
1190           
1191          Section.__init__(self, self, 0, self) 
1192           
1193          infile = infile or [] 
1194           
1195          _options = {'configspec': configspec, 
1196                      'encoding': encoding, 'interpolation': interpolation, 
1197                      'raise_errors': raise_errors, 'list_values': list_values, 
1198                      'create_empty': create_empty, 'file_error': file_error, 
1199                      'stringify': stringify, 'indent_type': indent_type, 
1200                      'default_encoding': default_encoding, 'unrepr': unrepr, 
1201                      'write_empty_values': write_empty_values} 
1202   
1203          if options is None: 
1204              options = _options 
1205          else: 
1206              import warnings 
1207              warnings.warn('Passing in an options dictionary to ConfigObj() is ' 
1208                            'deprecated. Use **options instead.', 
1209                            DeprecationWarning, stacklevel=2) 
1210               
1211               
1212              for entry in options: 
1213                  if entry not in OPTION_DEFAULTS: 
1214                      raise TypeError('Unrecognised option "%s".' % entry) 
1215              for entry, value in OPTION_DEFAULTS.items(): 
1216                  if entry not in options: 
1217                      options[entry] = value 
1218                  keyword_value = _options[entry] 
1219                  if value != keyword_value: 
1220                      options[entry] = keyword_value 
1221           
1222           
1223           
1224          if _inspec: 
1225              options['list_values'] = False 
1226           
1227          self._initialise(options) 
1228          configspec = options['configspec'] 
1229          self._original_configspec = configspec 
1230          self._load(infile, configspec) 
 1231           
1232           
1233 -    def _load(self, infile, configspec): 
 1234          if isinstance(infile, basestring): 
1235              self.filename = infile 
1236              if os.path.isfile(infile): 
1237                  h = open(infile, 'rb') 
1238                  infile = h.read() or [] 
1239                  h.close() 
1240              elif self.file_error: 
1241                   
1242                  raise IOError('Config file not found: "%s".' % self.filename) 
1243              else: 
1244                   
1245                  if self.create_empty: 
1246                       
1247                       
1248                      h = open(infile, 'w') 
1249                      h.write('') 
1250                      h.close() 
1251                  infile = [] 
1252                   
1253          elif isinstance(infile, (list, tuple)): 
1254              infile = list(infile) 
1255               
1256          elif isinstance(infile, dict): 
1257               
1258               
1259              if isinstance(infile, ConfigObj): 
1260                   
1261                  def set_section(in_section, this_section): 
1262                      for entry in in_section.scalars: 
1263                          this_section[entry] = in_section[entry] 
1264                      for section in in_section.sections: 
1265                          this_section[section] = {} 
1266                          set_section(in_section[section], this_section[section]) 
 1267                  set_section(infile, self) 
1268                   
1269              else: 
1270                  for entry in infile: 
1271                      self[entry] = infile[entry] 
1272              del self._errors 
1273               
1274              if configspec is not None: 
1275                  self._handle_configspec(configspec) 
1276              else: 
1277                  self.configspec = None 
1278              return 
1279           
1280          elif getattr(infile, 'read', MISSING) is not MISSING: 
1281               
1282              infile = infile.read() or [] 
1283               
1284               
1285          else: 
1286              raise TypeError('infile must be a filename, file like object, or list of lines.') 
1287           
1288          if infile: 
1289               
1290              infile = self._handle_bom(infile) 
1291               
1292               
1293               
1294               
1295              for line in infile: 
1296                  if (not line) or (line[-1] not in ('\r', '\n', '\r\n')): 
1297                      continue 
1298                  for end in ('\r\n', '\n', '\r'): 
1299                      if line.endswith(end): 
1300                          self.newlines = end 
1301                          break 
1302                  break 
1303   
1304              infile = [line.rstrip('\r\n') for line in infile] 
1305               
1306          self._parse(infile) 
1307           
1308          if self._errors: 
1309              info = "at line %s." % self._errors[0].line_number 
1310              if len(self._errors) > 1: 
1311                  msg = "Parsing failed with several errors.\nFirst error %s" % info 
1312                  error = ConfigObjError(msg) 
1313              else: 
1314                  error = self._errors[0] 
1315               
1316               
1317              error.errors = self._errors 
1318               
1319              error.config = self 
1320              raise error 
1321           
1322          del self._errors 
1323           
1324          if configspec is None: 
1325              self.configspec = None 
1326          else: 
1327              self._handle_configspec(configspec) 
 1328       
1329       
1331          if options is None: 
1332              options = OPTION_DEFAULTS 
1333               
1334           
1335          self.filename = None 
1336          self._errors = [] 
1337          self.raise_errors = options['raise_errors'] 
1338          self.interpolation = options['interpolation'] 
1339          self.list_values = options['list_values'] 
1340          self.create_empty = options['create_empty'] 
1341          self.file_error = options['file_error'] 
1342          self.stringify = options['stringify'] 
1343          self.indent_type = options['indent_type'] 
1344          self.encoding = options['encoding'] 
1345          self.default_encoding = options['default_encoding'] 
1346          self.BOM = False 
1347          self.newlines = None 
1348          self.write_empty_values = options['write_empty_values'] 
1349          self.unrepr = options['unrepr'] 
1350           
1351          self.initial_comment = [] 
1352          self.final_comment = [] 
1353          self.configspec = None 
1354           
1355          if self._inspec: 
1356              self.list_values = False 
1357           
1358           
1359          Section._initialise(self) 
 1360           
1361           
1368          return ('ConfigObj({%s})' %  
1369                  ', '.join([('%s: %s' % (repr(key), repr(_getval(key))))  
1370                  for key in (self.scalars + self.sections)])) 
1371       
1372       
1374          """ 
1375          Handle any BOM, and decode if necessary. 
1376           
1377          If an encoding is specified, that *must* be used - but the BOM should 
1378          still be removed (and the BOM attribute set). 
1379           
1380          (If the encoding is wrongly specified, then a BOM for an alternative 
1381          encoding won't be discovered or removed.) 
1382           
1383          If an encoding is not specified, UTF8 or UTF16 BOM will be detected and 
1384          removed. The BOM attribute will be set. UTF16 will be decoded to 
1385          unicode. 
1386           
1387          NOTE: This method must not be called with an empty ``infile``. 
1388           
1389          Specifying the *wrong* encoding is likely to cause a 
1390          ``UnicodeDecodeError``. 
1391           
1392          ``infile`` must always be returned as a list of lines, but may be 
1393          passed in as a single string. 
1394          """ 
1395          if ((self.encoding is not None) and 
1396              (self.encoding.lower() not in BOM_LIST)): 
1397               
1398               
1399               
1400              return self._decode(infile, self.encoding) 
1401           
1402          if isinstance(infile, (list, tuple)): 
1403              line = infile[0] 
1404          else: 
1405              line = infile 
1406          if self.encoding is not None: 
1407               
1408               
1409               
1410               
1411              enc = BOM_LIST[self.encoding.lower()] 
1412              if enc == 'utf_16': 
1413                   
1414                  for BOM, (encoding, final_encoding) in BOMS.items(): 
1415                      if not final_encoding: 
1416                           
1417                          continue 
1418                      if infile.startswith(BOM): 
1419                           
1420                           
1421                           
1422                          return self._decode(infile, encoding) 
1423                       
1424                   
1425                   
1426                  return self._decode(infile, self.encoding) 
1427               
1428               
1429              BOM = BOM_SET[enc] 
1430              if not line.startswith(BOM): 
1431                  return self._decode(infile, self.encoding) 
1432               
1433              newline = line[len(BOM):] 
1434               
1435               
1436              if isinstance(infile, (list, tuple)): 
1437                  infile[0] = newline 
1438              else: 
1439                  infile = newline 
1440              self.BOM = True 
1441              return self._decode(infile, self.encoding) 
1442           
1443           
1444          for BOM, (encoding, final_encoding) in BOMS.items(): 
1445              if not line.startswith(BOM): 
1446                  continue 
1447              else: 
1448                   
1449                  self.encoding = final_encoding 
1450                  if not final_encoding: 
1451                      self.BOM = True 
1452                       
1453                       
1454                      newline = line[len(BOM):] 
1455                      if isinstance(infile, (list, tuple)): 
1456                          infile[0] = newline 
1457                      else: 
1458                          infile = newline 
1459                       
1460                      if isinstance(infile, basestring): 
1461                          return infile.splitlines(True) 
1462                      else: 
1463                          return infile 
1464                   
1465                  return self._decode(infile, encoding) 
1466               
1467           
1468          if isinstance(infile, basestring): 
1469               
1470              return infile.splitlines(True) 
1471          return infile 
 1472   
1473   
1475          """Decode ASCII strings to unicode if a self.encoding is specified.""" 
1476          if self.encoding: 
1477              return aString.decode('ascii') 
1478          else: 
1479              return aString 
 1480   
1481   
1482 -    def _decode(self, infile, encoding): 
 1483          """ 
1484          Decode infile to unicode. Using the specified encoding. 
1485           
1486          if is a string, it also needs converting to a list. 
1487          """ 
1488          if isinstance(infile, basestring): 
1489               
1490               
1491              return infile.decode(encoding).splitlines(True) 
1492          for i, line in enumerate(infile): 
1493              if not isinstance(line, unicode): 
1494                   
1495                   
1496                   
1497                  infile[i] = line.decode(encoding) 
1498          return infile 
 1499   
1500   
1502          """Decode element to unicode if necessary.""" 
1503          if not self.encoding: 
1504              return line 
1505          if isinstance(line, str) and self.default_encoding: 
1506              return line.decode(self.default_encoding) 
1507          return line 
 1508   
1509   
1510 -    def _str(self, value): 
 1511          """ 
1512          Used by ``stringify`` within validate, to turn non-string values 
1513          into strings. 
1514          """ 
1515          if not isinstance(value, basestring): 
1516              return str(value) 
1517          else: 
1518              return value 
 1519   
1520   
1522          """Actually parse the config file.""" 
1523          temp_list_values = self.list_values 
1524          if self.unrepr: 
1525              self.list_values = False 
1526               
1527          comment_list = [] 
1528          done_start = False 
1529          this_section = self 
1530          maxline = len(infile) - 1 
1531          cur_index = -1 
1532          reset_comment = False 
1533           
1534          while cur_index < maxline: 
1535              if reset_comment: 
1536                  comment_list = [] 
1537              cur_index += 1 
1538              line = infile[cur_index] 
1539              sline = line.strip() 
1540               
1541              if not sline or sline.startswith('#'): 
1542                  reset_comment = False 
1543                  comment_list.append(line) 
1544                  continue 
1545               
1546              if not done_start: 
1547                   
1548                  self.initial_comment = comment_list 
1549                  comment_list = [] 
1550                  done_start = True 
1551                   
1552              reset_comment = True 
1553               
1554              mat = self._sectionmarker.match(line) 
1555              if mat is not None: 
1556                   
1557                  (indent, sect_open, sect_name, sect_close, comment) = mat.groups() 
1558                  if indent and (self.indent_type is None): 
1559                      self.indent_type = indent 
1560                  cur_depth = sect_open.count('[') 
1561                  if cur_depth != sect_close.count(']'): 
1562                      self._handle_error("Cannot compute the section depth at line %s.", 
1563                                         NestingError, infile, cur_index) 
1564                      continue 
1565                   
1566                  if cur_depth < this_section.depth: 
1567                       
1568                      try: 
1569                          parent = self._match_depth(this_section, 
1570                                                     cur_depth).parent 
1571                      except SyntaxError: 
1572                          self._handle_error("Cannot compute nesting level at line %s.", 
1573                                             NestingError, infile, cur_index) 
1574                          continue 
1575                  elif cur_depth == this_section.depth: 
1576                       
1577                      parent = this_section.parent 
1578                  elif cur_depth == this_section.depth + 1: 
1579                       
1580                      parent = this_section 
1581                  else: 
1582                      self._handle_error("Section too nested at line %s.", 
1583                                         NestingError, infile, cur_index) 
1584                       
1585                  sect_name = self._unquote(sect_name) 
1586                  if sect_name in parent: 
1587                      self._handle_error('Duplicate section name at line %s.', 
1588                                         DuplicateError, infile, cur_index) 
1589                      continue 
1590                   
1591                   
1592                  this_section = Section( 
1593                      parent, 
1594                      cur_depth, 
1595                      self, 
1596                      name=sect_name) 
1597                  parent[sect_name] = this_section 
1598                  parent.inline_comments[sect_name] = comment 
1599                  parent.comments[sect_name] = comment_list 
1600                  continue 
1601               
1602               
1603               
1604              mat = self._keyword.match(line) 
1605              if mat is None: 
1606                   
1607                   
1608                  self._handle_error( 
1609                      'Invalid line at line "%s".', 
1610                      ParseError, infile, cur_index) 
1611              else: 
1612                   
1613                   
1614                  (indent, key, value) = mat.groups() 
1615                  if indent and (self.indent_type is None): 
1616                      self.indent_type = indent 
1617                   
1618                  if value[:3] in ['"""', "'''"]: 
1619                      try: 
1620                          value, comment, cur_index = self._multiline( 
1621                              value, infile, cur_index, maxline) 
1622                      except SyntaxError: 
1623                          self._handle_error( 
1624                              'Parse error in value at line %s.', 
1625                              ParseError, infile, cur_index) 
1626                          continue 
1627                      else: 
1628                          if self.unrepr: 
1629                              comment = '' 
1630                              try: 
1631                                  value = unrepr(value) 
1632                              except Exception, e: 
1633                                  if type(e) == UnknownType: 
1634                                      msg = 'Unknown name or type in value at line %s.' 
1635                                  else: 
1636                                      msg = 'Parse error in value at line %s.' 
1637                                  self._handle_error(msg, UnreprError, infile, 
1638                                      cur_index) 
1639                                  continue 
1640                  else: 
1641                      if self.unrepr: 
1642                          comment = '' 
1643                          try: 
1644                              value = unrepr(value) 
1645                          except Exception, e: 
1646                              if isinstance(e, UnknownType): 
1647                                  msg = 'Unknown name or type in value at line %s.' 
1648                              else: 
1649                                  msg = 'Parse error in value at line %s.' 
1650                              self._handle_error(msg, UnreprError, infile, 
1651                                  cur_index) 
1652                              continue 
1653                      else: 
1654                           
1655                          try: 
1656                              (value, comment) = self._handle_value(value) 
1657                          except SyntaxError: 
1658                              self._handle_error( 
1659                                  'Parse error in value at line %s.', 
1660                                  ParseError, infile, cur_index) 
1661                              continue 
1662                   
1663                  key = self._unquote(key) 
1664                  if key in this_section: 
1665                      self._handle_error( 
1666                          'Duplicate keyword name at line %s.', 
1667                          DuplicateError, infile, cur_index) 
1668                      continue 
1669                   
1670                   
1671                   
1672                  this_section.__setitem__(key, value, unrepr=True) 
1673                  this_section.inline_comments[key] = comment 
1674                  this_section.comments[key] = comment_list 
1675                  continue 
1676           
1677          if self.indent_type is None: 
1678               
1679              self.indent_type = '' 
1680   
1681           
1682          if not self and not self.initial_comment: 
1683              self.initial_comment = comment_list 
1684          elif not reset_comment: 
1685              self.final_comment = comment_list 
1686          self.list_values = temp_list_values 
 1687   
1688   
1690          """ 
1691          Given a section and a depth level, walk back through the sections 
1692          parents to see if the depth level matches a previous section. 
1693           
1694          Return a reference to the right section, 
1695          or raise a SyntaxError. 
1696          """ 
1697          while depth < sect.depth: 
1698              if sect is sect.parent: 
1699                   
1700                  raise SyntaxError() 
1701              sect = sect.parent 
1702          if sect.depth == depth: 
1703              return sect 
1704           
1705          raise SyntaxError() 
 1706   
1707   
1709          """ 
1710          Handle an error according to the error settings. 
1711           
1712          Either raise the error or store it. 
1713          The error will have occured at ``cur_index`` 
1714          """ 
1715          line = infile[cur_index] 
1716          cur_index += 1 
1717          message = text % cur_index 
1718          error = ErrorClass(message, cur_index, line) 
1719          if self.raise_errors: 
1720               
1721              raise error 
1722           
1723           
1724          self._errors.append(error) 
 1725   
1726   
1728          """Return an unquoted version of a value""" 
1729          if not value: 
1730               
1731              raise SyntaxError 
1732          if (value[0] == value[-1]) and (value[0] in ('"', "'")): 
1733              value = value[1:-1] 
1734          return value 
 1735   
1736   
1737 -    def _quote(self, value, multiline=True): 
 1738          """ 
1739          Return a safely quoted version of a value. 
1740           
1741          Raise a ConfigObjError if the value cannot be safely quoted. 
1742          If multiline is ``True`` (default) then use triple quotes 
1743          if necessary. 
1744           
1745          * Don't quote values that don't need it. 
1746          * Recursively quote members of a list and return a comma joined list. 
1747          * Multiline is ``False`` for lists. 
1748          * Obey list syntax for empty and single member lists. 
1749           
1750          If ``list_values=False`` then the value is only quoted if it contains 
1751          a ``\\n`` (is multiline) or '#'. 
1752           
1753          If ``write_empty_values`` is set, and the value is an empty string, it 
1754          won't be quoted. 
1755          """ 
1756          if multiline and self.write_empty_values and value == '': 
1757               
1758               
1759              return '' 
1760           
1761          if multiline and isinstance(value, (list, tuple)): 
1762              if not value: 
1763                  return ',' 
1764              elif len(value) == 1: 
1765                  return self._quote(value[0], multiline=False) + ',' 
1766              return ', '.join([self._quote(val, multiline=False) 
1767                  for val in value]) 
1768          if not isinstance(value, basestring): 
1769              if self.stringify: 
1770                  value = str(value) 
1771              else: 
1772                  raise TypeError('Value "%s" is not a string.' % value) 
1773   
1774          if not value: 
1775              return '""' 
1776           
1777          no_lists_no_quotes = not self.list_values and '\n' not in value and '#' not in value 
1778          need_triple = multiline and ((("'" in value) and ('"' in value)) or ('\n' in value )) 
1779          hash_triple_quote = multiline and not need_triple and ("'" in value) and ('"' in value) and ('#' in value) 
1780          check_for_single = (no_lists_no_quotes or not need_triple) and not hash_triple_quote 
1781           
1782          if check_for_single: 
1783              if not self.list_values: 
1784                   
1785                  quot = noquot 
1786               
1787              elif '\n' in value: 
1788                   
1789                  raise ConfigObjError('Value "%s" cannot be safely quoted.' % value) 
1790              elif ((value[0] not in wspace_plus) and 
1791                      (value[-1] not in wspace_plus) and 
1792                      (',' not in value)): 
1793                  quot = noquot 
1794              else: 
1795                  quot = self._get_single_quote(value) 
1796          else: 
1797               
1798              quot = self._get_triple_quote(value) 
1799           
1800          if quot == noquot and '#' in value and self.list_values: 
1801              quot = self._get_single_quote(value) 
1802                   
1803          return quot % value 
 1804       
1805       
1807          if ("'" in value) and ('"' in value): 
1808              raise ConfigObjError('Value "%s" cannot be safely quoted.' % value) 
1809          elif '"' in value: 
1810              quot = squot 
1811          else: 
1812              quot = dquot 
1813          return quot 
 1814       
1815       
1817          if (value.find('"""') != -1) and (value.find("'''") != -1): 
1818              raise ConfigObjError('Value "%s" cannot be safely quoted.' % value) 
1819          if value.find('"""') == -1: 
1820              quot = tsquot 
1821          else: 
1822              quot = tdquot 
1823          return quot 
 1824   
1825   
1827          """ 
1828          Given a value string, unquote, remove comment, 
1829          handle lists. (including empty and single member lists) 
1830          """ 
1831          if self._inspec: 
1832               
1833              return (value, '') 
1834           
1835          if not self.list_values: 
1836              mat = self._nolistvalue.match(value) 
1837              if mat is None: 
1838                  raise SyntaxError() 
1839               
1840              return mat.groups() 
1841           
1842          mat = self._valueexp.match(value) 
1843          if mat is None: 
1844               
1845               
1846              raise SyntaxError() 
1847          (list_values, single, empty_list, comment) = mat.groups() 
1848          if (list_values == '') and (single is None): 
1849               
1850              raise SyntaxError() 
1851           
1852           
1853          if empty_list is not None: 
1854               
1855              return ([], comment) 
1856          if single is not None: 
1857               
1858              if list_values and not single: 
1859                   
1860                   
1861                  single = None 
1862              else: 
1863                  single = single or '""' 
1864                  single = self._unquote(single) 
1865          if list_values == '': 
1866               
1867              return (single, comment) 
1868          the_list = self._listvalueexp.findall(list_values) 
1869          the_list = [self._unquote(val) for val in the_list] 
1870          if single is not None: 
1871              the_list += [single] 
1872          return (the_list, comment) 
 1873   
1874   
1875 -    def _multiline(self, value, infile, cur_index, maxline): 
 1876          """Extract the value, where we are in a multiline situation.""" 
1877          quot = value[:3] 
1878          newvalue = value[3:] 
1879          single_line = self._triple_quote[quot][0] 
1880          multi_line = self._triple_quote[quot][1] 
1881          mat = single_line.match(value) 
1882          if mat is not None: 
1883              retval = list(mat.groups()) 
1884              retval.append(cur_index) 
1885              return retval 
1886          elif newvalue.find(quot) != -1: 
1887               
1888              raise SyntaxError() 
1889           
1890          while cur_index < maxline: 
1891              cur_index += 1 
1892              newvalue += '\n' 
1893              line = infile[cur_index] 
1894              if line.find(quot) == -1: 
1895                  newvalue += line 
1896              else: 
1897                   
1898                  break 
1899          else: 
1900               
1901              raise SyntaxError() 
1902          mat = multi_line.match(line) 
1903          if mat is None: 
1904               
1905              raise SyntaxError() 
1906          (value, comment) = mat.groups() 
1907          return (newvalue + value, comment, cur_index) 
 1908   
1909   
1911          """Parse the configspec.""" 
1912           
1913           
1914          if not isinstance(configspec, ConfigObj): 
1915              try: 
1916                  configspec = ConfigObj(configspec, 
1917                                         raise_errors=True, 
1918                                         file_error=True, 
1919                                         _inspec=True) 
1920              except ConfigObjError, e: 
1921                   
1922                   
1923                  raise ConfigspecError('Parsing configspec failed: %s' % e) 
1924              except IOError, e: 
1925                  raise IOError('Reading configspec failed: %s' % e) 
1926           
1927          self.configspec = configspec 
 1928               
1929   
1930           
1932          """ 
1933          Called by validate. Handles setting the configspec on subsections 
1934          including sections to be validated by __many__ 
1935          """ 
1936          configspec = section.configspec 
1937          many = configspec.get('__many__') 
1938          if isinstance(many, dict): 
1939              for entry in section.sections: 
1940                  if entry not in configspec: 
1941                      section[entry].configspec = many 
1942                       
1943          for entry in configspec.sections: 
1944              if entry == '__many__': 
1945                  continue 
1946              if entry not in section: 
1947                  section[entry] = {} 
1948                  section[entry]._created = True 
1949                  if copy: 
1950                       
1951                      section.comments[entry] = configspec.comments.get(entry, []) 
1952                      section.inline_comments[entry] = configspec.inline_comments.get(entry, '') 
1953                   
1954               
1955              if isinstance(section[entry], Section): 
1956                  section[entry].configspec = configspec[entry] 
 1957                           
1958   
1959 -    def _write_line(self, indent_string, entry, this_entry, comment): 
 1960          """Write an individual line, for the write method""" 
1961           
1962          if not self.unrepr: 
1963              val = self._decode_element(self._quote(this_entry)) 
1964          else: 
1965              val = repr(this_entry) 
1966          return '%s%s%s%s%s' % (indent_string, 
1967                                 self._decode_element(self._quote(entry, multiline=False)), 
1968                                 self._a_to_u(' = '), 
1969                                 val, 
1970                                 self._decode_element(comment)) 
 1971   
1972   
1980   
1981   
1990   
1991   
1992       
1993   
1994 -    def write(self, outfile=None, section=None): 
 1995          """ 
1996          Write the current ConfigObj as a file 
1997           
1998          tekNico: FIXME: use StringIO instead of real files 
1999           
2000          >>> filename = a.filename 
2001          >>> a.filename = 'test.ini' 
2002          >>> a.write() 
2003          >>> a.filename = filename 
2004          >>> a == ConfigObj('test.ini', raise_errors=True) 
2005          1 
2006          >>> import os 
2007          >>> os.remove('test.ini') 
2008          """ 
2009          if self.indent_type is None: 
2010               
2011              self.indent_type = DEFAULT_INDENT_TYPE 
2012               
2013          out = [] 
2014          cs = self._a_to_u('#') 
2015          csp = self._a_to_u('# ') 
2016          if section is None: 
2017              int_val = self.interpolation 
2018              self.interpolation = False 
2019              section = self 
2020              for line in self.initial_comment: 
2021                  line = self._decode_element(line) 
2022                  stripped_line = line.strip() 
2023                  if stripped_line and not stripped_line.startswith(cs): 
2024                      line = csp + line 
2025                  out.append(line) 
2026                   
2027          indent_string = self.indent_type * section.depth 
2028          for entry in (section.scalars + section.sections): 
2029              if entry in section.defaults: 
2030                   
2031                  continue 
2032              for comment_line in section.comments[entry]: 
2033                  comment_line = self._decode_element(comment_line.lstrip()) 
2034                  if comment_line and not comment_line.startswith(cs): 
2035                      comment_line = csp + comment_line 
2036                  out.append(indent_string + comment_line) 
2037              this_entry = section[entry] 
2038              comment = self._handle_comment(section.inline_comments[entry]) 
2039               
2040              if isinstance(this_entry, dict): 
2041                   
2042                  out.append(self._write_marker( 
2043                      indent_string, 
2044                      this_entry.depth, 
2045                      entry, 
2046                      comment)) 
2047                  out.extend(self.write(section=this_entry)) 
2048              else: 
2049                  out.append(self._write_line( 
2050                      indent_string, 
2051                      entry, 
2052                      this_entry, 
2053                      comment)) 
2054                   
2055          if section is self: 
2056              for line in self.final_comment: 
2057                  line = self._decode_element(line) 
2058                  stripped_line = line.strip() 
2059                  if stripped_line and not stripped_line.startswith(cs): 
2060                      line = csp + line 
2061                  out.append(line) 
2062              self.interpolation = int_val 
2063               
2064          if section is not self: 
2065              return out 
2066           
2067          if (self.filename is None) and (outfile is None): 
2068               
2069               
2070               
2071              if self.encoding: 
2072                  out = [l.encode(self.encoding) for l in out] 
2073              if (self.BOM and ((self.encoding is None) or 
2074                  (BOM_LIST.get(self.encoding.lower()) == 'utf_8'))): 
2075                   
2076                  if not out: 
2077                      out.append('') 
2078                  out[0] = BOM_UTF8 + out[0] 
2079              return out 
2080           
2081           
2082          newline = self.newlines or os.linesep 
2083          if (getattr(outfile, 'mode', None) is not None and outfile.mode == 'w' 
2084              and sys.platform == 'win32' and newline == '\r\n'): 
2085               
2086              newline = '\n' 
2087          output = self._a_to_u(newline).join(out) 
2088          if self.encoding: 
2089              output = output.encode(self.encoding) 
2090          if self.BOM and ((self.encoding is None) or match_utf8(self.encoding)): 
2091               
2092              output = BOM_UTF8 + output 
2093               
2094          if not output.endswith(newline): 
2095              output += newline 
2096          if outfile is not None: 
2097              outfile.write(output) 
2098          else: 
2099              h = open(self.filename, 'wb') 
2100              h.write(output) 
2101              h.close() 
 2102   
2103   
2104 -    def validate(self, validator, preserve_errors=False, copy=False, 
2105                   section=None): 
 2106          """ 
2107          Test the ConfigObj against a configspec. 
2108           
2109          It uses the ``validator`` object from *validate.py*. 
2110           
2111          To run ``validate`` on the current ConfigObj, call: :: 
2112           
2113              test = config.validate(validator) 
2114           
2115          (Normally having previously passed in the configspec when the ConfigObj 
2116          was created - you can dynamically assign a dictionary of checks to the 
2117          ``configspec`` attribute of a section though). 
2118           
2119          It returns ``True`` if everything passes, or a dictionary of 
2120          pass/fails (True/False). If every member of a subsection passes, it 
2121          will just have the value ``True``. (It also returns ``False`` if all 
2122          members fail). 
2123           
2124          In addition, it converts the values from strings to their native 
2125          types if their checks pass (and ``stringify`` is set). 
2126           
2127          If ``preserve_errors`` is ``True`` (``False`` is default) then instead 
2128          of a marking a fail with a ``False``, it will preserve the actual 
2129          exception object. This can contain info about the reason for failure. 
2130          For example the ``VdtValueTooSmallError`` indicates that the value 
2131          supplied was too small. If a value (or section) is missing it will 
2132          still be marked as ``False``. 
2133           
2134          You must have the validate module to use ``preserve_errors=True``. 
2135           
2136          You can then use the ``flatten_errors`` function to turn your nested 
2137          results dictionary into a flattened list of failures - useful for 
2138          displaying meaningful error messages. 
2139          """ 
2140          if section is None: 
2141              if self.configspec is None: 
2142                  raise ValueError('No configspec supplied.') 
2143              if preserve_errors: 
2144                   
2145                   
2146                  from validate import VdtMissingValue 
2147                  self._vdtMissingValue = VdtMissingValue 
2148                   
2149              section = self 
2150   
2151              if copy: 
2152                  section.initial_comment = section.configspec.initial_comment 
2153                  section.final_comment = section.configspec.final_comment 
2154                  section.encoding = section.configspec.encoding 
2155                  section.BOM = section.configspec.BOM 
2156                  section.newlines = section.configspec.newlines 
2157                  section.indent_type = section.configspec.indent_type 
2158               
2159           
2160           
2161          configspec = section.configspec 
2162          self._set_configspec(section, copy) 
2163   
2164           
2165          def validate_entry(entry, spec, val, missing, ret_true, ret_false): 
2166              section.default_values.pop(entry, None) 
2167                   
2168              try: 
2169                  section.default_values[entry] = validator.get_default_value(configspec[entry]) 
2170              except (KeyError, AttributeError, validator.baseErrorClass): 
2171                   
2172                   
2173                  pass 
2174               
2175              try: 
2176                  check = validator.check(spec, 
2177                                          val, 
2178                                          missing=missing 
2179                                          ) 
2180              except validator.baseErrorClass, e: 
2181                  if not preserve_errors or isinstance(e, self._vdtMissingValue): 
2182                      out[entry] = False 
2183                  else: 
2184                       
2185                      out[entry] = e 
2186                      ret_false = False 
2187                  ret_true = False 
2188              else: 
2189                  ret_false = False 
2190                  out[entry] = True 
2191                  if self.stringify or missing: 
2192                       
2193                       
2194                      if not self.stringify: 
2195                          if isinstance(check, (list, tuple)): 
2196                               
2197                              check = [self._str(item) for item in check] 
2198                          elif missing and check is None: 
2199                               
2200                              check = '' 
2201                          else: 
2202                              check = self._str(check) 
2203                      if (check != val) or missing: 
2204                          section[entry] = check 
2205                  if not copy and missing and entry not in section.defaults: 
2206                      section.defaults.append(entry) 
2207              return ret_true, ret_false 
 2208           
2209           
2210          out = {} 
2211          ret_true = True 
2212          ret_false = True 
2213           
2214          unvalidated = [k for k in section.scalars if k not in configspec] 
2215          incorrect_sections = [k for k in configspec.sections if k in section.scalars]         
2216          incorrect_scalars = [k for k in configspec.scalars if k in section.sections] 
2217           
2218          for entry in configspec.scalars: 
2219              if entry in ('__many__', '___many___'): 
2220                   
2221                  continue 
2222              if (not entry in section.scalars) or (entry in section.defaults): 
2223                   
2224                   
2225                  missing = True 
2226                  val = None 
2227                  if copy and entry not in section.scalars: 
2228                       
2229                      section.comments[entry] = ( 
2230                          configspec.comments.get(entry, [])) 
2231                      section.inline_comments[entry] = ( 
2232                          configspec.inline_comments.get(entry, '')) 
2233                   
2234              else: 
2235                  missing = False 
2236                  val = section[entry] 
2237               
2238              ret_true, ret_false = validate_entry(entry, configspec[entry], val,  
2239                                                   missing, ret_true, ret_false) 
2240           
2241          many = None 
2242          if '__many__' in configspec.scalars: 
2243              many = configspec['__many__'] 
2244          elif '___many___' in configspec.scalars: 
2245              many = configspec['___many___'] 
2246           
2247          if many is not None: 
2248              for entry in unvalidated: 
2249                  val = section[entry] 
2250                  ret_true, ret_false = validate_entry(entry, many, val, False, 
2251                                                       ret_true, ret_false) 
2252              unvalidated = [] 
2253   
2254          for entry in incorrect_scalars: 
2255              ret_true = False 
2256              if not preserve_errors: 
2257                  out[entry] = False 
2258              else: 
2259                  ret_false = False 
2260                  msg = 'Value %r was provided as a section' % entry 
2261                  out[entry] = validator.baseErrorClass(msg) 
2262          for entry in incorrect_sections: 
2263              ret_true = False 
2264              if not preserve_errors: 
2265                  out[entry] = False 
2266              else: 
2267                  ret_false = False 
2268                  msg = 'Section %r was provided as a single value' % entry 
2269                  out[entry] = validator.baseErrorClass(msg) 
2270                   
2271           
2272           
2273          for entry in section.sections: 
2274               
2275              if section is self and entry == 'DEFAULT': 
2276                  continue 
2277              if section[entry].configspec is None: 
2278                  unvalidated.append(entry) 
2279                  continue 
2280              if copy: 
2281                  section.comments[entry] = configspec.comments.get(entry, []) 
2282                  section.inline_comments[entry] = configspec.inline_comments.get(entry, '') 
2283              check = self.validate(validator, preserve_errors=preserve_errors, copy=copy, section=section[entry]) 
2284              out[entry] = check 
2285              if check == False: 
2286                  ret_true = False 
2287              elif check == True: 
2288                  ret_false = False 
2289              else: 
2290                  ret_true = False 
2291           
2292          section.extra_values = unvalidated 
2293          if preserve_errors and not section._created: 
2294               
2295               
2296              ret_false = False 
2297           
2298          if ret_false and preserve_errors and out: 
2299               
2300               
2301               
2302               
2303              ret_false = not any(out.values()) 
2304          if ret_true: 
2305              return True 
2306          elif ret_false: 
2307              return False 
2308          return out 
2309   
2310   
2312          """Clear ConfigObj instance and restore to 'freshly created' state.""" 
2313          self.clear() 
2314          self._initialise() 
2315           
2316           
2317          self.configspec = None 
2318           
2319          self._original_configspec = None 
 2320           
2321           
2323          """ 
2324          Reload a ConfigObj from file. 
2325           
2326          This method raises a ``ReloadError`` if the ConfigObj doesn't have 
2327          a filename attribute pointing to a file. 
2328          """ 
2329          if not isinstance(self.filename, basestring): 
2330              raise ReloadError() 
2331   
2332          filename = self.filename 
2333          current_options = {} 
2334          for entry in OPTION_DEFAULTS: 
2335              if entry == 'configspec': 
2336                  continue 
2337              current_options[entry] = getattr(self, entry) 
2338               
2339          configspec = self._original_configspec 
2340          current_options['configspec'] = configspec 
2341               
2342          self.clear() 
2343          self._initialise(current_options) 
2344          self._load(filename, configspec) 
 2345           
2346   
2347   
2349      """ 
2350      A simple validator. 
2351      Can be used to check that all members expected are present. 
2352       
2353      To use it, provide a configspec with all your members in (the value given 
2354      will be ignored). Pass an instance of ``SimpleVal`` to the ``validate`` 
2355      method of your ``ConfigObj``. ``validate`` will return ``True`` if all 
2356      members are present, or a dictionary with True/False meaning 
2357      present/missing. (Whole missing sections will be replaced with ``False``) 
2358      """ 
2359       
2362       
2363 -    def check(self, check, member, missing=False): 
 2364          """A dummy check method, always returns the value unchanged.""" 
2365          if missing: 
2366              raise self.baseErrorClass() 
2367          return member 
  2368   
2369   
2371      """ 
2372      An example function that will turn a nested dictionary of results 
2373      (as returned by ``ConfigObj.validate``) into a flat list. 
2374       
2375      ``cfg`` is the ConfigObj instance being checked, ``res`` is the results 
2376      dictionary returned by ``validate``. 
2377       
2378      (This is a recursive function, so you shouldn't use the ``levels`` or 
2379      ``results`` arguments - they are used by the function.) 
2380       
2381      Returns a list of keys that failed. Each member of the list is a tuple:: 
2382       
2383          ([list of sections...], key, result) 
2384       
2385      If ``validate`` was called with ``preserve_errors=False`` (the default) 
2386      then ``result`` will always be ``False``. 
2387   
2388      *list of sections* is a flattened list of sections that the key was found 
2389      in. 
2390       
2391      If the section was missing (or a section was expected and a scalar provided 
2392      - or vice-versa) then key will be ``None``. 
2393       
2394      If the value (or section) was missing then ``result`` will be ``False``. 
2395       
2396      If ``validate`` was called with ``preserve_errors=True`` and a value 
2397      was present, but failed the check, then ``result`` will be the exception 
2398      object returned. You can use this as a string that describes the failure. 
2399       
2400      For example *The value "3" is of the wrong type*. 
2401      """ 
2402      if levels is None: 
2403           
2404          levels = [] 
2405          results = [] 
2406      if res == True: 
2407          return results 
2408      if res == False or isinstance(res, Exception): 
2409          results.append((levels[:], None, res)) 
2410          if levels: 
2411              levels.pop() 
2412          return results 
2413      for (key, val) in res.items(): 
2414          if val == True: 
2415              continue 
2416          if isinstance(cfg.get(key), dict): 
2417               
2418              levels.append(key) 
2419              flatten_errors(cfg[key], val, levels, results) 
2420              continue 
2421          results.append((levels[:], key, val)) 
2422       
2423       
2424      if levels: 
2425          levels.pop() 
2426       
2427      return results 
 2428   
2429   
2431      """ 
2432      Find all the values and sections not in the configspec from a validated 
2433      ConfigObj. 
2434       
2435      ``get_extra_values`` returns a list of tuples where each tuple represents 
2436      either an extra section, or an extra value. 
2437       
2438      The tuples contain two values, a tuple representing the section the value  
2439      is in and the name of the extra values. For extra values in the top level 
2440      section the first member will be an empty tuple. For values in the 'foo' 
2441      section the first member will be ``('foo',)``. For members in the 'bar' 
2442      subsection of the 'foo' section the first member will be ``('foo', 'bar')``. 
2443       
2444      NOTE: If you call ``get_extra_values`` on a ConfigObj instance that hasn't 
2445      been validated it will return an empty list. 
2446      """ 
2447      out = [] 
2448       
2449      out.extend([(_prepend, name) for name in conf.extra_values]) 
2450      for name in conf.sections: 
2451          if name not in conf.extra_values: 
2452              out.extend(get_extra_values(conf[name], _prepend + (name,))) 
2453      return out 
 2454   
2455   
2456  """*A programming language is a medium of expression.* - Paul Graham""" 
2457