def unescape_path(path):
    """Decodes a percent-encoded URL path.

    Raises `ValueError` if the escaping is incorrect.
    """
    idx = 0
    while True:
        idx = path.find('%', idx)
        if idx == -1:
            return path
        start = idx
        data = []
        while True:
            hex_num = path[idx + 1:idx + 3]
            if len(hex_num) != 2:
                raise ValueError(
                    'incomplete escape, expected 2 characters after "%"')
            idx += 3
            try:
                if '-' in hex_num:
                    raise ValueError()
                value = int(hex_num, 16)
            except ValueError:
                raise ValueError(
                    'incorrect escape: expected 2 hex digits after "%%", got "%s"'
                     % hex_num)
            data.append(value)
            if len(data) > 1:
                if value & 192 == 128:
                    remaining -= 1
                    if remaining == 0:
                        path = path[:start] + bytes(data).decode() + path[idx:]
                        break
                else:
                    raise ValueError(
                        'invalid percent-encoded UTF8: expected 0x80..0xBF for non-first byte, got 0x%02X'
                         % value)
            elif value == 47:
                path = path[:start] + '%2f' + path[idx:]
                break
            elif value < 128:
                path = path[:start] + chr(value) + path[idx:]
                break
            elif value < 192 or value >= 248:
                raise ValueError(
                    'invalid percent-encoded UTF8: expected 0xC0..0xF7 for first byte, got 0x%02X'
                     % value)
            elif value < 224:
                remaining = 1
            elif value < 240:
                remaining = 2
            elif value < 248:
                remaining = 3
            else:
                assert False, value
            if idx == len(path) or path[idx] != '%':
                raise ValueError(
                    'incomplete escaped UTF8 character, expected %d more escaped bytes'
                     % remaining)
