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, ))
Example #2
0
def new_interpolate(cur_sect, cur_key, value, lookup_func):
    """Recursive interp

    >>> lookup = lambda s, x: '<'+x+'>'
    >>> new_interpolate('sect', 'key', 'text', lookup)
    'text'
    >>> new_interpolate('sect', 'key', 'foo.${baz}.com', lookup)
    'foo.<baz>.com'
    >>> new_interpolate('sect', 'key', 'foo.${baz.${goo}.zap}.com', lookup)
    'foo.<baz.<goo>.zap>.com'
    """
    if not value:
        return value

    pos = 0
    dst = []
    while pos < len(value):
        m = _NEW_VAR_OPEN_RX.search(value, pos)
        if not m:
            dst.append(value[pos:])
            break
        pos2 = m.start()
        if pos2 > pos:
            dst.append(value[pos:pos2])
        pos = m.end()
        tok = m.group(0)
        if tok == '$$':
            dst.append('$')
        elif tok == '${':
            subval, pos = _scan_key(cur_sect, cur_key, value, pos, lookup_func)
            dst.append(subval)
        else:
            raise InterpolationSyntaxError(cur_key, cur_sect,
                                           'Interpolation parse error')
    return ''.join(dst)
Example #3
0
    def GetValue(self, parser, section, option, path):
        path = path.split(":")
        if (len(path) == 1):
            sec = section
            opt = parser.optionxform(path[0])
        elif (len(path) == 2):
            sec = path[0]
            opt = parser.optionxform(path[1])
        else:
            raise InterpolationSyntaxError(option, section,
                                           "More than one ':' found.")

        try:
            return self.GetCached(sec, opt)
        except KeyError:
            pass

        try:
            value = parser.get(sec, opt, raw=True)
            # print("GetValue: successful parser access: '{0}'".format(value))
        except (KeyError, NoSectionError, NoOptionError) as ex:
            raise InterpolationMissingOptionError(option, section, "",
                                                  ":".join(path)) from ex

        if (("$" in value) or ("%" in value)):
            value = self.interpolate(parser, sec, opt, value, {})

        self.UpdateCache(sec, opt, value)
        return value
Example #4
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))
Example #5
0
 def GetSpecial(self, section, option, path):
     parts = section.split(".")
     if (path == "Root"):
         return parts[0]
     elif (path == "Parent"):
         return ".".join(parts[1:-1])
     elif (path == "ParentWithRoot"):
         return ".".join(parts[:-1])
     elif (path == "GrantParent"):
         return ".".join(parts[1:-2])
     elif (path == "Path"):
         return ".".join(parts[1:])
     elif (path == "PathWithRoot"):
         return section
     elif (path == "Name"):
         return parts[-1]
     else:
         raise InterpolationSyntaxError(
             option, section,
             "Unknown keyword '{0}'in special operator.".format(path))
Example #6
0
    def before_get(self, parser, section, option, value, defaults):
        dollar_ind = value.find('$')
        if dollar_ind == -1:
            return value

        colon_ind = value.find('::')
        if colon_ind != -1 and value[dollar_ind + 1:colon_ind] == 'ENV':
            env_name = value[colon_ind + 2:]
            return parser.env.get(env_name)

        m = self._KEYCRE.match(value[dollar_ind:])
        if m is None:
            raise InterpolationSyntaxError(option, section,
                                           f'bad interpolation variable reference {value}')
        var = parser.optionxform(m.group(1))
        try:
            val = defaults[var]
        except KeyError:
            raise InterpolationMissingOptionError(option, section, value, var) from None

        # the resolved value can also contain variables
        val = self.before_get(parser, section, option, val, defaults)

        return val + value[m.end():]
Example #7
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)
Example #8
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