Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for EXPIREAT command's options #2024

Merged
merged 8 commits into from
Mar 14, 2022
Merged
20 changes: 16 additions & 4 deletions redis/commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1501,16 +1501,28 @@ def expire(self, name: KeyT, time: ExpiryT) -> ResponseT:
time = int(time.total_seconds())
return self.execute_command("EXPIRE", name, time)

def expireat(self, name: KeyT, when: AbsExpiryT) -> ResponseT:
def expireat(self, name: KeyT, when: AbsExpiryT, option: str = None) -> ResponseT:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dogukanteber WDYT about making these options (NX, XX, etc) variables in the function header. IMHO it would watch our other functions.

"""
Set an expire flag on key ``name``. ``when`` can be represented
as an integer indicating unix time or a Python datetime object.
Set an expire flag on key ``name`` with the given ``option``. ``when``
can be represented as an integer indicating unix time or a Python
datetime 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/expireat
"""
if isinstance(when, datetime.datetime):
when = int(time.mktime(when.timetuple()))
return self.execute_command("EXPIREAT", name, when)

exp_option = list()
if option is not None:
exp_option.append(option)

return self.execute_command("EXPIREAT", name, when, *exp_option)

def get(self, name: KeyT) -> ResponseT:
"""
Expand Down
37 changes: 37 additions & 0 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,43 @@ def test_expireat_unixtime(self, r):
assert r.expireat("a", expire_at_seconds) is True
assert 0 < r.ttl("a") <= 61

@skip_if_server_version_lt("7.0.0")
def test_expireat_option_nx(self, r):
assert r.set("key", "val") is True
expire_at = redis_server_time(r) + datetime.timedelta(minutes=1)
assert r.expireat("key", expire_at, "NX") is True
expire_at = redis_server_time(r) + datetime.timedelta(minutes=2)
assert r.expireat("key", expire_at, "NX") is False

@skip_if_server_version_lt("7.0.0")
def test_expireat_option_xx(self, r):
assert r.set("key", "val") is True
expire_at = redis_server_time(r) + datetime.timedelta(minutes=1)
assert r.expireat("key", expire_at, "XX") is False
assert r.expireat("key", expire_at) is True
expire_at = redis_server_time(r) + datetime.timedelta(minutes=2)
assert r.expireat("key", expire_at, "XX") is True

@skip_if_server_version_lt("7.0.0")
def test_expireat_option_gt(self, r):
expire_at = redis_server_time(r) + datetime.timedelta(minutes=2)
assert r.set("key", "val") is True
assert r.expireat("key", expire_at) is True
expire_at = redis_server_time(r) + datetime.timedelta(minutes=1)
assert r.expireat("key", expire_at, "GT") is False
expire_at = redis_server_time(r) + datetime.timedelta(minutes=3)
assert r.expireat("key", expire_at, "GT") is True

@skip_if_server_version_lt("7.0.0")
def test_expireat_option_lt(self, r):
expire_at = redis_server_time(r) + datetime.timedelta(minutes=2)
assert r.set("key", "val") is True
assert r.expireat("key", expire_at) is True
expire_at = redis_server_time(r) + datetime.timedelta(minutes=3)
assert r.expireat("key", expire_at, "LT") is False
expire_at = redis_server_time(r) + datetime.timedelta(minutes=1)
assert r.expireat("key", expire_at, "LT") is True

def test_get_and_set(self, r):
# get and set can't be tested independently of each other
assert r.get("a") is None
Expand Down