diff options
author | Nickolai Novik <is.infinity@yahoo.com> | 2014-06-21 21:31:44 +0300 |
---|---|---|
committer | Nickolai Novik <is.infinity@yahoo.com> | 2014-06-21 21:31:44 +0300 |
commit | a21987f68f3e94cc5e0746790a9c117fbdd86c86 (patch) | |
tree | 9bca9732a675c2ac7b1741d9c42081bde6139f09 | |
parent | bd28b48b143e736c672b90561175e85e6223c86c (diff) | |
download | redis-py-a21987f68f3e94cc5e0746790a9c117fbdd86c86.tar.gz |
bitpos command implementation
-rwxr-xr-x | redis/client.py | 28 | ||||
-rw-r--r-- | tests/test_commands.py | 22 |
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') |