def to_unicode(obj, encoding='<STR_LIT:utf-8>', fallback='<STR_LIT>', **decode_args):
<EOL>if not isinstance(obj, binary_type):<EOL><INDENT>if isinstance(obj, text_type) or hasattr(obj, text_type_magicmethod):<EOL><INDENT>return text_type(obj)<EOL><DEDENT>obj_str = binary_type(obj)<EOL><DEDENT>else:<EOL><INDENT>obj_str = obj<EOL><DEDENT>try:<EOL><INDENT>return text_type(obj_str, encoding, **decode_args)<EOL><DEDENT>except UnicodeDecodeError:<EOL><INDENT>return text_type(obj_str, fallback, **decode_args)<EOL><DEDENT>
r"""
    Returns a ``unicode`` of ``obj``, decoding using ``encoding`` if necessary.
    If decoding fails, the ``fallback`` encoding (default ``latin1``) is used.

    Examples::

        >>> r(to_unicode(b'\xe1\x88\xb4'))
        u'\u1234'
        >>> r(to_unicode(b'\xff'))
        u'\xff'
        >>> r(to_unicode(u'\u1234'))
        u'\u1234'
        >>> r(to_unicode(Exception(u'\u1234')))
        u'\u1234'
        >>> r(to_unicode([42]))
        u'[42]'

    See source code for detailed semantics.