summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Spooren <mail@aparcar.org>2020-07-22 12:09:12 -1000
committerGitHub <noreply@github.com>2020-07-22 15:09:12 -0700
commitf001927f91ba3c22cb892bbf1e39b34fd47693bc (patch)
tree2c632cf9cb0718eae74680ba629bcdb30ac43d7d
parent75a2cfe6eeca842801372c997a42707b6dca8c05 (diff)
downloadredis-py-f001927f91ba3c22cb892bbf1e39b34fd47693bc.tar.gz
LPOS: add new command (#1354)
Added the LPOS command from Redis 6.0.6 Fixes #1353
-rw-r--r--docker/base/Dockerfile2
-rwxr-xr-xredis/client.py36
-rw-r--r--tests/test_commands.py32
3 files changed, 69 insertions, 1 deletions
diff --git a/docker/base/Dockerfile b/docker/base/Dockerfile
index ab97386..8e952b8 100644
--- a/docker/base/Dockerfile
+++ b/docker/base/Dockerfile
@@ -1 +1 @@
-FROM redis:6.0.5-buster
+FROM redis:6.0.6-buster
diff --git a/redis/client.py b/redis/client.py
index 9653f7d..5c95e9f 100755
--- a/redis/client.py
+++ b/redis/client.py
@@ -2030,6 +2030,42 @@ class Redis(object):
"Push ``value`` onto the tail of the list ``name`` if ``name`` exists"
return self.execute_command('RPUSHX', name, value)
+ def lpos(self, name, value, rank=None, count=None, maxlen=None):
+ """
+ Get position of ``value`` within the list ``name``
+
+ If specified, ``rank`` indicates the "rank" of the first element to
+ return in case there are multiple copies of ``value`` in the list.
+ By default, LPOS returns the position of the first occurrence of
+ ``value`` in the list. When ``rank`` 2, LPOS returns the position of
+ the second ``value`` in the list. If ``rank`` is negative, LPOS
+ searches the list in reverse. For example, -1 would return the
+ position of the last occurrence of ``value`` and -2 would return the
+ position of the next to last occurrence of ``value``.
+
+ If specified, ``count`` indicates that LPOS should return a list of
+ up to ``count`` positions. A ``count`` of 2 would return a list of
+ up to 2 positions. A ``count`` of 0 returns a list of all positions
+ matching ``value``. When ``count`` is specified and but ``value``
+ does not exist in the list, an empty list is returned.
+
+ If specified, ``maxlen`` indicates the maximum number of list
+ elements to scan. A ``maxlen`` of 1000 will only return the
+ position(s) of items within the first 1000 entries in the list.
+ A ``maxlen`` of 0 (the default) will scan the entire list.
+ """
+ pieces = [name, value]
+ if rank is not None:
+ pieces.extend(['RANK', rank])
+
+ if count is not None:
+ pieces.extend(['COUNT', count])
+
+ if maxlen is not None:
+ pieces.extend(['MAXLEN', maxlen])
+
+ return self.execute_command('LPOS', *pieces)
+
def sort(self, name, start=None, num=None, by=None, get=None,
desc=False, alpha=False, store=None, groups=False):
"""
diff --git a/tests/test_commands.py b/tests/test_commands.py
index c68f14c..91bcbb3 100644
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -1052,6 +1052,38 @@ class TestRedisCommands(object):
assert r.rpush('a', '3', '4') == 4
assert r.lrange('a', 0, -1) == [b'1', b'2', b'3', b'4']
+ @skip_if_server_version_lt('6.0.6')
+ def test_lpos(self, r):
+ assert r.rpush('a', 'a', 'b', 'c', '1', '2', '3', 'c', 'c') == 8
+ assert r.lpos('a', 'a') == 0
+ assert r.lpos('a', 'c') == 2
+
+ assert r.lpos('a', 'c', rank=1) == 2
+ assert r.lpos('a', 'c', rank=2) == 6
+ assert r.lpos('a', 'c', rank=4) is None
+ assert r.lpos('a', 'c', rank=-1) == 7
+ assert r.lpos('a', 'c', rank=-2) == 6
+
+ assert r.lpos('a', 'c', count=0) == [2, 6, 7]
+ assert r.lpos('a', 'c', count=1) == [2]
+ assert r.lpos('a', 'c', count=2) == [2, 6]
+ assert r.lpos('a', 'c', count=100) == [2, 6, 7]
+
+ assert r.lpos('a', 'c', count=0, rank=2) == [6, 7]
+ assert r.lpos('a', 'c', count=2, rank=-1) == [7, 6]
+
+ assert r.lpos('axxx', 'c', count=0, rank=2) == []
+ assert r.lpos('axxx', 'c') is None
+
+ assert r.lpos('a', 'x', count=2) == []
+ assert r.lpos('a', 'x') is None
+
+ assert r.lpos('a', 'a', count=0, maxlen=1) == [0]
+ assert r.lpos('a', 'c', count=0, maxlen=1) == []
+ assert r.lpos('a', 'c', count=0, maxlen=3) == [2]
+ assert r.lpos('a', 'c', count=0, maxlen=3, rank=-1) == [7, 6]
+ assert r.lpos('a', 'c', count=0, maxlen=7, rank=2) == [6]
+
def test_rpushx(self, r):
assert r.rpushx('a', 'b') == 0
assert r.lrange('a', 0, -1) == []