def safe_modulo(s, meta, checked='', print_warning=True, stacklevel=2):
    """Safe version of the modulo operation (%) of strings

    Parameters
    ----------
    s: str
        string to apply the modulo operation with
    meta: dict or tuple
        meta informations to insert (usually via ``s % meta``)
    checked: {'KEY', 'VALUE'}, optional
        Security parameter for the recursive structure of this function. It can
        be set to 'VALUE' if an error shall be raised when facing a TypeError
        or ValueError or to 'KEY' if an error shall be raised when facing a
        KeyError. This parameter is mainly for internal processes.
    print_warning: bool
        If True and a key is not existent in `s`, a warning is raised
    stacklevel: int
        The stacklevel for the :func:`warnings.warn` function


    Examples
    --------
    The effects are demonstrated by this example::

        >>> from docrep import safe_modulo
        >>> s = "That's %(one)s string %(with)s missing 'with' and %s key"
        >>> s % {'one': 1}          # raises KeyError because of missing 'with'
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        KeyError: 'with'
        >>> s % {'one': 1, 'with': 2}        # raises TypeError because of '%s'
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        TypeError: not enough arguments for format string
        >>> safe_modulo(s, {'one': 1})
        "That's 1 string %(with)s missing 'with' and %s key"
    """
    try:
        return s % meta
    except (ValueError, TypeError, KeyError):
        # replace the missing fields by %%
        keys = substitution_pattern.finditer(s)
        for m in keys:
            key = m.group('key')
            if not isinstance(meta, dict) or key not in meta:
                if print_warning:
                    warn("%r is not a valid key!" % key, SyntaxWarning,
                         stacklevel)
                full = m.group()
                s = s.replace(full, '%' + full)
        if 'KEY' not in checked:
            return safe_modulo(s, meta, checked=checked + 'KEY',
                               print_warning=print_warning,
                               stacklevel=stacklevel)
        if not isinstance(meta, dict) or 'VALUE' in checked:
            raise
        s = re.sub(r"""(?<!%)(%%)*%(?!%) # uneven number of %
                    \s*(\w|$)         # format strings""", '%\g<0>', s,
                   flags=re.VERBOSE)
        return safe_modulo(s, meta, checked=checked + 'VALUE',
                           print_warning=print_warning, stacklevel=stacklevel)
def safe_modulo ( s , meta , checked = '' , print_warning = True , stacklevel = 2 ) : try : return s % meta except ( ValueError , TypeError , KeyError ) : keys = substitution_pattern . finditer ( s ) for m in keys : key = m . group ( 'key' ) if not isinstance ( meta , dict ) or key not in meta : if print_warning : warn ( "%r is not a valid key!" % key , SyntaxWarning , stacklevel ) full = m . group ( ) s = s . replace ( full , '%' + full ) if 'KEY' not in checked : return safe_modulo ( s , meta , checked = checked + 'KEY' , print_warning = print_warning , stacklevel = stacklevel ) if not isinstance ( meta , dict ) or 'VALUE' in checked : raise s = re . sub ( r"""(?<!%)(%%)*%(?!%) # uneven number of %
                    \s*(\w|$)         # format strings""" , '%\g<0>' , s , flags = re . VERBOSE ) return safe_modulo ( s , meta , checked = checked + 'VALUE' , print_warning = print_warning , stacklevel = stacklevel )
Safe version of the modulo operation (%) of strings

    Parameters
    ----------
    s: str
        string to apply the modulo operation with
    meta: dict or tuple
        meta informations to insert (usually via ``s % meta``)
    checked: {'KEY', 'VALUE'}, optional
        Security parameter for the recursive structure of this function. It can
        be set to 'VALUE' if an error shall be raised when facing a TypeError
        or ValueError or to 'KEY' if an error shall be raised when facing a
        KeyError. This parameter is mainly for internal processes.
    print_warning: bool
        If True and a key is not existent in `s`, a warning is raised
    stacklevel: int
        The stacklevel for the :func:`warnings.warn` function


    Examples
    --------
    The effects are demonstrated by this example::

        >>> from docrep import safe_modulo
        >>> s = "That's %(one)s string %(with)s missing 'with' and %s key"
        >>> s % {'one': 1}          # raises KeyError because of missing 'with'
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        KeyError: 'with'
        >>> s % {'one': 1, 'with': 2}        # raises TypeError because of '%s'
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        TypeError: not enough arguments for format string
        >>> safe_modulo(s, {'one': 1})
        "That's 1 string %(with)s missing 'with' and %s key"