summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNickolai Novik <is.infinity@yahoo.com>2014-06-21 21:31:44 +0300
committerNickolai Novik <is.infinity@yahoo.com>2014-06-21 21:31:44 +0300
commita21987f68f3e94cc5e0746790a9c117fbdd86c86 (patch)
tree9bca9732a675c2ac7b1741d9c42081bde6139f09
parentbd28b48b143e736c672b90561175e85e6223c86c (diff)
downloadredis-py-a21987f68f3e94cc5e0746790a9c117fbdd86c86.tar.gz
bitpos command implementation
-rwxr-xr-xredis/client.py28
-rw-r--r--tests/test_commands.py22
2 files changed, 46 insertions, 4 deletions
diff --git a/redis/client.py b/redis/client.py
index 0ab8081..bffe226 100755
--- a/redis/client.py
+++ b/redis/client.py
@@ -293,10 +293,10 @@ class StrictRedis(object):
bool
),
string_keys_to_dict(
- 'BITCOUNT DECRBY DEL GETBIT HDEL HLEN INCRBY LINSERT LLEN LPUSHX '
- 'PFADD PFCOUNT RPUSHX SADD SCARD SDIFFSTORE SETBIT SETRANGE '
- 'SINTERSTORE SREM STRLEN SUNIONSTORE ZADD ZCARD ZLEXCOUNT ZREM '
- 'ZREMRANGEBYLEX ZREMRANGEBYRANK ZREMRANGEBYSCORE',
+ 'BITCOUNT BITPOS DECRBY DEL GETBIT HDEL HLEN INCRBY LINSERT LLEN '
+ 'LPUSHX PFADD PFCOUNT RPUSHX SADD SCARD SDIFFSTORE SETBIT '
+ 'SETRANGE SINTERSTORE SREM STRLEN SUNIONSTORE ZADD ZCARD '
+ 'ZLEXCOUNT ZREM ZREMRANGEBYLEX ZREMRANGEBYRANK ZREMRANGEBYSCORE',
int
),
string_keys_to_dict('INCRBYFLOAT HINCRBYFLOAT', float),
@@ -782,6 +782,26 @@ class StrictRedis(object):
"""
return self.execute_command('BITOP', operation, dest, *keys)
+ def bitpos(self, key, bit, start=None, end=None):
+ """
+ Return the position of the first bit set to 1 or 0 in a string.
+ ``start`` and ``end`` difines search range. The range is interpreted
+ as a range of bytes and not a range of bits, so start=0 and end=2
+ means to look at the first three bytes.
+ """
+ if bit not in (0, 1):
+ raise RedisError('bit must be 0 or 1')
+ params = [key, bit]
+
+ start is not None and params.append(start)
+
+ if start is not None and end is not None:
+ params.append(end)
+ elif start is None and end is not None:
+ raise RedisError("start argument is not set, "
+ "when end is specified")
+ return self.execute_command('BITPOS', *params)
+
def decr(self, name, amount=1):
"""
Decrements the value of ``key`` by ``amount``. If no key exists,
diff --git a/tests/test_commands.py b/tests/test_commands.py
index aaff22e..11b15d2 100644
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -230,6 +230,28 @@ class TestRedisCommands(object):
assert int(binascii.hexlify(r['res2']), 16) == 0x0102FFFF
assert int(binascii.hexlify(r['res3']), 16) == 0x000000FF
+ @skip_if_server_version_lt('2.8.7')
+ def test_bitpos(self, r):
+ key = 'key:bitpos'
+ r.set(key, '\xff\xf0\x00')
+ assert r.bitpos(key, 0) == 12
+ assert r.bitpos(key, 0, 2, -1) == 16
+ assert r.bitpos(key, 0, -2, -1) == 12
+ r.set(key, '\x00\xff\xf0')
+ assert r.bitpos(key, 1, 0) == 8
+ assert r.bitpos(key, 1, 1) == 8
+ r.set(key, '\x00\x00\x00')
+ assert r.bitpos(key, 1) == -1
+
+ @skip_if_server_version_lt('2.8.7')
+ def test_bitpos_wrong_arguments(self, r):
+ key = 'key:bitpos:wrong:args'
+ r.set(key, '\xff\xf0\x00')
+ with pytest.raises(exceptions.RedisError):
+ r.bitpos(key, 0, end=1) == 12
+ with pytest.raises(exceptions.RedisError):
+ r.bitpos(key, 7) == 12
+
def test_decr(self, r):
assert r.decr('a') == -1
assert r['a'] == b('-1')