Skip to content

Commit 0dadbb0

Browse files
committed
Issue #598 extend support for the hashmap functions
1 parent e11150a commit 0dadbb0

File tree

5 files changed

+290
-20
lines changed

5 files changed

+290
-20
lines changed

changelog.d/731.feature

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support for the hashmaps functions hsetnx, hget, hgetall, hmget hincrby

django_redis/cache.py

+20
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,22 @@ def sunionstore(self, *args, **kwargs):
257257
def hset(self, *args, **kwargs):
258258
return self.client.hset(*args, **kwargs)
259259

260+
@omit_exception
261+
def hsetnx(self, *args, **kwargs):
262+
return self.client.hsetnx(*args, **kwargs)
263+
264+
@omit_exception
265+
def hget(self, *args, **kwargs):
266+
return self.client.hget(*args, **kwargs)
267+
268+
@omit_exception
269+
def hgetall(self, *args, **kwargs):
270+
return self.client.hgetall(*args, **kwargs)
271+
272+
@omit_exception
273+
def hmget(self, *args, **kwargs):
274+
return self.client.hmget(*args, **kwargs)
275+
260276
@omit_exception
261277
def hdel(self, *args, **kwargs):
262278
return self.client.hdel(*args, **kwargs)
@@ -272,3 +288,7 @@ def hkeys(self, *args, **kwargs):
272288
@omit_exception
273289
def hexists(self, *args, **kwargs):
274290
return self.client.hexists(*args, **kwargs)
291+
292+
@omit_exception
293+
def hincrby(self, *args, **kwargs):
294+
return self.client.hincrby(*args, **kwargs)

django_redis/client/default.py

+99-10
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ def _incr(
621621
# if cached value or total value is greater than 64 bit signed
622622
# integer.
623623
# elif int is encoded. so redis sees the data as string.
624-
# In this situations redis will throw ResponseError
624+
# In these situations redis will throw ResponseError
625625

626626
# try to keep TTL of key
627627
timeout = self.ttl(key, version=version, client=client)
@@ -1103,7 +1103,7 @@ def touch(
11031103

11041104
def hset(
11051105
self,
1106-
name: str,
1106+
name: KeyT,
11071107
key: KeyT,
11081108
value: EncodableT,
11091109
version: Optional[int] = None,
@@ -1115,13 +1115,76 @@ def hset(
11151115
"""
11161116
if client is None:
11171117
client = self.get_client(write=True)
1118+
key_name = self.make_key(name, version=version)
11181119
nkey = self.make_key(key, version=version)
11191120
nvalue = self.encode(value)
1120-
return int(client.hset(name, nkey, nvalue))
1121+
return int(client.hset(key_name, nkey, nvalue))
1122+
1123+
def hsetnx(
1124+
self,
1125+
name: KeyT,
1126+
key: KeyT,
1127+
value: EncodableT,
1128+
version: Optional[int] = None,
1129+
client: Optional[Redis] = None,
1130+
) -> int:
1131+
if client is None:
1132+
client = self.get_client(write=True)
1133+
nkey = self.make_key(key, version=version)
1134+
key_name = self.make_key(name, version=version)
1135+
nvalue = self.encode(value)
1136+
return int(client.hsetnx(key_name, nkey, nvalue))
1137+
1138+
def hget(
1139+
self,
1140+
name: KeyT,
1141+
key: KeyT,
1142+
version: Optional[int] = None,
1143+
client: Optional[Redis] = None,
1144+
) -> Any:
1145+
"""
1146+
Return the value of hash name at key.
1147+
"""
1148+
if client is None:
1149+
client = self.get_client(write=False)
1150+
name = self.make_key(name, version=version)
1151+
nkey = self.make_key(key, version=version)
1152+
value = client.hget(name, nkey)
1153+
if value is None:
1154+
return None
1155+
return self.decode(value)
1156+
1157+
def hgetall(
1158+
self,
1159+
name: KeyT,
1160+
version: Optional[int] = None,
1161+
client: Optional[Redis] = None,
1162+
) -> Dict[str, Any]:
1163+
1164+
if client is None:
1165+
client = self.get_client(write=False)
1166+
name = self.make_key(name, version=version)
1167+
data = client.hgetall(name)
1168+
return {self.reverse_key(k.decode()): self.decode(v) for k, v in data.items()}
1169+
1170+
def hmget(
1171+
self,
1172+
name: KeyT,
1173+
*keys: KeyT,
1174+
version: Optional[int] = None,
1175+
client: Optional[Redis] = None,
1176+
) -> List[Any]:
1177+
if client is None:
1178+
client = self.get_client(write=False)
1179+
name = self.make_key(name, version=version)
1180+
nkeys = [self.make_key(k, version=version) for k in keys]
1181+
return [
1182+
self.decode(v) if v is not None else None for v in client.hmget(name, nkeys)
1183+
]
11211184

11221185
def hdel(
11231186
self,
1124-
name: str,
1187+
name: KeyT,
11251188
key: KeyT,
11261189
version: Optional[int] = None,
11271190
client: Optional[Redis] = None,
@@ -1132,39 +1195,44 @@ def hdel(
11321195
"""
11331196
if client is None:
11341197
client = self.get_client(write=True)
1198+
name = self.make_key(name, version=version)
11351199
nkey = self.make_key(key, version=version)
11361200
return int(client.hdel(name, nkey))
11371201

11381202
def hlen(
11391203
self,
1140-
name: str,
1204+
name: KeyT,
1205+
version: Optional[int] = None,
11411206
client: Optional[Redis] = None,
11421207
) -> int:
11431208
"""
11441209
Return the number of items in hash name.
11451210
"""
11461211
if client is None:
11471212
client = self.get_client(write=False)
1148-
return int(client.hlen(name))
1213+
key_name = self.make_key(name, version=version)
1214+
return int(client.hlen(key_name))
11491215

11501216
def hkeys(
11511217
self,
1152-
name: str,
1218+
name: KeyT,
1219+
version: Optional[int] = None,
11531220
client: Optional[Redis] = None,
11541221
) -> List[Any]:
11551222
"""
11561223
Return a list of keys in hash name.
11571224
"""
1225+
key_name = self.make_key(name, version=version)
11581226
if client is None:
11591227
client = self.get_client(write=False)
11601228
try:
1161-
return [self.reverse_key(k.decode()) for k in client.hkeys(name)]
1229+
return [self.reverse_key(k.decode()) for k in client.hkeys(key_name)]
11621230
except _main_exceptions as e:
11631231
raise ConnectionInterrupted(connection=client) from e
11641232

11651233
def hexists(
11661234
self,
1167-
name: str,
1235+
name: KeyT,
11681236
key: KeyT,
11691237
version: Optional[int] = None,
11701238
client: Optional[Redis] = None,
@@ -1174,5 +1242,26 @@ def hexists(
11741242
"""
11751243
if client is None:
11761244
client = self.get_client(write=False)
1245+
key_name = self.make_key(name, version=version)
11771246
nkey = self.make_key(key, version=version)
1178-
return bool(client.hexists(name, nkey))
1247+
return bool(client.hexists(key_name, nkey))
1248+
1249+
def hincrby(
1250+
self,
1251+
name: KeyT,
1252+
key: KeyT,
1253+
increment: int = 1,
1254+
version: Optional[int] = None,
1255+
client: Optional[Redis] = None,
1256+
) -> int:
1257+
if client is None:
1258+
client = self.get_client(write=True)
1259+
key_name = self.make_key(name, version=version)
1260+
nkey = self.make_key(key, version=version)
1261+
try:
1262+
value = client.hincrby(key_name, nkey, increment)
1263+
except ResponseError as exc:
1264+
value = self.hget(key_name, nkey)
1265+
msg = f"Value: {value} is not an integer or out of range."
1266+
raise ValueError(msg) from exc
1267+
return int(value)

django_redis/client/sharded.py

+122
Original file line numberDiff line numberDiff line change
@@ -483,3 +483,125 @@ def smismember(
483483
key = self.make_key(key, version=version)
484484
client = self.get_server(key)
485485
return super().smismember(key, *members, version=version, client=client)
486+
487+
def hset(
488+
self,
489+
name: KeyT,
490+
key: KeyT,
491+
value: Any,
492+
version: Optional[int] = None,
493+
client: Optional[Redis] = None,
494+
) -> int:
495+
if client is None:
496+
key_name = self.make_key(name, version=version)
497+
client = self.get_server(key_name)
498+
return super().hset(key_name, key, value, version=version, client=client)
499+
500+
def hsetnx(
501+
self,
502+
name: KeyT,
503+
key: KeyT,
504+
value: Any,
505+
version: Optional[int] = None,
506+
client: Optional[Redis] = None,
507+
) -> int:
508+
if client is None:
509+
key_name = self.make_key(name, version=version)
510+
client = self.get_server(key_name)
511+
return super().hsetnx(key_name, key, value, version=version, client=client)
512+
513+
def hlen(
514+
self,
515+
name: KeyT,
516+
version: Optional[int] = None,
517+
client: Optional[Redis] = None,
518+
) -> int:
519+
if client is None:
520+
key_name = self.make_key(name, version=version)
521+
client = self.get_server(key_name)
522+
return super().hlen(key_name, version=version, client=client)
523+
524+
def hget(
525+
self,
526+
name: KeyT,
527+
key: KeyT,
528+
version: Optional[int] = None,
529+
client: Optional[Redis] = None,
530+
) -> Any:
531+
if client is None:
532+
key_name = self.make_key(name, version=version)
533+
client = self.get_server(key_name)
534+
return super().hget(key_name, key, version=version, client=client)
535+
536+
def hexists(
537+
self,
538+
name: KeyT,
539+
key: KeyT,
540+
version: Optional[int] = None,
541+
client: Optional[Redis] = None,
542+
) -> bool:
543+
if client is None:
544+
key_name = self.make_key(name, version=version)
545+
client = self.get_server(key_name)
546+
return super().hexists(key_name, key, version=version, client=client)
547+
548+
def hkeys(
549+
self,
550+
name: KeyT,
551+
version: Optional[int] = None,
552+
client: Optional[Redis] = None,
553+
) -> List[Any]:
554+
if client is None:
555+
key_name = self.make_key(name, version=version)
556+
client = self.get_server(key_name)
557+
return super().hkeys(key_name, client=client)
558+
559+
def hgetall(
560+
self,
561+
name: KeyT,
562+
version: Optional[int] = None,
563+
client: Optional[Redis] = None,
564+
) -> Any:
565+
if client is None:
566+
key_name = self.make_key(name, version=version)
567+
client = self.get_server(key_name)
568+
return super().hgetall(key_name, version=version, client=client)
569+
570+
def hincrby(
571+
self,
572+
name: KeyT,
573+
key: KeyT,
574+
increment: int = 1,
575+
version: Optional[int] = None,
576+
client: Optional[Redis] = None,
577+
) -> int:
578+
if client is None:
579+
name = self.make_key(name, version=version)
580+
client = self.get_server(name)
581+
return super().hincrby(
582+
name, key, increment=increment, version=version, client=client
583+
)
584+
585+
def hmget(
586+
self,
587+
name: KeyT,
588+
*keys: KeyT,
589+
version: Optional[int] = None,
590+
client: Optional[Redis] = None,
591+
) -> List[Any]:
592+
if client is None:
593+
name = self.make_key(name, version=version)
594+
client = self.get_server(name)
595+
return super().hmget(name, *keys, version=version, client=client)
596+
597+
def hdel(
598+
self,
599+
name: KeyT,
600+
key: KeyT,
601+
version: Optional[int] = None,
602+
client: Optional[Redis] = None,
603+
) -> int:
604+
if client is None:
605+
name = self.make_key(name, version=version)
606+
client = self.get_server(name)
607+
return super().hdel(name, key, version=version, client=client)

0 commit comments

Comments
 (0)