Parse a string for possible escape sequences.

    Sample usage:
    >>> parse_escape_sequences('foo\\nbar')
    'foo\nbar'
    >>> parse_escape_sequences('foo\\\\u0256')
    'foo\\u0256'

    :param string:
        Any string.
    :type string:
        `basestring`
    :raises:
        :class:`ValueError` if a backslash character is found, but it doesn't
        form a proper escape sequence with the character(s) that follow.
    :return:
        The parsed string. Will parse the standard escape sequences, and also
        basic \\uxxxx escape sequences.
        \\uxxxxxxxxxx escape sequences are not currently supported.
    :rtype:
        `unicode`

def parse_escape_sequences(string):
    """Parse a string for possible escape sequences.

    Sample usage:
    >>> parse_escape_sequences('foo\\nbar')
    'foo\nbar'
    >>> parse_escape_sequences('foo\\\\u0256')
    'foo\\u0256'

    :param string:
        Any string.
    :type string:
        `basestring`
    :raises:
        :class:`ValueError` if a backslash character is found, but it doesn't
        form a proper escape sequence with the character(s) that follow.
    :return:
        The parsed string. Will parse the standard escape sequences, and also
        basic \\uxxxx escape sequences.
        \\uxxxxxxxxxx escape sequences are not currently supported.
    :rtype:
        `unicode`
    """
    string = safe_unicode(string)
    characters = []
    i = 0
    string_len = len(string)
    while i < string_len:
        character = string[i]
        if character == '\\':
            # Figure out the size of the escape sequence. Most escape sequences
            # are two characters (e.g. '\\' and 'n'), with the sole exception
            # being \uxxxx escape sequences, which are six characters.
            if string[(i + 1):(i + 2)] == 'u':
                offset = 6
            else:
                offset = 2

            try:
                # `json.decoder.scanstring()` mostly does what we want, but it
                # also does some stuff that we don't want, like parsing quote
                # characters. This will mess us up. The iteration and scanning
                # within this loop is meant to isolate the escape sequences, so
                # that we'll always be calling it with something like
                # >>> scanstring('"\n"', 1)
                # or
                # >>> scanstring('"\u0256"', 1)
                # The 1 refers to the location of the first character after the
                # open quote character.
                json_string = '"' + string[i:(i + offset)] + '"'
                character = scanstring(json_string, 1)[0]
                characters.append(character)
                i += offset
            except ValueError:
                # If an exception was raised, raise a new `ValueError`. The
                # reason we don't re-raise the original exception is because,
                # in Python 3, it is a custom JSON `ValueError` subclass. We
                # don't want to raise a JSON error from a function that has
                # nothing to do with JSON, so we create a new `ValueError`. The
                # error message is also nonsensical to the caller, in all
                # cases.
                raise_from(ValueError(string), None)
        else:
            characters.append(character)
            i += 1
    return ''.join(characters)