Skip to content

Commit

Permalink
Merge pull request #719 from kysre/598-add-support-for-hashmaps
Browse files Browse the repository at this point in the history
Add support for hashmaps
  • Loading branch information
WisdomPill authored Jan 29, 2024
2 parents 4c4af16 + d2ce2fa commit 81ec264
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog.d/598.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support HashMaps
20 changes: 20 additions & 0 deletions django_redis/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,23 @@ def close(self, **kwargs):
@omit_exception
def touch(self, *args, **kwargs):
return self.client.touch(*args, **kwargs)

@omit_exception
def hset(self, *args, **kwargs):
return self.client.hset(*args, **kwargs)

@omit_exception
def hdel(self, *args, **kwargs):
return self.client.hdel(*args, **kwargs)

@omit_exception
def hlen(self, *args, **kwargs):
return self.client.hlen(*args, **kwargs)

@omit_exception
def hkeys(self, *args, **kwargs):
return self.client.hkeys(*args, **kwargs)

@omit_exception
def hexists(self, *args, **kwargs):
return self.client.hexists(*args, **kwargs)
76 changes: 76 additions & 0 deletions django_redis/client/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -813,3 +813,79 @@ def touch(
# Convert to milliseconds
timeout = int(timeout * 1000)
return bool(client.pexpire(key, timeout))

def hset(
self,
name: str,
key: KeyT,
value: EncodableT,
version: Optional[int] = None,
client: Optional[Redis] = None,
) -> int:
"""
Set the value of hash name at key to value.
Returns the number of fields added to the hash.
"""
if client is None:
client = self.get_client(write=True)
nkey = self.make_key(key, version=version)
nvalue = self.encode(value)
return int(client.hset(name, nkey, nvalue))

def hdel(
self,
name: str,
key: KeyT,
version: Optional[int] = None,
client: Optional[Redis] = None,
) -> int:
"""
Remove keys from hash name.
Returns the number of fields deleted from the hash.
"""
if client is None:
client = self.get_client(write=True)
nkey = self.make_key(key, version=version)
return int(client.hdel(name, nkey))

def hlen(
self,
name: str,
client: Optional[Redis] = None,
) -> int:
"""
Return the number of items in hash name.
"""
if client is None:
client = self.get_client(write=False)
return int(client.hlen(name))

def hkeys(
self,
name: str,
client: Optional[Redis] = None,
) -> List[Any]:
"""
Return a list of keys in hash name.
"""
if client is None:
client = self.get_client(write=False)
try:
return [self.reverse_key(k.decode()) for k in client.hkeys(name)]
except _main_exceptions as e:
raise ConnectionInterrupted(connection=client) from e

def hexists(
self,
name: str,
key: KeyT,
version: Optional[int] = None,
client: Optional[Redis] = None,
) -> bool:
"""
Return True if key exists in hash name, else False.
"""
if client is None:
client = self.get_client(write=False)
nkey = self.make_key(key, version=version)
return bool(client.hexists(name, nkey))
48 changes: 48 additions & 0 deletions tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -797,3 +797,51 @@ def test_clear(self, cache: RedisCache):
cache.clear()
value_from_cache_after_clear = cache.get("foo")
assert value_from_cache_after_clear is None

def test_hset(self, cache: RedisCache):
if isinstance(cache.client, ShardClient):
pytest.skip("ShardClient doesn't support get_client")
cache.hset("foo_hash1", "foo1", "bar1")
cache.hset("foo_hash1", "foo2", "bar2")
assert cache.hlen("foo_hash1") == 2
assert cache.hexists("foo_hash1", "foo1")
assert cache.hexists("foo_hash1", "foo2")

def test_hdel(self, cache: RedisCache):
if isinstance(cache.client, ShardClient):
pytest.skip("ShardClient doesn't support get_client")
cache.hset("foo_hash2", "foo1", "bar1")
cache.hset("foo_hash2", "foo2", "bar2")
assert cache.hlen("foo_hash2") == 2
deleted_count = cache.hdel("foo_hash2", "foo1")
assert deleted_count == 1
assert cache.hlen("foo_hash2") == 1
assert not cache.hexists("foo_hash2", "foo1")
assert cache.hexists("foo_hash2", "foo2")

def test_hlen(self, cache: RedisCache):
if isinstance(cache.client, ShardClient):
pytest.skip("ShardClient doesn't support get_client")
assert cache.hlen("foo_hash3") == 0
cache.hset("foo_hash3", "foo1", "bar1")
assert cache.hlen("foo_hash3") == 1
cache.hset("foo_hash3", "foo2", "bar2")
assert cache.hlen("foo_hash3") == 2

def test_hkeys(self, cache: RedisCache):
if isinstance(cache.client, ShardClient):
pytest.skip("ShardClient doesn't support get_client")
cache.hset("foo_hash4", "foo1", "bar1")
cache.hset("foo_hash4", "foo2", "bar2")
cache.hset("foo_hash4", "foo3", "bar3")
keys = cache.hkeys("foo_hash4")
assert len(keys) == 3
for i in range(len(keys)):
assert keys[i] == f"foo{i + 1}"

def test_hexists(self, cache: RedisCache):
if isinstance(cache.client, ShardClient):
pytest.skip("ShardClient doesn't support get_client")
cache.hset("foo_hash5", "foo1", "bar1")
assert cache.hexists("foo_hash5", "foo1")
assert not cache.hexists("foo_hash5", "foo")

0 comments on commit 81ec264

Please sign in to comment.