145 lines
5.1 KiB
Python
Raw Normal View History

2022-06-24 17:14:37 +02:00
from itertools import chain
from aioredis.util import (
wait_ok,
wait_convert,
wait_make_dict,
_NOTSET,
_ScanIter,
)
class HashCommandsMixin:
"""Hash commands mixin.
For commands details see: http://redis.io/commands#hash
"""
def hdel(self, key, field, *fields):
"""Delete one or more hash fields."""
return self.execute(b'HDEL', key, field, *fields)
def hexists(self, key, field):
"""Determine if hash field exists."""
fut = self.execute(b'HEXISTS', key, field)
return wait_convert(fut, bool)
def hget(self, key, field, *, encoding=_NOTSET):
"""Get the value of a hash field."""
return self.execute(b'HGET', key, field, encoding=encoding)
def hgetall(self, key, *, encoding=_NOTSET):
"""Get all the fields and values in a hash."""
fut = self.execute(b'HGETALL', key, encoding=encoding)
return wait_make_dict(fut)
def hincrby(self, key, field, increment=1):
"""Increment the integer value of a hash field by the given number."""
return self.execute(b'HINCRBY', key, field, increment)
def hincrbyfloat(self, key, field, increment=1.0):
"""Increment the float value of a hash field by the given number."""
fut = self.execute(b'HINCRBYFLOAT', key, field, increment)
return wait_convert(fut, float)
def hkeys(self, key, *, encoding=_NOTSET):
"""Get all the fields in a hash."""
return self.execute(b'HKEYS', key, encoding=encoding)
def hlen(self, key):
"""Get the number of fields in a hash."""
return self.execute(b'HLEN', key)
def hmget(self, key, field, *fields, encoding=_NOTSET):
"""Get the values of all the given fields."""
return self.execute(b'HMGET', key, field, *fields, encoding=encoding)
def hmset(self, key, field, value, *pairs):
"""Set multiple hash fields to multiple values."""
if len(pairs) % 2 != 0:
raise TypeError("length of pairs must be even number")
return wait_ok(self.execute(b'HMSET', key, field, value, *pairs))
def hmset_dict(self, key, *args, **kwargs):
"""Set multiple hash fields to multiple values.
dict can be passed as first positional argument:
>>> await redis.hmset_dict(
... 'key', {'field1': 'value1', 'field2': 'value2'})
or keyword arguments can be used:
>>> await redis.hmset_dict(
... 'key', field1='value1', field2='value2')
or dict argument can be mixed with kwargs:
>>> await redis.hmset_dict(
... 'key', {'field1': 'value1'}, field2='value2')
.. note:: ``dict`` and ``kwargs`` not get mixed into single dictionary,
if both specified and both have same key(s) -- ``kwargs`` will win:
>>> await redis.hmset_dict('key', {'foo': 'bar'}, foo='baz')
>>> await redis.hget('key', 'foo', encoding='utf-8')
'baz'
"""
if not args and not kwargs:
raise TypeError("args or kwargs must be specified")
pairs = ()
if len(args) > 1:
raise TypeError("single positional argument allowed")
elif len(args) == 1:
if not isinstance(args[0], dict):
raise TypeError("args[0] must be dict")
elif not args[0] and not kwargs:
raise ValueError("args[0] is empty dict")
pairs = chain.from_iterable(args[0].items())
kwargs_pairs = chain.from_iterable(kwargs.items())
return wait_ok(self.execute(
b'HMSET', key, *chain(pairs, kwargs_pairs)))
def hset(self, key, field, value):
"""Set the string value of a hash field."""
return self.execute(b'HSET', key, field, value)
def hsetnx(self, key, field, value):
"""Set the value of a hash field, only if the field does not exist."""
return self.execute(b'HSETNX', key, field, value)
def hvals(self, key, *, encoding=_NOTSET):
"""Get all the values in a hash."""
return self.execute(b'HVALS', key, encoding=encoding)
def hscan(self, key, cursor=0, match=None, count=None):
"""Incrementally iterate hash fields and associated values."""
args = [key, cursor]
match is not None and args.extend([b'MATCH', match])
count is not None and args.extend([b'COUNT', count])
fut = self.execute(b'HSCAN', *args)
return wait_convert(fut, _make_pairs)
def ihscan(self, key, *, match=None, count=None):
"""Incrementally iterate sorted set items using async for.
Usage example:
>>> async for name, val in redis.ihscan(key, match='something*'):
... print('Matched:', name, '->', val)
"""
return _ScanIter(lambda cur: self.hscan(key, cur,
match=match,
count=count))
def hstrlen(self, key, field):
"""Get the length of the value of a hash field."""
return self.execute(b'HSTRLEN', key, field)
def _make_pairs(obj):
it = iter(obj[1])
return (int(obj[0]), list(zip(it, it)))