summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy McCurdy <andy@andymccurdy.com>2018-11-15 01:23:50 -0800
committerAndy McCurdy <andy@andymccurdy.com>2018-11-15 01:23:50 -0800
commit20639c334fa9180c046f1e8726057e9ee00e67de (patch)
tree3c1f59e0087416937a1d0441b575d0664b5c5a75
parent69eb38ffd3f991b2a01ec2a604492d4c6b190a80 (diff)
downloadredis-py-20639c334fa9180c046f1e8726057e9ee00e67de.tar.gz
redis-py 3.0.0
-rw-r--r--CHANGES87
-rw-r--r--README.rst145
-rw-r--r--redis/__init__.py2
3 files changed, 216 insertions, 18 deletions
diff --git a/CHANGES b/CHANGES
index 625ed25..42f7c4a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,88 @@
-* UNRELEASED
- * Removed support for EOL Python 2.6 and 3.3.
+* 3.0.0
+ BACKWARDS INCOMPATIBLE CHANGES
+ * When using a Lock as a context manager and the lock fails to be acquired
+ a LockError is now raised. This prevents the code block inside the
+ context manager from being executed if the lock could not be acquired.
+ * Renamed LuaLock to Lock.
+ * Removed the pipeline based Lock implementation in favor of the LuaLock
+ implementation.
+ * Only bytes, strings and numbers (ints, longs and floats) are acceptable
+ for keys and values. Previously redis-py attempted to cast other types
+ to str() and store the result. This caused must confusion and frustration
+ when passing boolean values (cast to 'True' and 'False') or None values
+ (cast to 'None'). It is now the user's responsibility to cast all
+ key names and values to bytes, strings or numbers before passing the
+ value to redis-py.
+ * The StrictRedis class has been renamed to Redis. StrictRedis will
+ continue to exist as an alias of Redis for the forseeable future.
+ * The legacy Redis client class has been removed. It caused much confusion
+ to users.
+ * ZINCRBY arguments 'value' and 'amount' have swapped order to match the
+ the Redis server. The new argument order is: keyname, amount, value.
+ * MGET no longer raises an error if zero keys are passed in. Instead an
+ empty list is returned.
+ * MSET and MSETNX now require all keys/values to be specified in a single
+ dictionary argument named mapping. This was changed to allow for future
+ options to these commands in the future.
+ * ZADD now requires all element names/scores be specified in a single
+ dictionary argument named mapping. This was required to allow the NX,
+ XX, CH and INCR options to be specified.
+ * Removed support for EOL Python 2.6 and 3.3. Thanks jdufresne
+ OTHER CHANGES
+ * Added missing DECRBY command. Thanks derek-dchu
+ * CLUSTER INFO and CLUSTER NODES respones are now properly decoded to
+ strings.
+ * Added a 'locked()' method to Lock objects. This method returns True
+ if the lock has been acquired and owned by the current process,
+ otherwise False.
+ * EXISTS now supports multiple keys. It's return value is now the number
+ of keys in the list that exist.
+ * Ensure all commands can accept key names as bytes. This fixes issues
+ with BLPOP, BRPOP and SORT.
+ * All errors resulting from bad user input are raised as DataError
+ exceptions. DataError is a subclass of RedisError so this should be
+ transparent to anyone previously catching these.
+ * Added support for NX, XX, CH and INCR options to ZADD
+ * Added support for the MIGRATE command
+ * Added support for the MEMORY USAGE and MEMORY PURGE commands. Thanks
+ Itamar Haber
+ * Added support for the 'asynchronous' argument to FLUSHDB and FLUSHALL
+ commands. Thanks Itamar Haber
+ * Added support for the BITFIELD command. Thanks Charles Leifer and
+ Itamar Haber
+ * Improved performance on pipeline requests with large chunks of data.
+ Thanks tzickel
+ * Fixed test suite to not fail if another client is connected to the
+ server the tests are running against.
+ * Added support for SWAPDB. Thanks Itamar Haber
+ * Added support for all STREAM commands. Thanks Roey Prat and Itamar Haber
+ * SHUTDOWN now accepts the 'save' and 'nosave' arguments. Thanks
+ dwilliams-kenzan
+ * Added support for ZPOPMAX, ZPOPMIN, BZPOPMAX, BZPOPMIN. Thanks
+ Itamar Haber
+ * Added support for the 'type' argument in CLIENT LIST. Thanks Roey Prat
+ * Added support for CLIENT PAUSE. Thanks Roey Prat
+ * Added support for CLIENT ID and CLIENT UNBLOCK. Thanks Itamar Haber
+ * GEODIST now returns a None value when referencing a place that does
+ not exist. Thanks qingping209
+ * Added a ping() method to pubsub objects. Thanks krishan-carbon
+ * Fixed a bug with keys in the INFO dict that contained ':' symbols.
+ Thanks mzalimeni
+ * ssl_cert_reqs now has a default value of 'required' by default. This
+ should make connecting to a remote Redis server over SSL more secure.
+ Thanks u2mejc
+ * Fixed the select system call retry compatibility with Python 2.x.
+ Thanks lddubeau
+ * max_connections is now a valid querystring argument for creating
+ connection pools from URLs. Thanks mmaslowskicc
+ * Added the UNLINK command. Thanks yozel
+ * Added socket_type option to Connection for configurability.
+ Thanks garlicnation
+ * Lock.do_acquire now atomically sets acquires the lock and sets the
+ expire value via set(nx=True, px=timeout). Thanks 23doors
+ * Added 'count' argument to SPOP. Thanks AlirezaSadeghi
+ * Fixed an issue parsing client_list respones that contained an '='.
+ Thanks swilly22
* 2.10.6
* Various performance improvements. Thanks cjsimpson
* Fixed a bug with SRANDMEMBER where the behavior for `number=0` did
diff --git a/README.rst b/README.rst
index 91d7902..8327c19 100644
--- a/README.rst
+++ b/README.rst
@@ -57,19 +57,146 @@ 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.
+
+Upgrading from redis-py 2.X to 3.0
+----------------------------------
+
+redis-py 3.0 introduces many new features but required a number of backwards
+incompatible changes to be made in the process. This section attempts to
+provide an upgrade path for users migrating from 2.X to 3.0.
+
+
+Python Version Support
+^^^^^^^^^^^^^^^^^^^^^^
+
+redis-py 3.0 now supports Python 2.7 and Python 3.4+. Python 2.6 and 3.3
+support has been dropped.
+
+
+Client Classes: Redis and StrictRedis
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+redis-py 3.0 drops support for the legacy "Redis" client class. "StrictRedis"
+has been renamed to "Redis" and an alias named "StrictRedis" is provided so
+that users previously using "StrictRedis" can continue to run unchanged.
+
+The 2.X "Redis" class provided alternative implementations of a few commands.
+This confused users (rightfully so) and caused a number of support issues. To
+make things easier going forward, it was decided to drop support for these
+alternate implementations and instead focus on a single client class.
+
+2.X users that are already using StrictRedis don't have to change the class
+name. StrictRedis will continue to work for the forseeable future.
+
+2.X users that are using the Redis class will have to make changes if they
+use any of the following commands:
+
+* SETEX: The argument order has changed. The new order is (name, time, value).
+* LREM: The argument order has changed. The new order is (name, num, value).
+* TTL and PTTL: The return value is now always an int and matches the
+ official Redis command (>0 indicates the timeout, -1 indicates that the key
+ exists but that it has no expire time set, -2 indicates that the key does
+ not exist)
+
+
+MSET, MSETNX and ZADD
+^^^^^^^^^^^^^^^^^^^^^
+
+These commands all accept a mapping of key/value pairs. In redis-py 2.X
+this mapping could be specified as *args or as **kwargs. Both of these styles
+caused issues when Redis introduced optional flags to ZADD. Relying on *args
+caused issues with the optional argument order, especially in Python 2.7.
+Relying on **kwargs caused potential collision issues of user keys with the
+argument names in the method signature.
+
+To resolve this, redis-py 3.0 has changed these three commands to all accept
+a single positional argument named mapping that is expected to be a dict.
+
+MSET, MSETNX and ZADD now look like:
+
+.. code-block:: pycon
+
+ def mset(self, mapping):
+ def msetnx(self, mapping):
+ def zadd(self, name, mapping, nx=False, xx=False, ch=False, incr=False):
+
+All 2.X users that use these commands must modify their code to supply
+keys and values as a dict to these commands.
+
+
+ZINCRBY
+^^^^^^^
+
+redis-py 2.X accidentily modified the argument order of ZINCRBY, swapping the
+order of value and amount. ZINCRBY now looks like:
+
+.. code-block:: pycon
+
+ def zincrby(self, name, amount, value):
+
+All 2.X users that rely on ZINCRBY must swap the order of amount and value
+for the command to continue to work as intended.
+
+
+Encoding of User Input
+^^^^^^^^^^^^^^^^^^^^^^
+
+redis-py 3.0 only accepts user data as bytes, strings or numbers (ints, longs
+and floats). Attempting to specify a key or a value as any other type will
+raise a DataError exception.
+
+redis-py 2.X attempted to coerce any type of input into a string. While
+occasionally convenient, this caused all sorts of hidden errors when users
+passed boolean values (which were coerced to 'True' or 'False'), a None
+value (which was coerced to 'None') or other values, such as user defined
+types.
+
+All 2.X users should make sure that the keys and values they pass into
+redis-py are either bytes, strings or numbers.
+
+
+Locks
+^^^^^
+
+redis-py 3.0 drops support for the pipeline-based Lock and now only supports
+the Lua-based lock. In doing so, LuaLock has been renamed to Lock. This also
+means that redis-py Lock objects require Redis server 2.6 or greater.
+
+2.X users that were explicitly referring to "LuaLock" will have to now refer
+to "Lock" instead.
+
+
+Locks as Context Managers
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+redis-py 3.0 now raises a LockError when using a lock as a context manager and
+the lock cannot be acquired within the specified timeout. This is more of a
+bug fix than a backwards incompatible change. However, given an error is now
+raised where none was before, this might alarm some users.
+
+2.X users should make sure they're wrapping their lock code in a try/catch
+like this:
+
+.. code-block:: pycon
+
+ try:
+ with r.lock('my-lock-key', blocking_timeout=5) as lock:
+ # code you want executed only after the lock has been acquired
+ except LockError:
+ # the lock wasn't acquired
+
+
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 Redis class attempts to adhere
+great job of explaining each command in detail. redis-py attempts to adhere
to the official command syntax. There are a few exceptions:
* **SELECT**: Not implemented. See the explanation in the Thread Safety section
below.
* **DEL**: 'del' is a reserved keyword in the Python syntax. Therefore redis-py
uses 'delete' instead.
-* **CONFIG GET|SET**: These are implemented separately as config_get or config_set.
* **MULTI/EXEC**: These are implemented as part of the Pipeline class. The
pipeline is wrapped with the MULTI and EXEC statements by default when it
is executed, which can be disabled by specifying transaction=False.
@@ -88,18 +215,6 @@ 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 Redis,
-overrides several other commands to provide backwards compatibility with older
-versions of redis-py:
-
-* **LREM**: Order of 'num' and 'value' arguments reversed such that 'num' can
- provide a default value of zero.
-* **ZADD**: Redis specifies the 'score' argument before 'value'. These were swapped
- accidentally when being implemented and not discovered until after people
- were already using it. The Redis class expects \*args in the form of:
- `name1, score1, name2, score2, ...`
-* **SETEX**: Order of 'time' and 'value' arguments reversed.
-
More Detail
-----------
diff --git a/redis/__init__.py b/redis/__init__.py
index 6607155..e8bcb34 100644
--- a/redis/__init__.py
+++ b/redis/__init__.py
@@ -22,7 +22,7 @@ from redis.exceptions import (
)
-__version__ = '2.10.6'
+__version__ = '3.0.0'
VERSION = tuple(map(int, __version__.split('.')))
__all__ = [