from django.conf import settings
from django.core.cache import parse_backend_uri

try:
    import redis as redislib
except:
    redislib = None

connections = {}

if not connections:  # don't set this repeatedly
    for alias, backend in settings.REDIS_BACKENDS.items():
        _, server, params = parse_backend_uri(backend)

        try:
            socket_timeout = float(params.pop('socket_timeout'))
        except (KeyError, ValueError):
            socket_timeout = None
        password = params.pop('password', None)
        if ':' in server:
            host, port = server.split(':')
            try:
                port = int(port)
            except (ValueError, TypeError):
                port = 6379
        else:
            host = 'localhost'
            port = 6379

        connections[alias] = redislib.Redis(host=host, port=port, db=0,
                                            password=password,
                                            socket_timeout=socket_timeout)


def mock_redis():
    ret = dict(connections)
    for key in connections:
        connections[key] = MockRedis()
    return ret


def reset_redis(cxn):
    for key, value in cxn.items():
        connections[key] = value


class MockRedis(object):
    """A fake redis we can use for testing."""

    def __init__(self):
        self.kv = {}

    def pipeline(self, **kw):
        return self

    def execute(self):
        pass

    def get(self, key):
        return self.kv.get(key)

    def set(self, key, val):
        self.kv[key] = val

    def setnx(self, key, val):
        if key not in self.kv:
            self.set(key, val)
            return True
        return False

    def delete(self, key):
        if key in self.kv:
            del self.kv[key]
            return True
        return False

    def sadd(self, key, val):
        v = self.kv.setdefault(key, set())
        if isinstance(v, set):
            v.add(val)
            return True
        return False

    def smembers(self, key):
        v = self.kv.get(key, set())
        if isinstance(v, set):
            return v

    def hmget(self, name, keys):
        db = self.kv.get(name, {})
        return [db.get(key) for key in keys]

    def hmset(self, name, dict_):
        db = self.kv.setdefault(name, {})
        db.update(dict_)

    def hgetall(self, name):
        return self.kv.get(name, {})

    def hset(self, name, key, value):
        self.hmset(name, {key: value})

    def hget(self, name, key):
        return self.kv.get(name, {}).get(key)

    def hdel(self, name, key):
        db = self.kv.get(name, {})
        if key in db:
            del db[key]

    def hlen(self, name):
        return len(self.kv.get(name, {}))

@@ -1214,16 +1214,449 @@
 value%0A%0A%0A
+class StringDict(dict):%0A    %22%22%22A dict that converts all keys to strings automatically (like redis).%22%22%22%0A%0A    def __setitem__(self, key, value):%0A        if not isinstance(key, basestring):%0A            key = unicode(key)%0A        super(StringDict, self).__setitem__(key, value)%0A%0A    def __getitem__(self, key):%0A        if not isinstance(key, basestring):%0A            key = unicode(key)%0A        super(StringDict, self).__getitem__(key)%0A%0A%0A
 class Mo
@@ -1762,18 +1762,28 @@
 lf.kv = 
-%7B%7D
+StringDict()
 %0A%0A    de
@@ -2593,34 +2593,44 @@
 lf.kv.get(name, 
-%7B%7D
+StringDict()
 )%0A        return
@@ -2725,34 +2725,44 @@
 etdefault(name, 
-%7B%7D
+StringDict()
 )%0A        db.upd
@@ -2835,18 +2835,28 @@
 t(name, 
-%7B%7D
+StringDict()
 )%0A%0A    d
@@ -2900,38 +2900,75 @@
     
-self.hmset(name, %7Bkey:
+db = self.kv.setdefault(name, StringDict())%0A        db%5Bkey%5D =
  value
-%7D)
 %0A%0A  
@@ -3029,18 +3029,28 @@
 t(name, 
-%7B%7D
+StringDict()
 ).get(ke
@@ -3115,18 +3115,28 @@
 t(name, 
-%7B%7D
+StringDict()
 )%0A      
@@ -3239,13 +3239,23 @@
 t(name, 
-%7B%7D
+StringDict()
 ))%0A

make sure that keys are strings