diff --git a/changelog.d/730.feature b/changelog.d/730.feature index d41ae639..8a7addfa 100644 --- a/changelog.d/730.feature +++ b/changelog.d/730.feature @@ -1 +1 @@ -Support for sets and support basic operations, sadd, scard, sdiff, sdiffstore, sinter, sinterstore, smismember, sismember, smembers, smove, spop, srandmember, srem, sscan, sscan_iter, sunion, sunionstore \ No newline at end of file +Support for sets and support basic operations, sadd, scard, sdiff, sdiffstore, sinter, sinterstore, smismember, sismember, smembers, smove, spop, srandmember, srem, sscan, sscan_iter, sunion, sunionstore diff --git a/changelog.d/731.feature b/changelog.d/731.feature new file mode 100644 index 00000000..b4ddcf9c --- /dev/null +++ b/changelog.d/731.feature @@ -0,0 +1 @@ +Add option flags nx, xx, gt, lt for expire and pexpire \ No newline at end of file diff --git a/django_redis/client/default.py b/django_redis/client/default.py index 3219f7c9..7301be7a 100644 --- a/django_redis/client/default.py +++ b/django_redis/client/default.py @@ -317,6 +317,10 @@ def expire( timeout: ExpiryT, version: Optional[int] = None, client: Optional[Redis] = None, + nx: bool = False, + xx: bool = False, + gt: bool = False, + lt: bool = False, ) -> bool: if timeout is DEFAULT_TIMEOUT: timeout = self._backend.default_timeout # type: ignore @@ -328,7 +332,7 @@ def expire( # for some strange reason mypy complains, # saying that timeout type is float | timedelta - return client.expire(key, timeout) # type: ignore + return client.expire(key, timeout, nx, xx, gt, lt) # type: ignore def pexpire( self, @@ -336,6 +340,10 @@ def pexpire( timeout: ExpiryT, version: Optional[int] = None, client: Optional[Redis] = None, + nx: bool = False, + xx: bool = False, + gt: bool = False, + lt: bool = False, ) -> bool: if timeout is DEFAULT_TIMEOUT: timeout = self._backend.default_timeout # type: ignore @@ -349,7 +357,7 @@ def pexpire( # is fixed. # for some strange reason mypy complains, # saying that timeout type is float | timedelta - return bool(client.pexpire(key, timeout)) # type: ignore + return bool(client.pexpire(key, timeout, nx, xx, gt, lt)) # type: ignore def pexpire_at( self, diff --git a/django_redis/client/sharded.py b/django_redis/client/sharded.py index 5e2eec90..a8858ad6 100644 --- a/django_redis/client/sharded.py +++ b/django_redis/client/sharded.py @@ -171,19 +171,57 @@ def persist(self, key, version=None, client=None): return super().persist(key=key, version=version, client=client) - def expire(self, key, timeout, version=None, client=None): + def expire( + self, + key, + timeout, + version=None, + client=None, + nx=False, + xx=False, + gt=False, + lt=False, + ): if client is None: key = self.make_key(key, version=version) client = self.get_server(key) - return super().expire(key=key, timeout=timeout, version=version, client=client) + return super().expire( + key=key, + timeout=timeout, + version=version, + client=client, + nx=nx, + xx=xx, + gt=gt, + lt=lt, + ) - def pexpire(self, key, timeout, version=None, client=None): + def pexpire( + self, + key, + timeout, + version=None, + client=None, + nx=False, + xx=False, + gt=False, + lt=False, + ): if client is None: key = self.make_key(key, version=version) client = self.get_server(key) - return super().pexpire(key=key, timeout=timeout, version=version, client=client) + return super().pexpire( + key=key, + timeout=timeout, + version=version, + client=client, + nx=nx, + xx=xx, + gt=gt, + lt=lt, + ) def pexpire_at(self, key, when: Union[datetime, int], version=None, client=None): """ diff --git a/tests/test_backend.py b/tests/test_backend.py index 8619931e..fa1cb9c4 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -606,6 +606,12 @@ def test_expire(self, cache: RedisCache): ttl = cache.ttl("foo") assert pytest.approx(ttl) == 20 assert cache.expire("not-existent-key", 20) is False + cache.set("key1", "value1", timeout=None) + assert cache.expire("key1", 20, nx=True) is True + cache.set("key2", "value2", timeout=20) + assert cache.expire("key2", 21, xx=True) is True + assert cache.expire("key2", 30, gt=True) is True + assert cache.expire("key2", 20, lt=True) is True def test_expire_with_default_timeout(self, cache: RedisCache): cache.set("foo", "bar", timeout=None) @@ -619,6 +625,12 @@ def test_pexpire(self, cache: RedisCache): # delta is set to 10 as precision error causes tests to fail assert pytest.approx(ttl, 10) == 20500 assert cache.pexpire("not-existent-key", 20500) is False + cache.set("key1", "value1", timeout=None) + assert cache.pexpire("key1", 20000, nx=True) is True + cache.set("key2", "value2", timeout=20000) + assert cache.expire("key2", 20500, xx=True) is True + assert cache.expire("key2", 30000, gt=True) is True + assert cache.expire("key2", 20000, lt=True) is True def test_pexpire_with_default_timeout(self, cache: RedisCache): cache.set("foo", "bar", timeout=None)