# Path: aredis/commands/cluster.py
# def parse_cluster_slots(response):
#     res = dict()
#     for slot_info in response:
#         min_slot, max_slot = slot_info[:2]
#         nodes = slot_info[2:]
#         parse_node = lambda node: {
#             'host': node[0],
#             'port': node[1],
#             'node_id': node[2] if len(node) > 2 else '',
#             'server_type': 'slave'
#         }
#         res[(min_slot, max_slot)] = [parse_node(node) for node in nodes]
#         res[(min_slot, max_slot)][0]['server_type'] = 'master'
#     return res
# 
# Path: aredis/exceptions.py
# class RedisClusterException(Exception):
#     pass
# 
# class ClusterDownError(ClusterError, ResponseError):
# 
#     def __init__(self, resp):
#         self.args = (resp,)
#         self.message = resp
# 
# Path: aredis/utils.py
# def list_keys_to_dict(key_list, callback):
#     return dict.fromkeys(key_list, callback)
# 
# def b(x):
#     return x.encode('latin-1') if not isinstance(x, bytes) else x
# 
# def dict_merge(*dicts):
#     merged = {}
#     for d in dicts:
#         merged.update(d)
#     return merged
# 
# def blocked_command(self, command):
#     """
#     Raises a `RedisClusterException` mentioning the command is blocked.
#     """
#     raise RedisClusterException("Command: {0} is blocked in redis cluster mode".format(command))
# 
# def merge_result(res):
#     """
#     Merges all items in `res` into a list.
# 
#     This command is used when sending a command to multiple nodes
#     and they result from each node should be merged into a single list.
#     """
#     if not isinstance(res, dict):
#         raise ValueError('Value should be of dict type')
# 
#     result = set([])
# 
#     for _, v in res.items():
#         for value in v:
#             result.add(value)
# 
#     return list(result)
# 
# def first_key(res):
#     """
#     Returns the first result for the given command.
# 
#     If more then 1 result is returned then a `RedisClusterException` is raised.
#     """
#     if not isinstance(res, dict):
#         raise ValueError('Value should be of dict type')
# 
#     if len(res.keys()) != 1:
#         raise RedisClusterException("More then 1 result from command")
# 
#     return list(res.values())[0]
# 
# def clusterdown_wrapper(func):
#     """
#     Wrapper for CLUSTERDOWN error handling.
# 
#     If the cluster reports it is down it is assumed that:
#      - connection_pool was disconnected
#      - connection_pool was reseted
#      - refereh_table_asap set to True
# 
#     It will try 3 times to rerun the command and raises ClusterDownException if it continues to fail.
#     """
# 
#     @wraps(func)
#     async def inner(*args, **kwargs):
#         for _ in range(0, 3):
#             try:
#                 return await func(*args, **kwargs)
#             except ClusterDownError:
#                 # Try again with the new cluster setup. All other errors
#                 # should be raised.
#                 pass
# 
#         # If it fails 3 times then raise exception back to caller
#         raise ClusterDownError("CLUSTERDOWN error. Unable to rebuild the cluster")
# 
#     return inner


from aredis.commands.cluster import parse_cluster_slots
from aredis.exceptions import (
    RedisClusterException, ClusterDownError
)
from aredis.utils import (
    list_keys_to_dict,
    b, dict_merge,
    blocked_command,
    merge_result,
    first_key,
    clusterdown_wrapper,
)
import pytest
       3) 1) "10.0.0.1"
          2) (integer) 10000
          3) "3588b4cf9fc72d57bb262a024747797ead0cf7ea"
       4) 1) "10.0.0.4"
          2) (integer) 10000
          3) "a72c02c7d85f4ec3145ab2c411eefc0812aa96b0"
    2) 1) (integer) 10923
       2) (integer) 16383
       3) 1) "10.0.0.2"
          2) (integer) 10000
          3) "ffd36d8d7cb10d813f81f9662a835f6beea72677"
       4) 1) "10.0.0.5"
          2) (integer) 10000
          3) "5c15b69186017ddc25ebfac81e74694fc0c1a160"
    3) 1) (integer) 0
       2) (integer) 5460
       3) 1) "10.0.0.3"
          2) (integer) 10000
          3) "069cda388c7c41c62abe892d9e0a2d55fbf5ffd5"
       4) 1) "10.0.0.6"
          2) (integer) 10000
          3) "dc152a08b4cf1f2a0baf775fb86ad0938cb907dc"
    """

    extended_mock_response = [
        [0, 5460, ['172.17.0.2', 7000, 'ffd36d8d7cb10d813f81f9662a835f6beea72677'], ['172.17.0.2', 7003, '5c15b69186017ddc25ebfac81e74694fc0c1a160']],
        [5461, 10922, ['172.17.0.2', 7001, '069cda388c7c41c62abe892d9e0a2d55fbf5ffd5'], ['172.17.0.2', 7004, 'dc152a08b4cf1f2a0baf775fb86ad0938cb907dc']],
        [10923, 16383, ['172.17.0.2', 7002, '3588b4cf9fc72d57bb262a024747797ead0cf7ea'], ['172.17.0.2', 7005, 'a72c02c7d85f4ec3145ab2c411eefc0812aa96b0']]
    ]


# Path: aredis/commands/cluster.py
# def parse_cluster_slots(response):
#     res = dict()
#     for slot_info in response:
#         min_slot, max_slot = slot_info[:2]
#         nodes = slot_info[2:]
#         parse_node = lambda node: {
#             'host': node[0],
#             'port': node[1],
#             'node_id': node[2] if len(node) > 2 else '',
#             'server_type': 'slave'
#         }
#         res[(min_slot, max_slot)] = [parse_node(node) for node in nodes]
#         res[(min_slot, max_slot)][0]['server_type'] = 'master'
#     return res
# 
# Path: aredis/exceptions.py
# class RedisClusterException(Exception):
#     pass
# 
# class ClusterDownError(ClusterError, ResponseError):
# 
#     def __init__(self, resp):
#         self.args = (resp,)
#         self.message = resp
# 
# Path: aredis/utils.py
# def list_keys_to_dict(key_list, callback):
#     return dict.fromkeys(key_list, callback)
# 
# def b(x):
#     return x.encode('latin-1') if not isinstance(x, bytes) else x
# 
# def dict_merge(*dicts):
#     merged = {}
#     for d in dicts:
#         merged.update(d)
#     return merged
# 
# def blocked_command(self, command):
#     """
#     Raises a `RedisClusterException` mentioning the command is blocked.
#     """
#     raise RedisClusterException("Command: {0} is blocked in redis cluster mode".format(command))
# 
# def merge_result(res):
#     """
#     Merges all items in `res` into a list.
# 
#     This command is used when sending a command to multiple nodes
#     and they result from each node should be merged into a single list.
#     """
#     if not isinstance(res, dict):
#         raise ValueError('Value should be of dict type')
# 
#     result = set([])
# 
#     for _, v in res.items():
#         for value in v:
#             result.add(value)
# 
#     return list(result)
# 
# def first_key(res):
#     """
#     Returns the first result for the given command.
# 
#     If more then 1 result is returned then a `RedisClusterException` is raised.
#     """
#     if not isinstance(res, dict):
#         raise ValueError('Value should be of dict type')
# 
#     if len(res.keys()) != 1:
#         raise RedisClusterException("More then 1 result from command")
# 
#     return list(res.values())[0]
# 
# def clusterdown_wrapper(func):
#     """
#     Wrapper for CLUSTERDOWN error handling.
# 
#     If the cluster reports it is down it is assumed that:
#      - connection_pool was disconnected
#      - connection_pool was reseted
#      - refereh_table_asap set to True
# 
#     It will try 3 times to rerun the command and raises ClusterDownException if it continues to fail.
#     """
# 
#     @wraps(func)
#     async def inner(*args, **kwargs):
#         for _ in range(0, 3):
#             try:
#                 return await func(*args, **kwargs)
#             except ClusterDownError:
#                 # Try again with the new cluster setup. All other errors
#                 # should be raised.
#                 pass
# 
#         # If it fails 3 times then raise exception back to caller
#         raise ClusterDownError("CLUSTERDOWN error. Unable to rebuild the cluster")
# 
#     return inner


# Path: tests/cluster/test_utils.py
from aredis.commands.cluster import parse_cluster_slots
from aredis.exceptions import (
    RedisClusterException, ClusterDownError
)
from aredis.utils import (
    list_keys_to_dict,
    b, dict_merge,
    blocked_command,
    merge_result,
    first_key,
    clusterdown_wrapper,
)
import pytest

       3) 1) "10.0.0.1"
          2) (integer) 10000
          3) "3588b4cf9fc72d57bb262a024747797ead0cf7ea"
       4) 1) "10.0.0.4"
          2) (integer) 10000
          3) "a72c02c7d85f4ec3145ab2c411eefc0812aa96b0"
    2) 1) (integer) 10923
       2) (integer) 16383
       3) 1) "10.0.0.2"
          2) (integer) 10000
          3) "ffd36d8d7cb10d813f81f9662a835f6beea72677"
       4) 1) "10.0.0.5"
          2) (integer) 10000
          3) "5c15b69186017ddc25ebfac81e74694fc0c1a160"
    3) 1) (integer) 0
       2) (integer) 5460
       3) 1) "10.0.0.3"
          2) (integer) 10000
          3) "069cda388c7c41c62abe892d9e0a2d55fbf5ffd5"
       4) 1) "10.0.0.6"
          2) (integer) 10000
          3) "dc152a08b4cf1f2a0baf775fb86ad0938cb907dc"
    """

    extended_mock_response = [
        [0, 5460, ['172.17.0.2', 7000, 'ffd36d8d7cb10d813f81f9662a835f6beea72677'], ['172.17.0.2', 7003, '5c15b69186017ddc25ebfac81e74694fc0c1a160']],
        [5461, 10922, ['172.17.0.2', 7001, '069cda388c7c41c62abe892d9e0a2d55fbf5ffd5'], ['172.17.0.2', 7004, 'dc152a08b4cf1f2a0baf775fb86ad0938cb907dc']],
        [10923, 16383, ['172.17.0.2', 7002, '3588b4cf9fc72d57bb262a024747797ead0cf7ea'], ['172.17.0.2', 7005, 'a72c02c7d85f4ec3145ab2c411eefc0812aa96b0']]
    ]


    parse_cluster_slots(extended_mock_response)