8383 write the configuration state in .ini format
8484"""
8585
86- import types
8786import re
8887
8988__all__ = ["NoSectionError" ,"DuplicateSectionError" ,"NoOptionError" ,
9089 "InterpolationError" ,"InterpolationDepthError" ,"ParsingError" ,
9190 "MissingSectionHeaderError" ,"ConfigParser" ,
92- "MAX_INTERPOLATION_DEPTH" ]
91+ "DEFAULTSECT" , " MAX_INTERPOLATION_DEPTH" ]
9392
9493DEFAULTSECT = "DEFAULT"
9594
@@ -200,7 +199,7 @@ def has_section(self, section):
200199
201200 The DEFAULT section is not acknowledged.
202201 """
203- return section in self .sections ()
202+ return section in self .__sections
204203
205204 def options (self , section ):
206205 """Return a list of option names for the given section name."""
@@ -260,40 +259,39 @@ def get(self, section, option, raw=0, vars=None):
260259
261260 The section DEFAULT is special.
262261 """
262+ d = self .__defaults .copy ()
263263 try :
264- sectdict = self .__sections [section ]. copy ( )
264+ d . update ( self .__sections [section ])
265265 except KeyError :
266- if section == DEFAULTSECT :
267- sectdict = {}
268- else :
266+ if section != DEFAULTSECT :
269267 raise NoSectionError (section )
270- d = self .__defaults .copy ()
271- d .update (sectdict )
272268 # Update with the entry specific variables
273269 if vars is not None :
274270 d .update (vars )
275271 option = self .optionxform (option )
276272 try :
277- rawval = d [option ]
273+ value = d [option ]
278274 except KeyError :
279275 raise NoOptionError (option , section )
280276
281277 if raw :
282- return rawval
278+ return value
279+ return self ._interpolate (section , option , value , d )
283280
281+ def _interpolate (self , section , option , rawval , vars ):
284282 # do the string interpolation
285- value = rawval # Make it a pretty variable name
286- depth = 0
287- while depth < 10 : # Loop through this until it's done
288- depth = depth + 1
289- if value .find ("%(" ) >= 0 :
283+ value = rawval
284+ depth = MAX_INTERPOLATION_DEPTH
285+ while depth : # Loop through this until it's done
286+ depth -= 1
287+ if value .find ("%(" ) != - 1 :
290288 try :
291- value = value % d
289+ value = value % vars
292290 except KeyError , key :
293291 raise InterpolationError (key , option , section , rawval )
294292 else :
295293 break
296- if value .find ("%(" ) >= 0 :
294+ if value .find ("%(" ) != - 1 :
297295 raise InterpolationDepthError (option , section , rawval )
298296 return value
299297
@@ -306,58 +304,59 @@ def getint(self, section, option):
306304 def getfloat (self , section , option ):
307305 return self .__get (section , float , option )
308306
307+ _boolean_states = {'1' : True , 'yes' : True , 'true' : True , 'on' : True ,
308+ '0' : False , 'no' : False , 'false' : False , 'off' : False }
309+
309310 def getboolean (self , section , option ):
310- states = {'1' : 1 , 'yes' : 1 , 'true' : 1 , 'on' : 1 ,
311- '0' : 0 , 'no' : 0 , 'false' : 0 , 'off' : 0 }
312311 v = self .get (section , option )
313- if not v .lower () in states :
312+ if v .lower () not in self . _boolean_states :
314313 raise ValueError , 'Not a boolean: %s' % v
315- return states [v .lower ()]
314+ return self . _boolean_states [v .lower ()]
316315
317316 def optionxform (self , optionstr ):
318317 return optionstr .lower ()
319318
320319 def has_option (self , section , option ):
321320 """Check for the existence of a given option in a given section."""
322- if not section or section == "DEFAULT" :
321+ if not section or section == DEFAULTSECT :
322+ option = self .optionxform (option )
323323 return option in self .__defaults
324- elif not self .has_section ( section ) :
324+ elif section not in self .__sections :
325325 return 0
326326 else :
327327 option = self .optionxform (option )
328- return option in self .__sections [section ]
328+ return (option in self .__sections [section ]
329+ or option in self .__defaults )
329330
330331 def set (self , section , option , value ):
331332 """Set an option."""
332- if not section or section == "DEFAULT" :
333+ if not section or section == DEFAULTSECT :
333334 sectdict = self .__defaults
334335 else :
335336 try :
336337 sectdict = self .__sections [section ]
337338 except KeyError :
338339 raise NoSectionError (section )
339- option = self .optionxform (option )
340- sectdict [option ] = value
340+ sectdict [self .optionxform (option )] = value
341341
342342 def write (self , fp ):
343343 """Write an .ini-format representation of the configuration state."""
344344 if self .__defaults :
345- fp .write ("[DEFAULT ]\n " )
345+ fp .write ("[%s ]\n " % DEFAULTSECT )
346346 for (key , value ) in self .__defaults .items ():
347347 fp .write ("%s = %s\n " % (key , str (value ).replace ('\n ' , '\n \t ' )))
348348 fp .write ("\n " )
349- for section in self .sections ():
350- fp .write ("[" + section + "]\n " )
351- sectdict = self .__sections [section ]
352- for (key , value ) in sectdict .items ():
353- if key == "__name__" :
354- continue
355- fp .write ("%s = %s\n " % (key , str (value ).replace ('\n ' , '\n \t ' )))
349+ for section in self .__sections :
350+ fp .write ("[%s]\n " % section )
351+ for (key , value ) in self .__sections [section ].items ():
352+ if key != "__name__" :
353+ fp .write ("%s = %s\n " %
354+ (key , str (value ).replace ('\n ' , '\n \t ' )))
356355 fp .write ("\n " )
357356
358357 def remove_option (self , section , option ):
359358 """Remove an option."""
360- if not section or section == "DEFAULT" :
359+ if not section or section == DEFAULTSECT :
361360 sectdict = self .__defaults
362361 else :
363362 try :
@@ -372,24 +371,22 @@ def remove_option(self, section, option):
372371
373372 def remove_section (self , section ):
374373 """Remove a file section."""
375- if section in self .__sections :
374+ existed = section in self .__sections
375+ if existed :
376376 del self .__sections [section ]
377- return True
378- else :
379- return False
377+ return existed
380378
381379 #
382- # Regular expressions for parsing section headers and options. Note a
383- # slight semantic change from the previous version, because of the use
384- # of \w, _ is allowed in section header names.
380+ # Regular expressions for parsing section headers and options.
381+ #
385382 SECTCRE = re .compile (
386383 r'\[' # [
387384 r'(?P<header>[^]]+)' # very permissive!
388385 r'\]' # ]
389386 )
390387 OPTCRE = re .compile (
391- r'(?P<option>[]\-[\w_.*,(){} ]+)' # a lot of stuff found by IvL
392- r'[ \t] *(?P<vi>[:=])[ \t]*' # any number of space/tab,
388+ r'(?P<option>[^:=\s ]+)' # very permissive!
389+ r'\s *(?P<vi>[:=])\s*' # any number of space/tab,
393390 # followed by separator
394391 # (either : or =), followed
395392 # by any # space/tab
@@ -418,15 +415,13 @@ def __read(self, fp, fpname):
418415 # comment or blank line?
419416 if line .strip () == '' or line [0 ] in '#;' :
420417 continue
421- if line .split ()[0 ].lower () == 'rem' \
422- and line [0 ] in "rR" : # no leading whitespace
418+ if line .split (None , 1 )[0 ].lower () == 'rem' and line [0 ] in "rR" : # no leading whitespace
423419 continue
424420 # continuation line?
425- if line [0 ] in ' \t ' and cursect is not None and optname :
421+ if line [0 ]. isspace () and cursect is not None and optname :
426422 value = line .strip ()
427423 if value :
428- k = self .optionxform (optname )
429- cursect [k ] = "%s\n %s" % (cursect [k ], value )
424+ cursect [optname ] = "%s\n %s" % (cursect [optname ], value )
430425 # a section header or option header?
431426 else :
432427 # is it a section header?
@@ -454,13 +449,14 @@ def __read(self, fp, fpname):
454449 # ';' is a comment delimiter only if it follows
455450 # a spacing character
456451 pos = optval .find (';' )
457- if pos and optval [pos - 1 ].isspace ():
452+ if pos != - 1 and optval [pos - 1 ].isspace ():
458453 optval = optval [:pos ]
459454 optval = optval .strip ()
460455 # allow empty values
461456 if optval == '""' :
462457 optval = ''
463- cursect [self .optionxform (optname )] = optval
458+ optname = self .optionxform (optname )
459+ cursect [optname ] = optval
464460 else :
465461 # a non-fatal parsing error occurred. set up the
466462 # exception but keep going. the exception will be
0 commit comments