from typing import Union
import base64


def is_base64(sb: Union[str, bytes], urlsafe: bool = True) -> bool:
    """
    Returns ``True`` if ``sb`` appears to be a Base64 encoded string/bytes, otherwise ``False``

    :param str|bytes sb: Data to check for base64 encoding
    :param bool urlsafe: (Default: ``True``) Use :py:func:`base64.urlsafe_b64encode` and decode, instead of
                         plain :py:func:`base64.b64encode` and decode.
    :return bool is_base64: ``True`` if data appears to be Base64, otherwise ``False``
    """
    b64_enc = base64.urlsafe_b64encode if urlsafe else base64.b64encode
    b64_dec = base64.urlsafe_b64decode if urlsafe else base64.b64decode
    try:
        if isinstance(sb, str):
            # If there's any unicode here, an exception will be thrown and the function will return false
            sb = bytes(sb, 'ascii')
        if not isinstance(sb, bytes):
            raise ValueError("Argument 'sb' must be string or bytes")
        return b64_enc(b64_dec(sb)) == sb
    except Exception:
        return False