From 1186252e9c8aa46d4b7a824b580a60b29764b4e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fukan=20Teber?= Date: Sat, 19 Feb 2022 15:45:14 +0300 Subject: [PATCH 1/4] Add support for EXPIRE command's options --- redis/commands/core.py | 18 ++++++++++++++---- tests/test_commands.py | 27 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/redis/commands/core.py b/redis/commands/core.py index 1e221c9402..628b0249d1 100644 --- a/redis/commands/core.py +++ b/redis/commands/core.py @@ -1246,16 +1246,26 @@ def exists(self, *names): __contains__ = exists - def expire(self, name, time): + def expire(self, name, time, option=None): """ - Set an expire flag on key ``name`` for ``time`` seconds. ``time`` - can be represented by an integer or a Python timedelta object. + Set an expire flag on key ``name`` for ``time`` seconds with the given + ``option``. ``time`` can be represented by an integer or a Python timedelta + object. + + Valid options are: + NX -> Set expiry only when the key has no expiry + XX -> Set expiry only when the key has an existing expiry + GT -> Set expiry only when the new expiry is greater than current one + LT -> Set expiry only when the new expiry is less than current one For more information check https://redis.io/commands/expire """ if isinstance(time, datetime.timedelta): time = int(time.total_seconds()) - return self.execute_command("EXPIRE", name, time) + + if option is None: + return self.execute_command("EXPIRE", name, time) + return self.execute_command("EXPIRE", name, time, option) def expireat(self, name, when): """ diff --git a/tests/test_commands.py b/tests/test_commands.py index ad9ee2c5fd..5581f920d7 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -1042,6 +1042,33 @@ def test_expire(self, r): assert r.persist("a") assert r.ttl("a") == -1 + @skip_if_server_version_lt("7.0.0") + def test_expire_option_nx(self, r): + r.set("key", "val") + assert r.expire("key", 100, "nx") == 1 + assert r.expire("key", 500, "nx") == 0 + + @skip_if_server_version_lt("7.0.0") + def test_expire_option_xx(self, r): + r.set("key", "val") + assert r.expire("key", 100, "xx") == 0 + assert r.expire("key", 100) + assert r.expire("key", 500, "xx") == 1 + + @skip_if_server_version_lt("7.0.0") + def test_expire_option_gt(self, r): + r.set("key", "val", 100) + assert r.expire("key", 50, "gt") == 0 + assert r.expire("key", 100, "gt") == 0 + assert r.expire("key", 500, "gt") == 1 + + @skip_if_server_version_lt("7.0.0") + def test_expire_option_lt(self, r): + r.set("key", "val", 100) + assert r.expire("key", 100, "lt") == 0 + assert r.expire("key", 50, "lt") == 1 + assert r.expire("key", 150, "lt") == 0 + def test_expireat_datetime(self, r): expire_at = redis_server_time(r) + datetime.timedelta(minutes=1) r["a"] = "foo" From 111d9171bcc7fad50322a35657914ed687b1f6ec Mon Sep 17 00:00:00 2001 From: dogukanteber Date: Tue, 22 Feb 2022 23:54:29 +0300 Subject: [PATCH 2/4] Add requested changes --- redis/commands/core.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/redis/commands/core.py b/redis/commands/core.py index 149d10c324..81e04f9c7b 100644 --- a/redis/commands/core.py +++ b/redis/commands/core.py @@ -1490,7 +1490,7 @@ def exists(self, *names: KeyT) -> ResponseT: __contains__ = exists - def expire(self, name, time, option=None): + def expire(self, name: KeyT, time: ExpiryT, option: str = None) -> ResponseT: """ Set an expire flag on key ``name`` for ``time`` seconds with the given ``option``. ``time`` can be represented by an integer or a Python timedelta @@ -1507,9 +1507,11 @@ def expire(self, name, time, option=None): if isinstance(time, datetime.timedelta): time = int(time.total_seconds()) - if option is None: - return self.execute_command("EXPIRE", name, time) - return self.execute_command("EXPIRE", name, time, option) + exp_option = list() + if option is not None: + exp_option.append(option) + + return self.execute_command("EXPIRE", name, time, *exp_option) def expireat(self, name: KeyT, when: AbsExpiryT) -> ResponseT: """ From 99995de5b3aad570d809f481410ec73b629f0e57 Mon Sep 17 00:00:00 2001 From: dogukanteber Date: Thu, 3 Mar 2022 13:20:37 +0300 Subject: [PATCH 3/4] Change method arguments --- redis/commands/core.py | 15 +++++++++++++-- tests/test_commands.py | 18 ++++++++---------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/redis/commands/core.py b/redis/commands/core.py index 81e04f9c7b..ffec1dba26 100644 --- a/redis/commands/core.py +++ b/redis/commands/core.py @@ -1490,9 +1490,16 @@ def exists(self, *names: KeyT) -> ResponseT: __contains__ = exists - def expire(self, name: KeyT, time: ExpiryT, option: str = None) -> ResponseT: + def expire( + self, + name: KeyT, + time: ExpiryT, + option: Union[ + Literal["NX"], Literal["XX"], Literal["GT"], Literal["LT"] + ] = None, + ) -> ResponseT: """ - Set an expire flag on key ``name`` for ``time`` seconds with the given + Set an expire flag on key ``name`` for ``time`` seconds with given ``option``. ``time`` can be represented by an integer or a Python timedelta object. @@ -1507,6 +1514,10 @@ def expire(self, name: KeyT, time: ExpiryT, option: str = None) -> ResponseT: if isinstance(time, datetime.timedelta): time = int(time.total_seconds()) + options = ["NX", "XX", "GT", "LT"] + if option and option not in options: + raise DataError(f"OPTION must be one of {options}") + exp_option = list() if option is not None: exp_option.append(option) diff --git a/tests/test_commands.py b/tests/test_commands.py index 6f03c6be5d..a69176b699 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -1045,29 +1045,27 @@ def test_expire(self, r): @skip_if_server_version_lt("7.0.0") def test_expire_option_nx(self, r): r.set("key", "val") - assert r.expire("key", 100, "nx") == 1 - assert r.expire("key", 500, "nx") == 0 + assert r.expire("key", 100, "NX") == 1 + assert r.expire("key", 500, "NX") == 0 @skip_if_server_version_lt("7.0.0") def test_expire_option_xx(self, r): r.set("key", "val") - assert r.expire("key", 100, "xx") == 0 + assert r.expire("key", 100, "XX") == 0 assert r.expire("key", 100) - assert r.expire("key", 500, "xx") == 1 + assert r.expire("key", 500, "XX") == 1 @skip_if_server_version_lt("7.0.0") def test_expire_option_gt(self, r): r.set("key", "val", 100) - assert r.expire("key", 50, "gt") == 0 - assert r.expire("key", 100, "gt") == 0 - assert r.expire("key", 500, "gt") == 1 + assert r.expire("key", 50, "GT") == 0 + assert r.expire("key", 500, "GT") == 1 @skip_if_server_version_lt("7.0.0") def test_expire_option_lt(self, r): r.set("key", "val", 100) - assert r.expire("key", 100, "lt") == 0 - assert r.expire("key", 50, "lt") == 1 - assert r.expire("key", 150, "lt") == 0 + assert r.expire("key", 50, "LT") == 1 + assert r.expire("key", 150, "LT") == 0 def test_expireat_datetime(self, r): expire_at = redis_server_time(r) + datetime.timedelta(minutes=1) From f5bcebd502629c0a988910e197a779ad66d1b0a4 Mon Sep 17 00:00:00 2001 From: dvora-h Date: Mon, 14 Mar 2022 12:14:17 +0200 Subject: [PATCH 4/4] add variables to the function header --- redis/commands/core.py | 21 ++++++++++++--------- tests/test_commands.py | 16 ++++++++-------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/redis/commands/core.py b/redis/commands/core.py index 6cf75d5c0a..a387c51860 100644 --- a/redis/commands/core.py +++ b/redis/commands/core.py @@ -1496,9 +1496,10 @@ def expire( self, name: KeyT, time: ExpiryT, - option: Union[ - Literal["NX"], Literal["XX"], Literal["GT"], Literal["LT"] - ] = None, + nx: bool = False, + xx: bool = False, + gt: bool = False, + lt: bool = False, ) -> ResponseT: """ Set an expire flag on key ``name`` for ``time`` seconds with given @@ -1516,13 +1517,15 @@ def expire( if isinstance(time, datetime.timedelta): time = int(time.total_seconds()) - options = ["NX", "XX", "GT", "LT"] - if option and option not in options: - raise DataError(f"OPTION must be one of {options}") - exp_option = list() - if option is not None: - exp_option.append(option) + if nx: + exp_option.append("NX") + if xx: + exp_option.append("XX") + if gt: + exp_option.append("GT") + if lt: + exp_option.append("LT") return self.execute_command("EXPIRE", name, time, *exp_option) diff --git a/tests/test_commands.py b/tests/test_commands.py index 5390a05e08..2e1291415a 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -1061,27 +1061,27 @@ def test_expire(self, r): @skip_if_server_version_lt("7.0.0") def test_expire_option_nx(self, r): r.set("key", "val") - assert r.expire("key", 100, "NX") == 1 - assert r.expire("key", 500, "NX") == 0 + assert r.expire("key", 100, nx=True) == 1 + assert r.expire("key", 500, nx=True) == 0 @skip_if_server_version_lt("7.0.0") def test_expire_option_xx(self, r): r.set("key", "val") - assert r.expire("key", 100, "XX") == 0 + assert r.expire("key", 100, xx=True) == 0 assert r.expire("key", 100) - assert r.expire("key", 500, "XX") == 1 + assert r.expire("key", 500, nx=True) == 1 @skip_if_server_version_lt("7.0.0") def test_expire_option_gt(self, r): r.set("key", "val", 100) - assert r.expire("key", 50, "GT") == 0 - assert r.expire("key", 500, "GT") == 1 + assert r.expire("key", 50, gt=True) == 0 + assert r.expire("key", 500, gt=True) == 1 @skip_if_server_version_lt("7.0.0") def test_expire_option_lt(self, r): r.set("key", "val", 100) - assert r.expire("key", 50, "LT") == 1 - assert r.expire("key", 150, "LT") == 0 + assert r.expire("key", 50, lt=True) == 1 + assert r.expire("key", 150, lt=True) == 0 def test_expireat_datetime(self, r): expire_at = redis_server_time(r) + datetime.timedelta(minutes=1)