from redis.client import Lock

from fakeredis import (
    FakeRedis as BaseFakeRedis,
    FakeStrictRedis as BaseFakeStrictRedis,
)


class FakeRedisLock(Lock):
    """Simplify lock release for fakeredis"""

    def do_release(self, expected_token):
        """Simple delete the key

        For the parameters, see ``Lock.do_release``

        Notes
        -----
        We do that because fakeredis has a bug in its redis transaction management:
        It watch keys but raise if a key is updated by the current transaction, not
        only from "outside"... so it cannot work as expected by the original ``do_release``

        """
        self.redis.delete(self.name)


class FakeRedis(BaseFakeRedis):

    def lock(self, name, timeout=None, sleep=0.1):
        """
        ## COPIED FROM redis.py ``Redis`` client
        Return a new Lock object using key ``name`` that mimics
        the behavior of threading.Lock.

        If specified, ``timeout`` indicates a maximum life for the lock.
        By default, it will remain locked until release() is called.

        ``sleep`` indicates the amount of time to sleep per loop iteration
        when the lock is in blocking mode and another client is currently
        holding the lock.
        """
        return FakeRedisLock(self, name, timeout=timeout, sleep=sleep)


class FakeStrictRedis(BaseFakeStrictRedis):

    def lock(self, name, timeout=None, sleep=0.1):
        """
        ## COPIED FROM redis.py ``Redis`` client
        Return a new Lock object using key ``name`` that mimics
        the behavior of threading.Lock.

        If specified, ``timeout`` indicates a maximum life for the lock.
        By default, it will remain locked until release() is called.

        ``sleep`` indicates the amount of time to sleep per loop iteration
        when the lock is in blocking mode and another client is currently
        holding the lock.
        """
        return FakeRedisLock(self, name, timeout=timeout, sleep=sleep)
