Skip to content

Commit

Permalink
Add support for hashmaps
Browse files Browse the repository at this point in the history
  • Loading branch information
kysre committed Jan 27, 2024
1 parent d94a7f9 commit 09e53a1
Show file tree
Hide file tree
Showing 4 changed files with 135 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)

Check warning on line 190 in django_redis/cache.py

View check run for this annotation

Codecov / codecov/patch

django_redis/cache.py#L189-L190

Added lines #L189 - L190 were not covered by tests

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

Check warning on line 194 in django_redis/cache.py

View check run for this annotation

Codecov / codecov/patch

django_redis/cache.py#L193-L194

Added lines #L193 - L194 were not covered by tests

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

Check warning on line 198 in django_redis/cache.py

View check run for this annotation

Codecov / codecov/patch

django_redis/cache.py#L197-L198

Added lines #L197 - L198 were not covered by tests

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

Check warning on line 202 in django_redis/cache.py

View check run for this annotation

Codecov / codecov/patch

django_redis/cache.py#L201-L202

Added lines #L201 - L202 were not covered by tests

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

Check warning on line 206 in django_redis/cache.py

View check run for this annotation

Codecov / codecov/patch

django_redis/cache.py#L205-L206

Added lines #L205 - L206 were not covered by tests
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:
"""
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)]

Check warning on line 874 in django_redis/client/default.py

View check run for this annotation

Codecov / codecov/patch

django_redis/client/default.py#L874

Added line #L874 was not covered by tests
except _main_exceptions as e:
raise ConnectionInterrupted(connection=client) from e

Check warning on line 876 in django_redis/client/default.py

View check run for this annotation

Codecov / codecov/patch

django_redis/client/default.py#L876

Added line #L876 was not covered by tests

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))
38 changes: 38 additions & 0 deletions tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -797,3 +797,41 @@ 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):
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")

Check warning on line 806 in tests/test_backend.py

View check run for this annotation

Codecov / codecov/patch

tests/test_backend.py#L801-L806

Added lines #L801 - L806 were not covered by tests

def test_hdel(self, cache: RedisCache):
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")

Check warning on line 816 in tests/test_backend.py

View check run for this annotation

Codecov / codecov/patch

tests/test_backend.py#L808-L816

Added lines #L808 - L816 were not covered by tests

def test_hlen(self, cache: RedisCache):
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

Check warning on line 823 in tests/test_backend.py

View check run for this annotation

Codecov / codecov/patch

tests/test_backend.py#L818-L823

Added lines #L818 - L823 were not covered by tests

def test_hkeys(self, cache: RedisCache):
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}"

Check warning on line 832 in tests/test_backend.py

View check run for this annotation

Codecov / codecov/patch

tests/test_backend.py#L825-L832

Added lines #L825 - L832 were not covered by tests

def test_hexists(self, cache: RedisCache):
cache.hset("foo_hash5", "foo1", "bar1")
assert cache.hexists("foo_hash5", "foo1")
assert not cache.hexists("foo_hash5", "foo")

Check warning on line 837 in tests/test_backend.py

View check run for this annotation

Codecov / codecov/patch

tests/test_backend.py#L834-L837

Added lines #L834 - L837 were not covered by tests

0 comments on commit 09e53a1

Please sign in to comment.