from typing import Callable
from typing import Iterable


def _attribute_transformer(prefix: str, scrub_message: str, keep: bool) -> Callable:
    """
    Create a function which may be used to transform exception attributes.

    If an attribute is string-valued, apply the logic keep? prefix + attr: prefix
    + scrub_message.

    If the attribute is iterable, apply this logic to each member of the
    attribute.

    If the attribute is callable, don't change it.

    If it is neither, replace it with None to ensure no private data leaks.
    """

    def inner(o):
        rv = o
        if isinstance(o, str):
            if keep:
                rv = prefix + o
            else:
                rv = prefix + scrub_message
        elif isinstance(o, Iterable):
            rv = type(o)(map(inner, o))  # type: ignore
        elif callable(o):
            rv = rv
        elif not keep:
            rv = None

        return rv

    return inner