def _interpolate_some(self, parser, option, accum, rest, section, map,
                       depth):
     rawval = parser.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 = parser.optionxform(path[0])
                     v = self._resolve_option(opt, map)
                 elif len(path) == 2:
                     sect = path[0]
                     opt = path[1]
                     v = self._resolve_section_option(sect, opt, parser)
                 else:
                     raise InterpolationSyntaxError(
                         option, section,
                         "More than one ':' found: %r" % (rest, ))
             except (KeyError, NoSectionError, NoOptionError):
                 raise InterpolationMissingOptionError(
                     option, section, rawval, ":".join(path)) from None
             if "$" in v:
                 self._interpolate_some(parser, opt, accum, v, sect,
                                        dict(parser.items(sect, raw=True)),
                                        depth + 1)
             else:
                 accum.append(v)
         else:
             raise InterpolationSyntaxError(
                 option, section, "'$' must be followed by '$' or '{', "
                 "found: %r" % (rest, ))
Exemple #2
0
    def _interpolate_ext(self, dst, parser, section, option, rawval, defaults,
                         loop_detect):
        if not rawval:
            return

        if len(loop_detect) > MAX_INTERPOLATION_DEPTH:
            raise InterpolationDepthError(option, section, rawval)

        xloop = (section, option)
        if xloop in loop_detect:
            raise InterpolationError(
                section, option,
                'Loop detected: %r in %r' % (xloop, loop_detect))
        loop_detect.add(xloop)

        parts = self._var_rc.split(rawval)
        for i, frag in enumerate(parts):
            fullkey = None
            use_vars = defaults
            if i % 2 == 0:
                dst.append(frag)
                continue
            if frag in ('$$', '%%'):
                dst.append(frag[0])
                continue
            if frag.startswith('${') and frag.endswith('}'):
                fullkey = frag[2:-1]

                # use section access only for new-style keys
                if ':' in fullkey:
                    ksect, key = fullkey.split(':', 1)
                    use_vars = None
                else:
                    ksect, key = section, fullkey
            elif frag.startswith('%(') and frag.endswith(')s'):
                fullkey = frag[2:-2]
                ksect, key = section, fullkey
            else:
                raise InterpolationError(section, option,
                                         'Internal parse error: %r' % frag)

            key = parser.optionxform(key)
            newpart = parser.get(ksect, key, raw=True, vars=use_vars)
            if newpart is None:
                raise InterpolationError(ksect, key, 'Key referenced is None')
            self._interpolate_ext(dst, parser, ksect, key, newpart, defaults,
                                  loop_detect)

        loop_detect.remove(xloop)
Exemple #3
0
    def _interpolate_ext_new(self, dst, parser, section, option, rawval,
                             defaults, loop_detect):
        if not rawval:
            return rawval

        if len(loop_detect) > MAX_INTERPOLATION_DEPTH:
            raise InterpolationDepthError(option, section, rawval)

        xloop = (section, option)
        if xloop in loop_detect:
            raise InterpolationError(
                option, section,
                'Loop detected: %r in %r' % (xloop, loop_detect))
        loop_detect.add(xloop)

        def lookup_helper(lk_section, lk_option):
            if '!' in lk_option:
                funcname, val = lk_option.split('!', 1)
                func = None
                if self._func_map:
                    func = self._func_map.get(funcname.strip())
                if not func:
                    raise InterpolationError(
                        option, section,
                        'Unknown interpolation function: %r' % funcname)
                return func(val.strip(), lk_section, lk_option)

            # normal fetch
            if ':' in lk_option:
                ksect, key = lk_option.split(':', 1)
                ksect, key = ksect.strip(), key.strip()
                use_vars = None
            else:
                ksect, key = lk_section, lk_option.strip()
                use_vars = defaults
            key = parser.optionxform(key)
            newpart = parser.get(ksect, key, raw=True, vars=use_vars)
            if newpart is None:
                raise InterpolationError(key, ksect, 'Key referenced is None')
            dst = []
            self._interpolate_ext_new(dst, parser, ksect, key, newpart,
                                      defaults, loop_detect)
            return ''.join(dst)

        val = new_interpolate(section, option, rawval, lookup_helper)
        dst.append(val)
        loop_detect.remove(xloop)
Exemple #4
0
 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
Exemple #5
0
 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: " + repr(rest))
Exemple #6
0
 def interpolate(self, parser, option, accum, rest, section, map, depth):
     # Mostly copy-pasted from the built-in configparser implementation.
     # We need to overwrite this method so we can add special handling for
     # block references :( All values produced here should be strings –
     # we need to wait until the whole config is interpreted anyways so
     # filling in incomplete values here is pointless. All we need is the
     # section reference so we can fetch it later.
     rawval = parser.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 == "{":
             # We want to treat both ${a:b} and ${a.b} the same
             m = self._KEYCRE.match(rest)
             if m is None:
                 err = f"bad interpolation variable reference {rest}"
                 raise InterpolationSyntaxError(option, section, err)
             path = m.group(1).replace(":", ".").rsplit(".", 1)
             rest = rest[m.end():]
             sect = section
             opt = option
             try:
                 if len(path) == 1:
                     opt = parser.optionxform(path[0])
                     if opt in map:
                         v = map[opt]
                     else:
                         # We have block reference, store it as a special key
                         section_name = parser[parser.optionxform(
                             path[0])]._name
                         v = self._get_section_name(section_name)
                 elif len(path) == 2:
                     sect = path[0]
                     opt = parser.optionxform(path[1])
                     fallback = "__FALLBACK__"
                     v = parser.get(sect, opt, raw=True, fallback=fallback)
                     # If a variable doesn't exist, try again and treat the
                     # reference as a section
                     if v == fallback:
                         v = self._get_section_name(
                             parser[f"{sect}.{opt}"]._name)
                 else:
                     err = f"More than one ':' found: {rest}"
                     raise InterpolationSyntaxError(option, section, err)
             except (KeyError, NoSectionError, NoOptionError):
                 raise InterpolationMissingOptionError(
                     option, section, rawval, ":".join(path)) from None
             if "$" in v:
                 new_map = dict(parser.items(sect, raw=True))
                 self.interpolate(parser, opt, accum, v, sect, new_map,
                                  depth + 1)
             else:
                 accum.append(v)
         else:
             err = "'$' must be followed by '$' or '{', " "found: %r" % (
                 rest, )
             raise InterpolationSyntaxError(option, section, err)
Exemple #7
0
    def interpolate(self, parser, section, option, value, _, depth=0):
        if depth > MAX_INTERPOLATION_DEPTH:
            raise InterpolationDepthError(option, section, value)

        # short cut operations if empty or a normal string
        if (value == ""):
            # print("interpol: SHORT -> empty string")
            return ""
        elif (("$" not in value) and ("%" not in value)):
            # print("interpol: SHORT -> {0}".format(value))
            return value

        # print("interpol: PREPARE section={0} option={1} value='{2}'".format(section, option, value))
        rawValue = value
        rest = ""

        while (len(rawValue) > 0):
            beginPos = rawValue.find("%")
            if (beginPos < 0):
                rest += rawValue
                rawValue = ""
            else:
                rest += rawValue[:beginPos]
                if (rawValue[beginPos + 1] == "%"):
                    rest += "%"
                    rawValue = rawValue[1:]
                elif (rawValue[beginPos + 1] == "{"):
                    endPos = rawValue.find("}", beginPos)
                    if (endPos < 0):
                        raise InterpolationSyntaxError(
                            option, section,
                            "bad interpolation variable reference {0!r}".
                            format(rawValue))
                    path = rawValue[beginPos + 2:endPos]
                    rawValue = rawValue[endPos + 1:]
                    rest += self.GetSpecial(section, option, path)

        # print("interpol: BEGIN   section={0} option={1} value='{2}'".format(section, option, rest))
        result = ""
        while (len(rest) > 0):
            # print("interpol: LOOP    rest='{0}'".format(rest))
            beginPos = rest.find("$")
            if (beginPos < 0):
                result += rest
                rest = ""
            else:
                result += rest[:beginPos]
                if (rest[beginPos + 1] == "$"):
                    result += "$"
                    rest = rest[1:]
                elif (rest[beginPos + 1] == "{"):
                    endPos = rest.find("}", beginPos)
                    nextPos = rest.rfind("$", beginPos, endPos)
                    if (endPos < 0):
                        raise InterpolationSyntaxError(
                            option, section,
                            "bad interpolation variable reference {0!r}".
                            format(rest))
                    if ((nextPos > 0)
                            and (nextPos < endPos)):  # an embedded $-sign
                        path = rest[nextPos + 2:endPos]
                        # print("interpol: path='{0}'".format(path))
                        innervalue = self.GetValue(parser, section, option,
                                                   path)
                        # innervalue = self.interpolate(parser, section, option, path, map, depth + 1)
                        # print("interpol: innervalue='{0}'".format(innervalue))
                        rest = rest[beginPos:nextPos] + innervalue + rest[
                            endPos + 1:]
                        # print("interpol: new rest='{0}'".format(rest))
                    else:
                        path = rest[beginPos + 2:endPos]
                        rest = rest[endPos + 1:]
                        result += self.GetValue(parser, section, option, path)

                    # print("interpol: LOOP END - result='{0}'".format(result))

        # print("interpol: RESULT => '{0}'".format(result))
        return result