@@ -538,3 +538,51 @@ def _interpolate(self, section, option, rawval, vars):
538538 if value .find ("%(" ) != - 1 :
539539 raise InterpolationDepthError (option , section , rawval )
540540 return value
541+
542+
543+ class SafeConfigParser (ConfigParser ):
544+
545+ def _interpolate (self , section , option , rawval , vars ):
546+ # do the string interpolation
547+ L = []
548+ self ._interpolate_some (option , L , rawval , section , vars , 1 )
549+ return '' .join (L )
550+
551+ _interpvar_match = re .compile (r"%\(([^)]+)\)s" ).match
552+
553+ def _interpolate_some (self , option , accum , rest , section , map , depth ):
554+ if depth > MAX_INTERPOLATION_DEPTH :
555+ raise InterpolationDepthError (option , section , rest )
556+ while rest :
557+ p = rest .find ("%" )
558+ if p < 0 :
559+ accum .append (rest )
560+ return
561+ if p > 0 :
562+ accum .append (rest [:p ])
563+ rest = rest [p :]
564+ # p is no longer used
565+ c = rest [1 :2 ]
566+ if c == "%" :
567+ accum .append ("%" )
568+ rest = rest [2 :]
569+ elif c == "(" :
570+ m = self ._interpvar_match (rest )
571+ if m is None :
572+ raise InterpolationSyntaxError (
573+ "bad interpolation variable syntax at: %r" % rest )
574+ var = m .group (1 )
575+ rest = rest [m .end ():]
576+ try :
577+ v = map [var ]
578+ except KeyError :
579+ raise InterpolationError (
580+ "no value found for %r" % var )
581+ if "%" in v :
582+ self ._interpolate_some (option , accum , v ,
583+ section , map , depth + 1 )
584+ else :
585+ accum .append (v )
586+ else :
587+ raise InterpolationSyntaxError (
588+ "'%' must be followed by '%' or '('" )
0 commit comments