# 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)

    async def parse_response(self, block=True, timeout=0):
        """Parses the response from a publish/subscribe command"""
        connection = self.connection
        if connection is None:
            raise RuntimeError(
                'pubsub connection not set: '
                'did you forget to call subscribe() or psubscribe()?')
        coro = self._execute(connection, connection.read_response)
        if not block and timeout > 0:
            try:
                return await asyncio.wait_for(coro, timeout)
            except Exception:
                return None
        return await coro

    async def psubscribe(self, *args, **kwargs):
        """
        Subscribes to channel patterns. Patterns supplied as keyword arguments
        expect a pattern name as the key and a callable as the value. A
        pattern's callable will be invoked automatically when a message is
        received on that pattern rather than producing a message via
        ``listen()``.
        """
        if args:
            args = list_or_args(args[0], args[1:])
        new_patterns = {}
        new_patterns.update(dict.fromkeys(map(self.encode, args)))
        for pattern, handler in iteritems(kwargs):
            new_patterns[self.encode(pattern)] = 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)


    async def parse_response(self, block=True, timeout=0):
        """Parses the response from a publish/subscribe command"""
        connection = self.connection
        if connection is None:
            raise RuntimeError(
                'pubsub connection not set: '
                'did you forget to call subscribe() or psubscribe()?')
        coro = self._execute(connection, connection.read_response)
        if not block and timeout > 0:
            try:
                return await asyncio.wait_for(coro, timeout)
            except Exception:
                return None
        return await coro

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

        ret_val = await self.execute_command('PSUBSCRIBE', *iterkeys(new_patterns))