# Path: aredis/compat.py

# 
# Path: aredis/exceptions.py
# class PubSubError(RedisError):
#     pass
# 
# class ConnectionError(RedisError):
#     pass
# 
# class TimeoutError(RedisError):
#     pass
# 
# Path: aredis/utils.py
# def list_or_args(keys, args):
#     # returns a single list combining keys and args
#     try:
#         iter(keys)
#         # a string or bytes instance can be iterated, but indicates
#         # keys wasn't passed as a list
#         if isinstance(keys, (str, bytes)):
#             keys = [keys]
#     except TypeError:
#         keys = [keys]
#     if args:
#         keys.extend(args)
#     return keys
# 
# def iteritems(x):
#     return iter(x.items())
# 
# def iterkeys(x):
#     return iter(x.keys())
# 
# def nativestr(x):
#     return x if isinstance(x, str) else x.decode('utf-8', 'replace')


import asyncio
import threading
from aredis.compat import CancelledError
from aredis.exceptions import PubSubError, ConnectionError, TimeoutError
from aredis.utils import (list_or_args,
                          iteritems,
                          iterkeys,
                          nativestr)
        ret_val = await self.execute_command('PSUBSCRIBE', *iterkeys(new_patterns))
        # update the patterns dict AFTER we send the command. we don't want to
        # subscribe twice to these patterns, once for the command and again
        # for the reconnection.
        self.patterns.update(new_patterns)
        return ret_val

    async def punsubscribe(self, *args):
        """
        Unsubscribes from the supplied patterns. If empy, unsubscribe from
        all patterns.
        """
        if args:
            args = list_or_args(args[0], args[1:])
        return await self.execute_command('PUNSUBSCRIBE', *args)

    async def subscribe(self, *args, **kwargs):
        """
        Subscribes to channels. Channels supplied as keyword arguments expect
        a channel name as the key and a callable as the value. A channel's
        callable will be invoked automatically when a message is received on
        that channel rather than producing a message via ``listen()`` or
        ``get_message()``.
        """
        if args:
            args = list_or_args(args[0], args[1:])
        new_channels = {}
        new_channels.update(dict.fromkeys(map(self.encode, args)))
        for channel, handler in iteritems(kwargs):
            new_channels[self.encode(channel)] = handler

# Path: aredis/compat.py

# 
# Path: aredis/exceptions.py
# class PubSubError(RedisError):
#     pass
# 
# class ConnectionError(RedisError):
#     pass
# 
# class TimeoutError(RedisError):
#     pass
# 
# Path: aredis/utils.py
# def list_or_args(keys, args):
#     # returns a single list combining keys and args
#     try:
#         iter(keys)
#         # a string or bytes instance can be iterated, but indicates
#         # keys wasn't passed as a list
#         if isinstance(keys, (str, bytes)):
#             keys = [keys]
#     except TypeError:
#         keys = [keys]
#     if args:
#         keys.extend(args)
#     return keys
# 
# def iteritems(x):
#     return iter(x.items())
# 
# def iterkeys(x):
#     return iter(x.keys())
# 
# def nativestr(x):
#     return x if isinstance(x, str) else x.decode('utf-8', 'replace')


# Path: aredis/pubsub.py
import asyncio
import threading
from aredis.compat import CancelledError
from aredis.exceptions import PubSubError, ConnectionError, TimeoutError
from aredis.utils import (list_or_args,
                          iteritems,
                          iterkeys,
                          nativestr)

        ret_val = await self.execute_command('PSUBSCRIBE', *iterkeys(new_patterns))
        # update the patterns dict AFTER we send the command. we don't want to
        # subscribe twice to these patterns, once for the command and again
        # for the reconnection.
        self.patterns.update(new_patterns)
        return ret_val

    async def punsubscribe(self, *args):
        """
        Unsubscribes from the supplied patterns. If empy, unsubscribe from
        all patterns.
        """
        if args:
            args = list_or_args(args[0], args[1:])
        return await self.execute_command('PUNSUBSCRIBE', *args)

    async def subscribe(self, *args, **kwargs):
        """
        Subscribes to channels. Channels supplied as keyword arguments expect
        a channel name as the key and a callable as the value. A channel's
        callable will be invoked automatically when a message is received on
        that channel rather than producing a message via ``listen()`` or
        ``get_message()``.
        """
        if args:
            args = list_or_args(args[0], args[1:])
        new_channels = {}
        new_channels.update(dict.fromkeys(map(self.encode, args)))
        for channel, handler in iteritems(kwargs):
            new_channels[self.encode(channel)] = handler

        ret_val = await self.execute_command('SUBSCRIBE', *iterkeys(new_channels))