Skip to content

Commit

Permalink
Merge branch 'master' of github.com:andy-stark-redis/redis-py
Browse files Browse the repository at this point in the history
  • Loading branch information
andy-stark-redis committed Jun 7, 2024
2 parents ac20f42 + 843c8d5 commit 1e903ed
Show file tree
Hide file tree
Showing 10 changed files with 1,087 additions and 8 deletions.
368 changes: 368 additions & 0 deletions redis/commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5094,6 +5094,374 @@ def hstrlen(self, name: str, key: str) -> Union[Awaitable[int], int]:
"""
return self.execute_command("HSTRLEN", name, key, keys=[name])

def hexpire(
self,
name: KeyT,
seconds: ExpiryT,
*fields: str,
nx: bool = False,
xx: bool = False,
gt: bool = False,
lt: bool = False,
) -> ResponseT:
"""
Sets or updates the expiration time for fields within a hash key, using relative
time in seconds.
If a field already has an expiration time, the behavior of the update can be
controlled using the `nx`, `xx`, `gt`, and `lt` parameters.
The return value provides detailed information about the outcome for each field.
For more information, see https://redis.io/commands/hexpire
Args:
name: The name of the hash key.
seconds: Expiration time in seconds, relative. Can be an integer, or a
Python `timedelta` object.
fields: List of fields within the hash to apply the expiration time to.
nx: Set expiry only when the field has no expiry.
xx: Set expiry only when the field has an existing expiry.
gt: Set expiry only when the new expiry is greater than the current one.
lt: Set expiry only when the new expiry is less than the current one.
Returns:
If the key does not exist, returns an empty list. If the key exists, returns
a list which contains for each field in the request:
- `-2` if the field does not exist.
- `0` if the specified NX | XX | GT | LT condition was not met.
- `1` if the expiration time was set or updated.
- `2` if the field was deleted because the specified expiration time is
in the past.
"""
conditions = [nx, xx, gt, lt]
if sum(conditions) > 1:
raise ValueError("Only one of 'nx', 'xx', 'gt', 'lt' can be specified.")

if isinstance(seconds, datetime.timedelta):
seconds = int(seconds.total_seconds())

options = []
if nx:
options.append("NX")
if xx:
options.append("XX")
if gt:
options.append("GT")
if lt:
options.append("LT")

return self.execute_command(
"HEXPIRE", name, seconds, *options, "FIELDS", len(fields), *fields
)

def hpexpire(
self,
name: KeyT,
milliseconds: ExpiryT,
*fields: str,
nx: bool = False,
xx: bool = False,
gt: bool = False,
lt: bool = False,
) -> ResponseT:
"""
Sets or updates the expiration time for fields within a hash key, using relative
time in milliseconds.
If a field already has an expiration time, the behavior of the update can be
controlled using the `nx`, `xx`, `gt`, and `lt` parameters.
The return value provides detailed information about the outcome for each field.
For more information, see https://redis.io/commands/hpexpire
Args:
name: The name of the hash key.
milliseconds: Expiration time in milliseconds, relative. Can be an integer,
or a Python `timedelta` object.
fields: List of fields within the hash to apply the expiration time to.
nx: Set expiry only when the field has no expiry.
xx: Set expiry only when the field has an existing expiry.
gt: Set expiry only when the new expiry is greater than the current one.
lt: Set expiry only when the new expiry is less than the current one.
Returns:
If the key does not exist, returns an empty list. If the key exists, returns
a list which contains for each field in the request:
- `-2` if the field does not exist.
- `0` if the specified NX | XX | GT | LT condition was not met.
- `1` if the expiration time was set or updated.
- `2` if the field was deleted because the specified expiration time is
in the past.
"""
conditions = [nx, xx, gt, lt]
if sum(conditions) > 1:
raise ValueError("Only one of 'nx', 'xx', 'gt', 'lt' can be specified.")

if isinstance(milliseconds, datetime.timedelta):
milliseconds = int(milliseconds.total_seconds() * 1000)

options = []
if nx:
options.append("NX")
if xx:
options.append("XX")
if gt:
options.append("GT")
if lt:
options.append("LT")

return self.execute_command(
"HPEXPIRE", name, milliseconds, *options, "FIELDS", len(fields), *fields
)

def hexpireat(
self,
name: KeyT,
unix_time_seconds: AbsExpiryT,
*fields: str,
nx: bool = False,
xx: bool = False,
gt: bool = False,
lt: bool = False,
) -> ResponseT:
"""
Sets or updates the expiration time for fields within a hash key, using an
absolute Unix timestamp in seconds.
If a field already has an expiration time, the behavior of the update can be
controlled using the `nx`, `xx`, `gt`, and `lt` parameters.
The return value provides detailed information about the outcome for each field.
For more information, see https://redis.io/commands/hexpireat
Args:
name: The name of the hash key.
unix_time_seconds: Expiration time as Unix timestamp in seconds. Can be an
integer or a Python `datetime` object.
fields: List of fields within the hash to apply the expiration time to.
nx: Set expiry only when the field has no expiry.
xx: Set expiry only when the field has an existing expiration time.
gt: Set expiry only when the new expiry is greater than the current one.
lt: Set expiry only when the new expiry is less than the current one.
Returns:
If the key does not exist, returns an empty list. If the key exists, returns
a list which contains for each field in the request:
- `-2` if the field does not exist.
- `0` if the specified NX | XX | GT | LT condition was not met.
- `1` if the expiration time was set or updated.
- `2` if the field was deleted because the specified expiration time is
in the past.
"""
conditions = [nx, xx, gt, lt]
if sum(conditions) > 1:
raise ValueError("Only one of 'nx', 'xx', 'gt', 'lt' can be specified.")

if isinstance(unix_time_seconds, datetime.datetime):
unix_time_seconds = int(unix_time_seconds.timestamp())

options = []
if nx:
options.append("NX")
if xx:
options.append("XX")
if gt:
options.append("GT")
if lt:
options.append("LT")

return self.execute_command(
"HEXPIREAT",
name,
unix_time_seconds,
*options,
"FIELDS",
len(fields),
*fields,
)

def hpexpireat(
self,
name: KeyT,
unix_time_milliseconds: AbsExpiryT,
*fields: str,
nx: bool = False,
xx: bool = False,
gt: bool = False,
lt: bool = False,
) -> ResponseT:
"""
Sets or updates the expiration time for fields within a hash key, using an
absolute Unix timestamp in milliseconds.
If a field already has an expiration time, the behavior of the update can be
controlled using the `nx`, `xx`, `gt`, and `lt` parameters.
The return value provides detailed information about the outcome for each field.
For more information, see https://redis.io/commands/hpexpireat
Args:
name: The name of the hash key.
unix_time_milliseconds: Expiration time as Unix timestamp in milliseconds.
Can be an integer or a Python `datetime` object.
fields: List of fields within the hash to apply the expiry.
nx: Set expiry only when the field has no expiry.
xx: Set expiry only when the field has an existing expiry.
gt: Set expiry only when the new expiry is greater than the current one.
lt: Set expiry only when the new expiry is less than the current one.
Returns:
If the key does not exist, returns an empty list. If the key exists, returns
a list which contains for each field in the request:
- `-2` if the field does not exist.
- `0` if the specified NX | XX | GT | LT condition was not met.
- `1` if the expiration time was set or updated.
- `2` if the field was deleted because the specified expiration time is
in the past.
"""
conditions = [nx, xx, gt, lt]
if sum(conditions) > 1:
raise ValueError("Only one of 'nx', 'xx', 'gt', 'lt' can be specified.")

if isinstance(unix_time_milliseconds, datetime.datetime):
unix_time_milliseconds = int(unix_time_milliseconds.timestamp() * 1000)

options = []
if nx:
options.append("NX")
if xx:
options.append("XX")
if gt:
options.append("GT")
if lt:
options.append("LT")

return self.execute_command(
"HPEXPIREAT",
name,
unix_time_milliseconds,
*options,
"FIELDS",
len(fields),
*fields,
)

def hpersist(self, name: KeyT, *fields: str) -> ResponseT:
"""
Removes the expiration time for each specified field in a hash.
For more information, see https://redis.io/commands/hpersist
Args:
name: The name of the hash key.
fields: A list of fields within the hash from which to remove the
expiration time.
Returns:
If the key does not exist, returns an empty list. If the key exists, returns
a list which contains for each field in the request:
- `-2` if the field does not exist.
- `-1` if the field exists but has no associated expiration time.
- `1` if the expiration time was successfully removed from the field.
"""
return self.execute_command("HPERSIST", name, "FIELDS", len(fields), *fields)

def hexpiretime(self, key: KeyT, *fields: str) -> ResponseT:
"""
Returns the expiration times of hash fields as Unix timestamps in seconds.
For more information, see https://redis.io/commands/hexpiretime
Args:
key: The hash key.
fields: A list of fields within the hash for which to get the expiration
time.
Returns:
If the key does not exist, returns an empty list. If the key exists, returns
a list which contains for each field in the request:
- `-2` if the field does not exist.
- `-1` if the field exists but has no associated expire time.
- A positive integer representing the expiration Unix timestamp in
seconds, if the field has an associated expiration time.
"""
return self.execute_command(
"HEXPIRETIME", key, "FIELDS", len(fields), *fields, keys=[key]
)

def hpexpiretime(self, key: KeyT, *fields: str) -> ResponseT:
"""
Returns the expiration times of hash fields as Unix timestamps in milliseconds.
For more information, see https://redis.io/commands/hpexpiretime
Args:
key: The hash key.
fields: A list of fields within the hash for which to get the expiration
time.
Returns:
If the key does not exist, returns an empty list. If the key exists, returns
a list which contains for each field in the request:
- `-2` if the field does not exist.
- `-1` if the field exists but has no associated expire time.
- A positive integer representing the expiration Unix timestamp in
milliseconds, if the field has an associated expiration time.
"""
return self.execute_command(
"HPEXPIRETIME", key, "FIELDS", len(fields), *fields, keys=[key]
)

def httl(self, key: KeyT, *fields: str) -> ResponseT:
"""
Returns the TTL (Time To Live) in seconds for each specified field within a hash
key.
For more information, see https://redis.io/commands/httl
Args:
key: The hash key.
fields: A list of fields within the hash for which to get the TTL.
Returns:
If the key does not exist, returns an empty list. If the key exists, returns
a list which contains for each field in the request:
- `-2` if the field does not exist.
- `-1` if the field exists but has no associated expire time.
- A positive integer representing the TTL in seconds if the field has
an associated expiration time.
"""
return self.execute_command(
"HTTL", key, "FIELDS", len(fields), *fields, keys=[key]
)

def hpttl(self, key: KeyT, *fields: str) -> ResponseT:
"""
Returns the TTL (Time To Live) in milliseconds for each specified field within a
hash key.
For more information, see https://redis.io/commands/hpttl
Args:
key: The hash key.
fields: A list of fields within the hash for which to get the TTL.
Returns:
If the key does not exist, returns an empty list. If the key exists, returns
a list which contains for each field in the request:
- `-2` if the field does not exist.
- `-1` if the field exists but has no associated expire time.
- A positive integer representing the TTL in milliseconds if the field
has an associated expiration time.
"""
return self.execute_command(
"HPTTL", key, "FIELDS", len(fields), *fields, keys=[key]
)


AsyncHashCommands = HashCommands

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
long_description_content_type="text/markdown",
keywords=["Redis", "key-value store", "database"],
license="MIT",
version="5.1.0b5",
version="5.1.0b6",
packages=find_packages(
include=[
"redis",
Expand Down
2 changes: 1 addition & 1 deletion tests/test_asyncio/test_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,7 @@ async def test_memory_stats(self, r: RedisCluster) -> None:
assert isinstance(stats, dict)
for key, value in stats.items():
if key.startswith("db."):
assert isinstance(value, dict)
assert not isinstance(value, list)

@skip_if_server_version_lt("4.0.0")
async def test_memory_help(self, r: RedisCluster) -> None:
Expand Down
Loading

0 comments on commit 1e903ed

Please sign in to comment.