def get(self, section, option, raw=False, current_depth=0): valueRaw = RawConfigParser.get(self, section, option) if raw: return valueRaw self.cur_depth = current_depth #Find all instances of ${(alphanumeric characters):(alphanumeric characters)} ret = valueRaw varSectOpts = re.findall(r'\$\{(\w*):(\w*)\}', ret) if varSectOpts: for v_section, v_option in varSectOpts: self.cur_depth = self.cur_depth + 1 #Skip matches which do not correspond to any section if not v_section in self.sections(): continue #Skip matches which do not correspond to any option if not v_option in self.options(v_section): continue #Try to get the value for the corresponding section/option #(avoid infinite loops with interpolation depth: self.cur_depth = self.cur_depth + 1 if self.cur_depth < self.MAX_INTERPOLATION_DEPTH: sub = self.get(v_section, v_option, current_depth=self.cur_depth) #Replace all instances of (section):(option) ret = re.sub(r'\$\{%s:%s\}' % (v_section, v_option), str(sub), ret) else: raise InterpolationDepthError(option, section, valueRaw) #Now try to get all variables from the same section: for v_option in self.options(section): #Check if the option appears in the string surrounded by any non-alphanumeric character #or the beginning of the expression or end of the expression if re.findall(r'\$\{%s\}' % v_option, ret): self.cur_depth = self.cur_depth + 1 if self.cur_depth < self.MAX_INTERPOLATION_DEPTH: sub = self.get(section, v_option, current_depth=self.cur_depth) #Replaces the correct instances: ret = re.sub(r'\$\{%s\}' % v_option, str(sub), ret) else: raise InterpolationDepthError(option, section, valueRaw) try: return eval(ret) except: return ret
def _interpolate_some(self, option, accum, rest, section, map, depth): rawval = self.get(section, option, raw=True, fallback=rest) if depth > MAX_INTERPOLATION_DEPTH: raise InterpolationDepthError(option, section, rawval) while rest: p = rest.find("$") if p < 0: accum.append(rest) return if p > 0: accum.append(rest[:p]) rest = rest[p:] # p is no longer used c = rest[1:2] if c == "$": accum.append("$") rest = rest[2:] elif c == "{": m = self._KEYCRE.match(rest) if m is None: raise InterpolationSyntaxError( option, section, "bad interpolation variable reference %r" % rest) path = m.group(1).split(':') rest = rest[m.end():] sect = section opt = option try: if len(path) == 1: opt = self.optionxform(path[0]) v = map[opt] elif len(path) == 2: sect = path[0] opt = self.optionxform(path[1]) v = self.get(sect, opt, raw=True) else: raise InterpolationSyntaxError( option, section, "More that one ':' found: %r" % (rest, )) except (KeyError, NoSectionError, NoOptionError): raise InterpolationMissingOptionError( option, section, rawval, ":".join(path)) if "$" in v: self._interpolate_some(opt, accum, v, sect, dict(self.items(sect, raw=True)), depth + 1) else: accum.append(v) else: raise InterpolationSyntaxError( option, section, "'$' must be followed by '$' or '{', " "found: %r" % (rest, ))
def _interpolate(self, section, option, rawval, vars): # do the string interpolation value = rawval depth = MAX_INTERPOLATION_DEPTH while depth: # Loop through this until it's done depth -= 1 if "%(" in value: try: value = value % vars except KeyError as e: raise InterpolationMissingOptionError( option, section, rawval, e.args[0]) else: break if value.find("%(") != -1: raise InterpolationDepthError(option, section, rawval) return value
class ConfigParser(RawConfigParser): def get(self, section, option, raw=False, vars=None): """Get an option value for a given section. All % interpolations are expanded in the return values, based on the defaults passed into the constructor, unless the optional argument `raw' is true. Additional substitutions may be provided using the `vars' argument, which must be a dictionary whose contents overrides any pre-existing defaults. The section DEFAULT is special. """ if section != DEFAULTSECT and not self.has_section(section): raise NoSectionError(section) option = self.optionxform(option) value = RawConfigParser.get(self, section, option, vars) if raw: return value else: d = ConfigDict(self, section, vars) return self._interpolate(section, option, value, d) def _interpolate(self, section, option, rawval, vars): # do the string interpolation value = rawval depth = MAX_INTERPOLATION_DEPTH while depth: # Loop through this until it's done depth -= 1 if "%(" in value: try: value = value % vars except KeyError, e: raise InterpolationMissingOptionError( option, section, rawval, e[0]) else: break if value.find("%(") != -1: raise InterpolationDepthError(option, section, rawval) return value
def _interpolate_some(self, option, accum, rest, section, map, depth): if depth > MAX_INTERPOLATION_DEPTH: raise InterpolationDepthError(option, section, rest) while rest: p = rest.find("%") if p < 0: accum.append(rest) return if p > 0: accum.append(rest[:p]) rest = rest[p:] # p is no longer used c = rest[1:2] if c == "%": accum.append("%") rest = rest[2:] elif c == "(": m = self._interpvar_match(rest) if m is None: raise InterpolationSyntaxError( option, section, "bad interpolation variable reference %r" % rest) var = m.group(1) rest = rest[m.end():] try: v = map[var] except KeyError: raise InterpolationMissingOptionError( option, section, rest, var) if "%" in v: self._interpolate_some(option, accum, v, section, map, depth + 1) else: accum.append(v) else: raise InterpolationSyntaxError( option, section, "'%' must be followed by '%' or '(', found: " + ` rest `)