summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy McCurdy <andy@andymccurdy.com>2018-11-13 16:44:36 -0800
committerAndy McCurdy <andy@andymccurdy.com>2018-11-13 16:44:36 -0800
commit36a84fc9ac4e06a9b85ccc4e4eda426b387c7093 (patch)
treeda94cf7658346e86eb212d507de9cbd4511b97d8
parent90a52dd5de111f0053bb3ebaa7c78f73a82a1e3e (diff)
downloadredis-py-36a84fc9ac4e06a9b85ccc4e4eda426b387c7093.tar.gz
remove legacy Redis class
redis-py maintained backwards compatibility by keeping the old "Redis" class around for quite some time. While no doubt a convenience for folks who relied on it, the presence of both Redis and StrictRedis causes a number of support issues and general confusion. With 3.0, we're breaking a few things to make redis-py better going forward. This change removes the old Redis class. We also renamed the StrictRedis class to Redis and aliased StrictRedis to Redis. For people that have been using StrictRedis, this should not change anything. You can continue doing things as you are. People still using the legacy Redis class will need to update the argument order for the SETEX, LREM and ZADD commands. Additionally, the return values for TTL and PTTL now return the integer values -1 when a key exists but has no expire time and -2 when a key does not exist. Previously these cases returned a None value in the Redis class.
-rw-r--r--README.rst16
-rw-r--r--benchmarks/base.py2
-rw-r--r--benchmarks/basic_operations.py2
-rwxr-xr-xredis/client.py103
-rw-r--r--redis/sentinel.py12
-rw-r--r--tests/conftest.py5
-rw-r--r--tests/test_commands.py196
-rw-r--r--tests/test_connection_pool.py2
-rw-r--r--tests/test_lock.py124
-rw-r--r--tests/test_pipeline.py8
-rw-r--r--tests/test_sentinel.py6
11 files changed, 191 insertions, 285 deletions
diff --git a/README.rst b/README.rst
index 7fd299c..91d7902 100644
--- a/README.rst
+++ b/README.rst
@@ -42,7 +42,7 @@ Getting Started
.. code-block:: pycon
>>> import redis
- >>> r = redis.StrictRedis(host='localhost', port=6379, db=0)
+ >>> r = redis.Redis(host='localhost', port=6379, db=0)
>>> r.set('foo', 'bar')
True
>>> r.get('foo')
@@ -53,7 +53,7 @@ Python 2. The user is responsible for decoding to Python 3 strings or Python 2
unicode objects.
If **all** string responses from a client should be decoded, the user can
-specify `decode_responses=True` to `StrictRedis.__init__`. In this case, any
+specify `decode_responses=True` to `Redis.__init__`. In this case, any
Redis command that returns a string type will be decoded with the `encoding`
specified.
@@ -62,7 +62,7 @@ API Reference
The `official Redis command documentation <https://redis.io/commands>`_ does a
great job of explaining each command in detail. redis-py exposes two client
-classes that implement these commands. The StrictRedis class attempts to adhere
+classes that implement these commands. The Redis class attempts to adhere
to the official command syntax. There are a few exceptions:
* **SELECT**: Not implemented. See the explanation in the Thread Safety section
@@ -88,7 +88,7 @@ to the official command syntax. There are a few exceptions:
to keep track of the cursor while iterating. Use the
scan_iter/sscan_iter/hscan_iter/zscan_iter methods for this behavior.
-In addition to the changes above, the Redis class, a subclass of StrictRedis,
+In addition to the changes above, the Redis class, a subclass of Redis,
overrides several other commands to provide backwards compatibility with older
versions of redis-py:
@@ -339,7 +339,7 @@ for new messages. Creating a `PubSub` object is easy.
.. code-block:: pycon
- >>> r = redis.StrictRedis(...)
+ >>> r = redis.Redis(...)
>>> p = r.pubsub()
Once a `PubSub` instance is created, channels and patterns can be subscribed
@@ -560,7 +560,7 @@ it with the multiplier value and returns the result.
.. code-block:: pycon
- >>> r = redis.StrictRedis()
+ >>> r = redis.Redis()
>>> lua = """
... local value = redis.call('GET', KEYS[1])
... value = tonumber(value)
@@ -595,7 +595,7 @@ that points to a completely different Redis server.
.. code-block:: pycon
- >>> r2 = redis.StrictRedis('redis2.example.com')
+ >>> r2 = redis.Redis('redis2.example.com')
>>> r2.set('foo', 3)
>>> multiply(keys=['foo'], args=[5], client=r2)
15
@@ -648,7 +648,7 @@ operations).
>>> slave.get('foo')
'bar'
-The master and slave objects are normal StrictRedis instances with their
+The master and slave objects are normal Redis instances with their
connection pool bound to the Sentinel instance. When a Sentinel backed client
attempts to establish a connection, it first queries the Sentinel servers to
determine an appropriate host to connect to. If no server is found,
diff --git a/benchmarks/base.py b/benchmarks/base.py
index a97001f..44e9341 100644
--- a/benchmarks/base.py
+++ b/benchmarks/base.py
@@ -21,7 +21,7 @@ class Benchmark(object):
}
defaults.update(kwargs)
pool = redis.ConnectionPool(**kwargs)
- self._client = redis.StrictRedis(connection_pool=pool)
+ self._client = redis.Redis(connection_pool=pool)
return self._client
def setup(self, **kwargs):
diff --git a/benchmarks/basic_operations.py b/benchmarks/basic_operations.py
index 34dcd97..a4b675d 100644
--- a/benchmarks/basic_operations.py
+++ b/benchmarks/basic_operations.py
@@ -31,7 +31,7 @@ def parse_args():
def run():
args = parse_args()
- r = redis.StrictRedis()
+ r = redis.Redis()
r.flushall()
set_str(conn=r, num=args.n, pipeline_size=args.P, data_size=args.s)
set_int(conn=r, num=args.n, pipeline_size=args.P, data_size=args.s)
diff --git a/redis/client.py b/redis/client.py
index 05e8b0d..9a508cd 100755
--- a/redis/client.py
+++ b/redis/client.py
@@ -403,7 +403,7 @@ def parse_pubsub_numsub(response, **options):
return list(zip(response[0::2], response[1::2]))
-class StrictRedis(object):
+class Redis(object):
"""
Implementation of the Redis protocol.
@@ -647,7 +647,7 @@ class StrictRedis(object):
atomic, pipelines are useful for reducing the back-and-forth overhead
between the client and server.
"""
- return StrictPipeline(
+ return Pipeline(
self.connection_pool,
self.response_callbacks,
transaction,
@@ -2818,88 +2818,7 @@ class StrictRedis(object):
return self.execute_command(command, *pieces, **kwargs)
-class Redis(StrictRedis):
- """
- Provides backwards compatibility with older versions of redis-py that
- changed arguments to some commands to be more Pythonic, sane, or by
- accident.
- """
-
- # Overridden callbacks
- RESPONSE_CALLBACKS = dict_merge(
- StrictRedis.RESPONSE_CALLBACKS,
- {
- 'TTL': lambda r: r >= 0 and r or None,
- 'PTTL': lambda r: r >= 0 and r or None,
- }
- )
-
- def pipeline(self, transaction=True, shard_hint=None):
- """
- Return a new pipeline object that can queue multiple commands for
- later execution. ``transaction`` indicates whether all commands
- should be executed atomically. Apart from making a group of operations
- atomic, pipelines are useful for reducing the back-and-forth overhead
- between the client and server.
- """
- return Pipeline(
- self.connection_pool,
- self.response_callbacks,
- transaction,
- shard_hint)
-
- def setex(self, name, value, time):
- """
- Set the value of key ``name`` to ``value`` that expires in ``time``
- seconds. ``time`` can be represented by an integer or a Python
- timedelta object.
- """
- if isinstance(time, datetime.timedelta):
- time = int(time.total_seconds())
- return self.execute_command('SETEX', name, time, value)
-
- def lrem(self, name, value, num=0):
- """
- Remove the first ``num`` occurrences of elements equal to ``value``
- from the list stored at ``name``.
-
- The ``num`` argument influences the operation in the following ways:
- num > 0: Remove elements equal to value moving from head to tail.
- num < 0: Remove elements equal to value moving from tail to head.
- num = 0: Remove all elements equal to value.
- """
- return self.execute_command('LREM', name, num, value)
-
- def zadd(self, name, *args, **kwargs):
- """
- NOTE: The order of arguments differs from that of the official ZADD
- command. For backwards compatability, this method accepts arguments
- in the form of name1, score1, name2, score2, while the official Redis
- documents expects score1, name1, score2, name2.
-
- If you're looking to use the standard syntax, consider using the
- StrictRedis class. See the API Reference section of the docs for more
- information.
-
- Set any number of element-name, score pairs to the key ``name``. Pairs
- can be specified in two ways:
-
- As *args, in the form of: name1, score1, name2, score2, ...
- or as **kwargs, in the form of: name1=score1, name2=score2, ...
-
- The following example would add four values to the 'my-key' key:
- redis.zadd('my-key', 'name1', 1.1, 'name2', 2.2, name3=3.3, name4=4.4)
- """
- pieces = []
- if args:
- if len(args) % 2 != 0:
- raise RedisError("ZADD requires an equal number of "
- "values and scores")
- pieces.extend(reversed(args))
- for pair in iteritems(kwargs):
- pieces.append(pair[1])
- pieces.append(pair[0])
- return self.execute_command('ZADD', name, *pieces)
+StrictRedis = Redis
class PubSub(object):
@@ -3203,7 +3122,7 @@ class PubSubWorkerThread(threading.Thread):
self.pubsub.punsubscribe()
-class BasePipeline(object):
+class Pipeline(Redis):
"""
Pipelines provide a way to transmit multiple commands to the Redis server
in one transmission. This is convenient for batch processing, such as
@@ -3433,7 +3352,7 @@ class BasePipeline(object):
exception.args = (msg,) + exception.args[1:]
def parse_response(self, connection, command_name, **options):
- result = StrictRedis.parse_response(
+ result = Redis.parse_response(
self, connection, command_name, **options)
if command_name in self.UNWATCH_COMMANDS:
self.watching = False
@@ -3505,16 +3424,6 @@ class BasePipeline(object):
return self.watching and self.execute_command('UNWATCH') or True
-class StrictPipeline(BasePipeline, StrictRedis):
- "Pipeline for the StrictRedis class"
- pass
-
-
-class Pipeline(BasePipeline, Redis):
- "Pipeline for the Redis class"
- pass
-
-
class Script(object):
"An executable Lua script object returned by ``register_script``"
@@ -3536,7 +3445,7 @@ class Script(object):
client = self.registered_client
args = tuple(keys) + tuple(args)
# make sure the Redis server knows about the script
- if isinstance(client, BasePipeline):
+ if isinstance(client, Pipeline):
# Make sure the pipeline can register the script before executing.
client.scripts.add(self)
try:
diff --git a/redis/sentinel.py b/redis/sentinel.py
index 0a9f2d3..9df2997 100644
--- a/redis/sentinel.py
+++ b/redis/sentinel.py
@@ -2,7 +2,7 @@ import os
import random
import weakref
-from redis.client import StrictRedis
+from redis.client import Redis
from redis.connection import ConnectionPool, Connection
from redis.exceptions import (ConnectionError, ResponseError, ReadOnlyError,
TimeoutError)
@@ -178,7 +178,7 @@ class Sentinel(object):
}
self.sentinel_kwargs = sentinel_kwargs
- self.sentinels = [StrictRedis(hostname, port, **self.sentinel_kwargs)
+ self.sentinels = [Redis(hostname, port, **self.sentinel_kwargs)
for hostname, port in sentinels]
self.min_other_sentinels = min_other_sentinels
self.connection_kwargs = connection_kwargs
@@ -244,7 +244,7 @@ class Sentinel(object):
return slaves
return []
- def master_for(self, service_name, redis_class=StrictRedis,
+ def master_for(self, service_name, redis_class=Redis,
connection_pool_class=SentinelConnectionPool, **kwargs):
"""
Returns a redis client instance for the ``service_name`` master.
@@ -255,7 +255,7 @@ class Sentinel(object):
NOTE: If the master's address has changed, any cached connections to
the old master are closed.
- By default clients will be a redis.StrictRedis instance. Specify a
+ By default clients will be a redis.Redis instance. Specify a
different class to the ``redis_class`` argument if you desire
something different.
@@ -272,7 +272,7 @@ class Sentinel(object):
return redis_class(connection_pool=connection_pool_class(
service_name, self, **connection_kwargs))
- def slave_for(self, service_name, redis_class=StrictRedis,
+ def slave_for(self, service_name, redis_class=Redis,
connection_pool_class=SentinelConnectionPool, **kwargs):
"""
Returns redis client instance for the ``service_name`` slave(s).
@@ -280,7 +280,7 @@ class Sentinel(object):
A SentinelConnectionPool class is used to retrive the slave's
address before establishing a new connection.
- By default clients will be a redis.StrictRedis instance. Specify a
+ By default clients will be a redis.Redis instance. Specify a
different class to the ``redis_class`` argument if you desire
something different.
diff --git a/tests/conftest.py b/tests/conftest.py
index 006697f..5a43968 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -47,11 +47,6 @@ def r(request, **kwargs):
return _get_client(redis.Redis, request, **kwargs)
-@pytest.fixture()
-def sr(request, **kwargs):
- return _get_client(redis.StrictRedis, request, **kwargs)
-
-
def _gen_cluster_mock_resp(r, response):
mock_connection_pool = Mock()
connection = Mock()
diff --git a/tests/test_commands.py b/tests/test_commands.py
index de94a71..1363d8d 100644
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -367,7 +367,7 @@ class TestRedisCommands(object):
assert r.expire('a', 10)
assert 0 < r.ttl('a') <= 10
assert r.persist('a')
- assert not r.ttl('a')
+ assert r.ttl('a') == -1
def test_expireat_datetime(self, r):
expire_at = redis_server_time(r) + datetime.timedelta(minutes=1)
@@ -497,7 +497,7 @@ class TestRedisCommands(object):
assert r.pexpire('a', 60000)
assert 0 < r.pttl('a') <= 60000
assert r.persist('a')
- assert r.pttl('a') is None
+ assert r.pttl('a') == -1
@skip_if_server_version_lt('2.6.0')
def test_pexpireat_datetime(self, r):
@@ -532,6 +532,20 @@ class TestRedisCommands(object):
assert r['a'] == b'value'
assert 0 < r.pttl('a') <= 1000
+ @skip_if_server_version_lt('2.6.0')
+ def test_pttl(self, r):
+ assert not r.pexpire('a', 10000)
+ r['a'] = '1'
+ assert r.pexpire('a', 10000)
+ assert 0 < r.pttl('a') <= 10000
+ assert r.persist('a')
+ assert r.pttl('a') == -1
+
+ @skip_if_server_version_lt('2.8.0')
+ def test_pttl_no_key(self, r):
+ "PTTL on servers 2.8 and after return -2 when the key doesn't exist"
+ assert r.pttl('a') == -2
+
def test_randomkey(self, r):
assert r.randomkey() is None
for key in ('a', 'b', 'c'):
@@ -597,7 +611,7 @@ class TestRedisCommands(object):
assert 0 < r.ttl('a') <= 10
def test_setex(self, r):
- assert r.setex('a', '1', 60)
+ assert r.setex('a', 60, '1')
assert r['a'] == b'1'
assert 0 < r.ttl('a') <= 60
@@ -625,6 +639,18 @@ class TestRedisCommands(object):
assert r.substr('a', 3, 5) == b'345'
assert r.substr('a', 3, -2) == b'345678'
+ def test_ttl(self, r):
+ r['a'] = '1'
+ assert r.expire('a', 10)
+ assert 0 < r.ttl('a') <= 10
+ assert r.persist('a')
+ assert r.ttl('a') == -1
+
+ @skip_if_server_version_lt('2.8.0')
+ def test_ttl_nokey(self, r):
+ "TTL on servers 2.8 and after return -2 when the key doesn't exist"
+ assert r.ttl('a') == -2
+
def test_type(self, r):
assert r.type('a') == b'none'
r['a'] = '1'
@@ -636,7 +662,7 @@ class TestRedisCommands(object):
r.sadd('a', '1')
assert r.type('a') == b'set'
del r['a']
- r.zadd('a', **{'1': 1})
+ r.zadd('a', {'1': 1})
assert r.type('a') == b'zset'
# LIST COMMANDS
@@ -720,11 +746,16 @@ class TestRedisCommands(object):
assert r.lrange('a', 0, -1) == [b'1', b'2', b'3', b'4', b'5']
def test_lrem(self, r):
- r.rpush('a', '1', '1', '1', '1')
- assert r.lrem('a', '1', 1) == 1
- assert r.lrange('a', 0, -1) == [b'1', b'1', b'1']
- assert r.lrem('a', '1') == 3
- assert r.lrange('a', 0, -1) == []
+ r.rpush('a', 'Z', 'b', 'Z', 'Z', 'c', 'Z', 'Z')
+ # remove the first 'Z' item
+ assert r.lrem('a', 1, 'Z') == 1
+ assert r.lrange('a', 0, -1) == [b'b', b'Z', b'Z', b'c', b'Z', b'Z']
+ # remove the last 2 'Z' items
+ assert r.lrem('a', -2, 'Z') == 2
+ assert r.lrange('a', 0, -1) == [b'b', b'Z', b'Z', b'c']
+ # remove all 'Z' items
+ assert r.lrem('a', 0, 'Z') == 2
+ assert r.lrange('a', 0, -1) == [b'b', b'c']
def test_lset(self, r):
r.rpush('a', '1', '2', '3')
@@ -822,7 +853,7 @@ class TestRedisCommands(object):
@skip_if_server_version_lt('2.8.0')
def test_zscan(self, r):
- r.zadd('a', 'a', 1, 'b', 2, 'c', 3)
+ r.zadd('a', {'a': 1, 'b': 2, 'c': 3})
cursor, pairs = r.zscan('a')
assert cursor == 0
assert set(pairs) == {(b'a', 1), (b'b', 2), (b'c', 3)}
@@ -831,7 +862,7 @@ class TestRedisCommands(object):
@skip_if_server_version_lt('2.8.0')
def test_zscan_iter(self, r):
- r.zadd('a', 'a', 1, 'b', 2, 'c', 3)
+ r.zadd('a', {'a': 1, 'b': 2, 'c': 3})
pairs = list(r.zscan_iter('a'))
assert set(pairs) == {(b'a', 1), (b'b', 2), (b'c', 3)}
pairs = list(r.zscan_iter('a', match='a'))
@@ -943,15 +974,17 @@ class TestRedisCommands(object):
# SORTED SET COMMANDS
def test_zadd(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
- assert r.zrange('a', 0, -1) == [b'a1', b'a2', b'a3']
+ mapping = {'a1': 1.0, 'a2': 2.0, 'a3': 3.0}
+ r.zadd('a', mapping)
+ assert r.zrange('a', 0, -1, withscores=True) == \
+ [(b'a1', 1.0), (b'a2', 2.0), (b'a3', 3.0)]
def test_zcard(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
assert r.zcard('a') == 3
def test_zcount(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
assert r.zcount('a', '-inf', '+inf') == 3
assert r.zcount('a', 1, 2) == 2
assert r.zcount('a', '(' + str(1), 2) == 1
@@ -959,7 +992,7 @@ class TestRedisCommands(object):
assert r.zcount('a', 10, 20) == 0
def test_zincrby(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
assert r.zincrby('a', 'a2') == 3.0
assert r.zincrby('a', 'a3', amount=5) == 8.0
assert r.zscore('a', 'a2') == 3.0
@@ -967,45 +1000,45 @@ class TestRedisCommands(object):
@skip_if_server_version_lt('2.8.9')
def test_zlexcount(self, r):
- r.zadd('a', a=0, b=0, c=0, d=0, e=0, f=0, g=0)
+ r.zadd('a', {'a': 0, 'b': 0, 'c': 0, 'd': 0, 'e': 0, 'f': 0, 'g': 0})
assert r.zlexcount('a', '-', '+') == 7
assert r.zlexcount('a', '[b', '[f') == 5
def test_zinterstore_sum(self, r):
- r.zadd('a', a1=1, a2=1, a3=1)
- r.zadd('b', a1=2, a2=2, a3=2)
- r.zadd('c', a1=6, a3=5, a4=4)
+ r.zadd('a', {'a1': 1, 'a2': 1, 'a3': 1})
+ r.zadd('b', {'a1': 2, 'a2': 2, 'a3': 2})
+ r.zadd('c', {'a1': 6, 'a3': 5, 'a4': 4})
assert r.zinterstore('d', ['a', 'b', 'c']) == 2
assert r.zrange('d', 0, -1, withscores=True) == \
[(b'a3', 8), (b'a1', 9)]
def test_zinterstore_max(self, r):
- r.zadd('a', a1=1, a2=1, a3=1)
- r.zadd('b', a1=2, a2=2, a3=2)
- r.zadd('c', a1=6, a3=5, a4=4)
+ r.zadd('a', {'a1': 1, 'a2': 1, 'a3': 1})
+ r.zadd('b', {'a1': 2, 'a2': 2, 'a3': 2})
+ r.zadd('c', {'a1': 6, 'a3': 5, 'a4': 4})
assert r.zinterstore('d', ['a', 'b', 'c'], aggregate='MAX') == 2
assert r.zrange('d', 0, -1, withscores=True) == \
[(b'a3', 5), (b'a1', 6)]
def test_zinterstore_min(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
- r.zadd('b', a1=2, a2=3, a3=5)
- r.zadd('c', a1=6, a3=5, a4=4)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
+ r.zadd('b', {'a1': 2, 'a2': 3, 'a3': 5})
+ r.zadd('c', {'a1': 6, 'a3': 5, 'a4': 4})
assert r.zinterstore('d', ['a', 'b', 'c'], aggregate='MIN') == 2
assert r.zrange('d', 0, -1, withscores=True) == \
[(b'a1', 1), (b'a3', 3)]
def test_zinterstore_with_weight(self, r):
- r.zadd('a', a1=1, a2=1, a3=1)
- r.zadd('b', a1=2, a2=2, a3=2)
- r.zadd('c', a1=6, a3=5, a4=4)
+ r.zadd('a', {'a1': 1, 'a2': 1, 'a3': 1})
+ r.zadd('b', {'a1': 2, 'a2': 2, 'a3': 2})
+ r.zadd('c', {'a1': 6, 'a3': 5, 'a4': 4})
assert r.zinterstore('d', {'a': 1, 'b': 2, 'c': 3}) == 2
assert r.zrange('d', 0, -1, withscores=True) == \
[(b'a3', 20), (b'a1', 23)]
@skip_if_server_version_lt('4.9.0')
def test_zpopmax(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
assert r.zpopmax('a') == [(b'a3', 3)]
# with count
@@ -1014,7 +1047,7 @@ class TestRedisCommands(object):
@skip_if_server_version_lt('4.9.0')
def test_zpopmin(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
assert r.zpopmin('a') == [(b'a1', 1)]
# with count
@@ -1023,30 +1056,30 @@ class TestRedisCommands(object):
@skip_if_server_version_lt('4.9.0')
def test_bzpopmax(self, r):
- r.zadd('a', a1=1, a2=2)
- r.zadd('b', b1=10, b2=20)
+ r.zadd('a', {'a1': 1, 'a2': 2})
+ r.zadd('b', {'b1': 10, 'b2': 20})
assert r.bzpopmax(['b', 'a'], timeout=1) == (b'b', b'b2', 20)
assert r.bzpopmax(['b', 'a'], timeout=1) == (b'b', b'b1', 10)
assert r.bzpopmax(['b', 'a'], timeout=1) == (b'a', b'a2', 2)
assert r.bzpopmax(['b', 'a'], timeout=1) == (b'a', b'a1', 1)
assert r.bzpopmax(['b', 'a'], timeout=1) is None
- r.zadd('c', c1=100)
+ r.zadd('c', {'c1': 100})
assert r.bzpopmax('c', timeout=1) == (b'c', b'c1', 100)
@skip_if_server_version_lt('4.9.0')
def test_bzpopmin(self, r):
- r.zadd('a', a1=1, a2=2)
- r.zadd('b', b1=10, b2=20)
+ r.zadd('a', {'a1': 1, 'a2': 2})
+ r.zadd('b', {'b1': 10, 'b2': 20})
assert r.bzpopmin(['b', 'a'], timeout=1) == (b'b', b'b1', 10)
assert r.bzpopmin(['b', 'a'], timeout=1) == (b'b', b'b2', 20)
assert r.bzpopmin(['b', 'a'], timeout=1) == (b'a', b'a1', 1)
assert r.bzpopmin(['b', 'a'], timeout=1) == (b'a', b'a2', 2)
assert r.bzpopmin(['b', 'a'], timeout=1) is None
- r.zadd('c', c1=100)
+ r.zadd('c', {'c1': 100})
assert r.bzpopmin('c', timeout=1) == (b'c', b'c1', 100)
def test_zrange(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
assert r.zrange('a', 0, 1) == [b'a1', b'a2']
assert r.zrange('a', 1, 2) == [b'a2', b'a3']
@@ -1062,7 +1095,7 @@ class TestRedisCommands(object):
@skip_if_server_version_lt('2.8.9')
def test_zrangebylex(self, r):
- r.zadd('a', a=0, b=0, c=0, d=0, e=0, f=0, g=0)
+ r.zadd('a', {'a': 0, 'b': 0, 'c': 0, 'd': 0, 'e': 0, 'f': 0, 'g': 0})
assert r.zrangebylex('a', '-', '[c') == [b'a', b'b', b'c']
assert r.zrangebylex('a', '-', '(c') == [b'a', b'b']
assert r.zrangebylex('a', '[aaa', '(g') == \
@@ -1072,7 +1105,7 @@ class TestRedisCommands(object):
@skip_if_server_version_lt('2.9.9')
def test_zrevrangebylex(self, r):
- r.zadd('a', a=0, b=0, c=0, d=0, e=0, f=0, g=0)
+ r.zadd('a', {'a': 0, 'b': 0, 'c': 0, 'd': 0, 'e': 0, 'f': 0, 'g': 0})
assert r.zrevrangebylex('a', '[c', '-') == [b'c', b'b', b'a']
assert r.zrevrangebylex('a', '(c', '-') == [b'b', b'a']
assert r.zrevrangebylex('a', '(g', '[aaa') == \
@@ -1082,7 +1115,7 @@ class TestRedisCommands(object):
[b'd', b'c']
def test_zrangebyscore(self, r):
- r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5})
assert r.zrangebyscore('a', 2, 4) == [b'a2', b'a3', b'a4']
# slicing with start/num
@@ -1099,26 +1132,26 @@ class TestRedisCommands(object):
[(b'a2', 2), (b'a3', 3), (b'a4', 4)]
def test_zrank(self, r):
- r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5})
assert r.zrank('a', 'a1') == 0
assert r.zrank('a', 'a2') == 1
assert r.zrank('a', 'a6') is None
def test_zrem(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
assert r.zrem('a', 'a2') == 1
assert r.zrange('a', 0, -1) == [b'a1', b'a3']
assert r.zrem('a', 'b') == 0
assert r.zrange('a', 0, -1) == [b'a1', b'a3']
def test_zrem_multiple_keys(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
assert r.zrem('a', 'a1', 'a2') == 2
assert r.zrange('a', 0, 5) == [b'a3']
@skip_if_server_version_lt('2.8.9')
def test_zremrangebylex(self, r):
- r.zadd('a', a=0, b=0, c=0, d=0, e=0, f=0, g=0)
+ r.zadd('a', {'a': 0, 'b': 0, 'c': 0, 'd': 0, 'e': 0, 'f': 0, 'g': 0})
assert r.zremrangebylex('a', '-', '[c') == 3
assert r.zrange('a', 0, -1) == [b'd', b'e', b'f', b'g']
assert r.zremrangebylex('a', '[f', '+') == 2
@@ -1127,19 +1160,19 @@ class TestRedisCommands(object):
assert r.zrange('a', 0, -1) == [b'd', b'e']
def test_zremrangebyrank(self, r):
- r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5})
assert r.zremrangebyrank('a', 1, 3) == 3
assert r.zrange('a', 0, 5) == [b'a1', b'a5']
def test_zremrangebyscore(self, r):
- r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5})
assert r.zremrangebyscore('a', 2, 4) == 3
assert r.zrange('a', 0, -1) == [b'a1', b'a5']
assert r.zremrangebyscore('a', 2, 4) == 0
assert r.zrange('a', 0, -1) == [b'a1', b'a5']
def test_zrevrange(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
assert r.zrevrange('a', 0, 1) == [b'a3', b'a2']
assert r.zrevrange('a', 1, 2) == [b'a2', b'a1']
@@ -1155,7 +1188,7 @@ class TestRedisCommands(object):
[(b'a3', 3.0), (b'a2', 2.0)]
def test_zrevrangebyscore(self, r):
- r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5})
assert r.zrevrangebyscore('a', 4, 2) == [b'a4', b'a3', b'a2']
# slicing with start/num
@@ -1172,45 +1205,45 @@ class TestRedisCommands(object):
[(b'a4', 4), (b'a3', 3), (b'a2', 2)]
def test_zrevrank(self, r):
- r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5})
assert r.zrevrank('a', 'a1') == 4
assert r.zrevrank('a', 'a2') == 3
assert r.zrevrank('a', 'a6') is None
def test_zscore(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
assert r.zscore('a', 'a1') == 1.0
assert r.zscore('a', 'a2') == 2.0
assert r.zscore('a', 'a4') is None
def test_zunionstore_sum(self, r):
- r.zadd('a', a1=1, a2=1, a3=1)
- r.zadd('b', a1=2, a2=2, a3=2)
- r.zadd('c', a1=6, a3=5, a4=4)
+ r.zadd('a', {'a1': 1, 'a2': 1, 'a3': 1})
+ r.zadd('b', {'a1': 2, 'a2': 2, 'a3': 2})
+ r.zadd('c', {'a1': 6, 'a3': 5, 'a4': 4})
assert r.zunionstore('d', ['a', 'b', 'c']) == 4
assert r.zrange('d', 0, -1, withscores=True) == \
[(b'a2', 3), (b'a4', 4), (b'a3', 8), (b'a1', 9)]
def test_zunionstore_max(self, r):
- r.zadd('a', a1=1, a2=1, a3=1)
- r.zadd('b', a1=2, a2=2, a3=2)
- r.zadd('c', a1=6, a3=5, a4=4)
+ r.zadd('a', {'a1': 1, 'a2': 1, 'a3': 1})
+ r.zadd('b', {'a1': 2, 'a2': 2, 'a3': 2})
+ r.zadd('c', {'a1': 6, 'a3': 5, 'a4': 4})
assert r.zunionstore('d', ['a', 'b', 'c'], aggregate='MAX') == 4
assert r.zrange('d', 0, -1, withscores=True) == \
[(b'a2', 2), (b'a4', 4), (b'a3', 5), (b'a1', 6)]
def test_zunionstore_min(self, r):
- r.zadd('a', a1=1, a2=2, a3=3)
- r.zadd('b', a1=2, a2=2, a3=4)
- r.zadd('c', a1=6, a3=5, a4=4)
+ r.zadd('a', {'a1': 1, 'a2': 2, 'a3': 3})
+ r.zadd('b', {'a1': 2, 'a2': 2, 'a3': 4})
+ r.zadd('c', {'a1': 6, 'a3': 5, 'a4': 4})
assert r.zunionstore('d', ['a', 'b', 'c'], aggregate='MIN') == 4
assert r.zrange('d', 0, -1, withscores=True) == \
[(b'a1', 1), (b'a2', 2), (b'a3', 3), (b'a4', 4)]
def test_zunionstore_with_weight(self, r):
- r.zadd('a', a1=1, a2=1, a3=1)
- r.zadd('b', a1=2, a2=2, a3=2)
- r.zadd('c', a1=6, a3=5, a4=4)
+ r.zadd('a', {'a1': 1, 'a2': 1, 'a3': 1})
+ r.zadd('b', {'a1': 2, 'a2': 2, 'a3': 2})
+ r.zadd('c', {'a1': 6, 'a3': 5, 'a4': 4})
assert r.zunionstore('d', {'a': 1, 'b': 2, 'c': 3}) == 4
assert r.zrange('d', 0, -1, withscores=True) == \
[(b'a2', 5), (b'a4', 12), (b'a3', 20), (b'a1', 23)]
@@ -2183,41 +2216,6 @@ class TestRedisCommands(object):
assert isinstance(r.memory_usage('foo'), int)
-class TestStrictCommands(object):
- def test_strict_zadd(self, sr):
- mapping = {'a1': 1.0, 'a2': 2.0, 'a3': 3.0}
- sr.zadd('a', mapping)
- assert sr.zrange('a', 0, -1, withscores=True) == \
- [(b'a1', 1.0), (b'a2', 2.0), (b'a3', 3.0)]
-
- def test_strict_lrem(self, sr):
- sr.rpush('a', 'a1', 'a2', 'a3', 'a1')
- sr.lrem('a', 0, 'a1')
- assert sr.lrange('a', 0, -1) == [b'a2', b'a3']
-
- def test_strict_setex(self, sr):
- assert sr.setex('a', 60, '1')
- assert sr['a'] == b'1'
- assert 0 < sr.ttl('a') <= 60
-
- def test_strict_ttl(self, sr):
- assert not sr.expire('a', 10)
- sr['a'] = '1'
- assert sr.expire('a', 10)
- assert 0 < sr.ttl('a') <= 10
- assert sr.persist('a')
- assert sr.ttl('a') == -1
-
- @skip_if_server_version_lt('2.6.0')
- def test_strict_pttl(self, sr):
- assert not sr.pexpire('a', 10000)
- sr['a'] = '1'
- assert sr.pexpire('a', 10000)
- assert 0 < sr.pttl('a') <= 10000
- assert sr.persist('a')
- assert sr.pttl('a') == -1
-
-
class TestBinarySave(object):
def test_binary_get_set(self, r):
@@ -2301,5 +2299,5 @@ class TestBinarySave(object):
precision.
"""
timestamp = 1349673917.939762
- r.zadd('a', 'a1', timestamp)
+ r.zadd('a', {'a1': timestamp})
assert r.zscore('a', 'a1') == timestamp
diff --git a/tests/test_connection_pool.py b/tests/test_connection_pool.py
index 1315abe..b0dec67 100644
--- a/tests/test_connection_pool.py
+++ b/tests/test_connection_pool.py
@@ -299,7 +299,7 @@ class TestConnectionPoolURLParsing(object):
assert isinstance(pool, redis.BlockingConnectionPool)
def test_client_creates_connection_pool(self):
- r = redis.StrictRedis.from_url('redis://myhost')
+ r = redis.Redis.from_url('redis://myhost')
assert r.connection_pool.connection_class == redis.Connection
assert r.connection_pool.connection_kwargs == {
'host': 'myhost',
diff --git a/tests/test_lock.py b/tests/test_lock.py
index b4f9a5d..9e0e2fe 100644
--- a/tests/test_lock.py
+++ b/tests/test_lock.py
@@ -12,17 +12,17 @@ class TestLock(object):
kwargs['lock_class'] = self.lock_class
return redis.lock(*args, **kwargs)
- def test_lock(self, sr):
- lock = self.get_lock(sr, 'foo')
+ def test_lock(self, r):
+ lock = self.get_lock(r, 'foo')
assert lock.acquire(blocking=False)
- assert sr.get('foo') == lock.local.token
- assert sr.ttl('foo') == -1
+ assert r.get('foo') == lock.local.token
+ assert r.ttl('foo') == -1
lock.release()
- assert sr.get('foo') is None
+ assert r.get('foo') is None
- def test_competing_locks(self, sr):
- lock1 = self.get_lock(sr, 'foo')
- lock2 = self.get_lock(sr, 'foo')
+ def test_competing_locks(self, r):
+ lock1 = self.get_lock(r, 'foo')
+ lock2 = self.get_lock(r, 'foo')
assert lock1.acquire(blocking=False)
assert not lock2.acquire(blocking=False)
lock1.release()
@@ -30,86 +30,86 @@ class TestLock(object):
assert not lock1.acquire(blocking=False)
lock2.release()
- def test_timeout(self, sr):
- lock = self.get_lock(sr, 'foo', timeout=10)
+ def test_timeout(self, r):
+ lock = self.get_lock(r, 'foo', timeout=10)
assert lock.acquire(blocking=False)
- assert 8 < sr.ttl('foo') <= 10
+ assert 8 < r.ttl('foo') <= 10
lock.release()
- def test_float_timeout(self, sr):
- lock = self.get_lock(sr, 'foo', timeout=9.5)
+ def test_float_timeout(self, r):
+ lock = self.get_lock(r, 'foo', timeout=9.5)
assert lock.acquire(blocking=False)
- assert 8 < sr.pttl('foo') <= 9500
+ assert 8 < r.pttl('foo') <= 9500
lock.release()
- def test_blocking_timeout(self, sr):
- lock1 = self.get_lock(sr, 'foo')
+ def test_blocking_timeout(self, r):
+ lock1 = self.get_lock(r, 'foo')
assert lock1.acquire(blocking=False)
- lock2 = self.get_lock(sr, 'foo', blocking_timeout=0.2)
+ lock2 = self.get_lock(r, 'foo', blocking_timeout=0.2)
start = time.time()
assert not lock2.acquire()
assert (time.time() - start) > 0.2
lock1.release()
- def test_context_manager(self, sr):
+ def test_context_manager(self, r):
# blocking_timeout prevents a deadlock if the lock can't be acquired
# for some reason
- with self.get_lock(sr, 'foo', blocking_timeout=0.2) as lock:
- assert sr.get('foo') == lock.local.token
- assert sr.get('foo') is None
+ with self.get_lock(r, 'foo', blocking_timeout=0.2) as lock:
+ assert r.get('foo') == lock.local.token
+ assert r.get('foo') is None
- def test_high_sleep_raises_error(self, sr):
+ def test_high_sleep_raises_error(self, r):
"If sleep is higher than timeout, it should raise an error"
with pytest.raises(LockError):
- self.get_lock(sr, 'foo', timeout=1, sleep=2)
+ self.get_lock(r, 'foo', timeout=1, sleep=2)
- def test_releasing_unlocked_lock_raises_error(self, sr):
- lock = self.get_lock(sr, 'foo')
+ def test_releasing_unlocked_lock_raises_error(self, r):
+ lock = self.get_lock(r, 'foo')
with pytest.raises(LockError):
lock.release()
- def test_releasing_lock_no_longer_owned_raises_error(self, sr):
- lock = self.get_lock(sr, 'foo')
+ def test_releasing_lock_no_longer_owned_raises_error(self, r):
+ lock = self.get_lock(r, 'foo')
lock.acquire(blocking=False)
# manually change the token
- sr.set('foo', 'a')
+ r.set('foo', 'a')
with pytest.raises(LockError):
lock.release()
# even though we errored, the token is still cleared
assert lock.local.token is None
- def test_extend_lock(self, sr):
- lock = self.get_lock(sr, 'foo', timeout=10)
+ def test_extend_lock(self, r):
+ lock = self.get_lock(r, 'foo', timeout=10)
assert lock.acquire(blocking=False)
- assert 8000 < sr.pttl('foo') <= 10000
+ assert 8000 < r.pttl('foo') <= 10000
assert lock.extend(10)
- assert 16000 < sr.pttl('foo') <= 20000
+ assert 16000 < r.pttl('foo') <= 20000
lock.release()
- def test_extend_lock_float(self, sr):
- lock = self.get_lock(sr, 'foo', timeout=10.0)
+ def test_extend_lock_float(self, r):
+ lock = self.get_lock(r, 'foo', timeout=10.0)
assert lock.acquire(blocking=False)
- assert 8000 < sr.pttl('foo') <= 10000
+ assert 8000 < r.pttl('foo') <= 10000
assert lock.extend(10.0)
- assert 16000 < sr.pttl('foo') <= 20000
+ assert 16000 < r.pttl('foo') <= 20000
lock.release()
- def test_extending_unlocked_lock_raises_error(self, sr):
- lock = self.get_lock(sr, 'foo', timeout=10)
+ def test_extending_unlocked_lock_raises_error(self, r):
+ lock = self.get_lock(r, 'foo', timeout=10)
with pytest.raises(LockError):
lock.extend(10)
- def test_extending_lock_with_no_timeout_raises_error(self, sr):
- lock = self.get_lock(sr, 'foo')
+ def test_extending_lock_with_no_timeout_raises_error(self, r):
+ lock = self.get_lock(r, 'foo')
assert lock.acquire(blocking=False)
with pytest.raises(LockError):
lock.extend(10)
lock.release()
- def test_extending_lock_no_longer_owned_raises_error(self, sr):
- lock = self.get_lock(sr, 'foo')
+ def test_extending_lock_no_longer_owned_raises_error(self, r):
+ lock = self.get_lock(r, 'foo')
assert lock.acquire(blocking=False)
- sr.set('foo', 'a')
+ r.set('foo', 'a')
with pytest.raises(LockError):
lock.extend(10)
@@ -119,48 +119,48 @@ class TestLuaLock(TestLock):
class TestLockClassSelection(object):
- def test_lock_class_argument(self, sr):
- lock = sr.lock('foo', lock_class=Lock)
+ def test_lock_class_argument(self, r):
+ lock = r.lock('foo', lock_class=Lock)
assert type(lock) == Lock
- lock = sr.lock('foo', lock_class=LuaLock)
+ lock = r.lock('foo', lock_class=LuaLock)
assert type(lock) == LuaLock
- def test_cached_lualock_flag(self, sr):
+ def test_cached_lualock_flag(self, r):
try:
- sr._use_lua_lock = True
- lock = sr.lock('foo')
+ r._use_lua_lock = True
+ lock = r.lock('foo')
assert type(lock) == LuaLock
finally:
- sr._use_lua_lock = None
+ r._use_lua_lock = None
- def test_cached_lock_flag(self, sr):
+ def test_cached_lock_flag(self, r):
try:
- sr._use_lua_lock = False
- lock = sr.lock('foo')
+ r._use_lua_lock = False
+ lock = r.lock('foo')
assert type(lock) == Lock
finally:
- sr._use_lua_lock = None
+ r._use_lua_lock = None
- def test_lua_compatible_server(self, sr, monkeypatch):
+ def test_lua_compatible_server(self, r, monkeypatch):
@classmethod
def mock_register(cls, redis):
return
monkeypatch.setattr(LuaLock, 'register_scripts', mock_register)
try:
- lock = sr.lock('foo')
+ lock = r.lock('foo')
assert type(lock) == LuaLock
- assert sr._use_lua_lock is True
+ assert r._use_lua_lock is True
finally:
- sr._use_lua_lock = None
+ r._use_lua_lock = None
- def test_lua_unavailable(self, sr, monkeypatch):
+ def test_lua_unavailable(self, r, monkeypatch):
@classmethod
def mock_register(cls, redis):
raise ResponseError()
monkeypatch.setattr(LuaLock, 'register_scripts', mock_register)
try:
- lock = sr.lock('foo')
+ lock = r.lock('foo')
assert type(lock) == Lock
- assert sr._use_lua_lock is False
+ assert r._use_lua_lock is False
finally:
- sr._use_lua_lock = None
+ r._use_lua_lock = None
diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py
index 3d63d91..9487a42 100644
--- a/tests/test_pipeline.py
+++ b/tests/test_pipeline.py
@@ -8,8 +8,12 @@ from redis._compat import unichr, unicode
class TestPipeline(object):
def test_pipeline(self, r):
with r.pipeline() as pipe:
- pipe.set('a', 'a1').get('a').zadd('z', z1=1).zadd('z', z2=4)
- pipe.zincrby('z', 'z1').zrange('z', 0, 5, withscores=True)
+ (pipe.set('a', 'a1')
+ .get('a')
+ .zadd('z', {'z1': 1})
+ .zadd('z', {'z2': 4})
+ .zincrby('z', 'z1')
+ .zrange('z', 0, 5, withscores=True))
assert pipe.execute() == \
[
True,
diff --git a/tests/test_sentinel.py b/tests/test_sentinel.py
index 5ed75f0..1081e2b 100644
--- a/tests/test_sentinel.py
+++ b/tests/test_sentinel.py
@@ -56,10 +56,10 @@ class SentinelTestCluster(object):
@pytest.fixture()
def cluster(request):
def teardown():
- redis.sentinel.StrictRedis = saved_StrictRedis
+ redis.sentinel.Redis = saved_Redis
cluster = SentinelTestCluster()
- saved_StrictRedis = redis.sentinel.StrictRedis
- redis.sentinel.StrictRedis = cluster.client
+ saved_Redis = redis.sentinel.Redis
+ redis.sentinel.Redis = cluster.client
request.addfinalizer(teardown)
return cluster