Skip to content

Commit

Permalink
Merge pull request redis#501 from jettify/master
Browse files Browse the repository at this point in the history
Added bitpos command
  • Loading branch information
andymccurdy committed Jul 7, 2014
2 parents 83013b5 + b993b32 commit 55da7fd
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
28 changes: 24 additions & 4 deletions redis/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -792,6 +792,26 @@ def bitop(self, operation, dest, *keys):
"""
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,
Expand Down
22 changes: 22 additions & 0 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,28 @@ def test_bitop_string_operands(self, r):
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, b('\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, b('\x00\xff\xf0'))
assert r.bitpos(key, 1, 0) == 8
assert r.bitpos(key, 1, 1) == 8
r.set(key, b('\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, b('\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')
Expand Down

0 comments on commit 55da7fd

Please sign in to comment.