Safe string template expansion. Raises an error if the provided substitution mapping has circularities.

def safe_expand(template, mapping):
    """
    Safe string template expansion. Raises an error if the provided substitution mapping has circularities.
    """
    for _ in range(len(mapping) + 1):
        _template = template
        template = string.Template(template).safe_substitute(mapping)
        if template == _template:
            return template
    else:
        raise ValueError("circular mapping provided!")