Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

[DRAFT] 3.0.0 development branch #399

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ dist: xenial
language: python
cache: pip
python:
- "2.7"
- "3.5"
- "3.6"
- "3.7"
Expand All @@ -12,9 +11,6 @@ python:
services:
- redis
install:
- "if [[ $REDIS_VERSION == '3.0' ]]; then REDIS_VERSION=3.0 make redis-install; fi"
- "if [[ $REDIS_VERSION == '3.2' ]]; then REDIS_VERSION=3.2 make redis-install; fi"
- "if [[ $REDIS_VERSION == '4.0' ]]; then REDIS_VERSION=4.0 make redis-install; fi"
- "if [[ $REDIS_VERSION == '5.0' ]]; then REDIS_VERSION=5.0 make redis-install; fi"
- "if [[ $REDIS_VERSION == '6.0' ]]; then REDIS_VERSION=6.0 make redis-install; fi"
- "if [[ $TEST_PYCODESTYLE == '1' ]]; then pip install pycodestyle; fi"
Expand All @@ -24,15 +20,6 @@ install:
- "pip freeze | grep redis"
- "pip freeze"
env:
# Redis 3.0 & HIREDIS
- HIREDIS=0 REDIS_VERSION=3.0
- HIREDIS=1 REDIS_VERSION=3.0
# Redis 3.2 & HIREDIS
- HIREDIS=0 REDIS_VERSION=3.2
- HIREDIS=1 REDIS_VERSION=3.2
# Redis 4.0 & HIREDIS
- HIREDIS=0 REDIS_VERSION=4.0
- HIREDIS=1 REDIS_VERSION=4.0
# Redis 5.0 & HIREDIS
- HIREDIS=0 REDIS_VERSION=5.0
- HIREDIS=1 REDIS_VERSION=5.0
Expand All @@ -50,8 +37,6 @@ after_success:
jobs:
allow_failures:
- python: "nightly"
- python: 2.7
env: TEST_PYCODESTYLE=1
- python: 3.6
env: TEST_PYCODESTYLE=1
# python 3.7 has to be specified manually in the matrix
Expand Down
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ This project is a port of `redis-rb-cluster` by antirez, with a lot of added fun
The branch `master` will always contain the latest unstable/development code that has been merged from Pull Requests. Use the latest commit from master branch on your own risk, there is no guarantees of compatibility or stability of non tagged commits on the master branch. Only tagged releases on the `master` branch is considered stable for use.


# Python 2 Compatibility Note
# Python 2 Compatibility note

As of redis-py-cluster 3.0.0 and above, python 2.7.x will not be supported or maintained.

This library follows the announced change from our upstream package redis-py. Due to this,
we will follow the same python 2.7 deprecation timeline as stated in there.
Expand All @@ -20,6 +22,13 @@ support Python 2 until August 1, 2020. redis-py-cluster 3.0.x will be the next m
version and will require Python 3.5+.


# Supported redis-server versions

This lib only tests for and aims to support redis-server 5.0 and above.

In release 3.0.0 redis-server 3.0.x, 3.2.x and 4.0.x was dropped as officially supported redis-server versions.


# Documentation

All documentation can be found at https://redis-py-cluster.readthedocs.io/en/master
Expand Down Expand Up @@ -54,7 +63,7 @@ Small sample script that shows how to get started with RedisCluster. It can also
>>> # Requires at least one node for cluster discovery. Multiple nodes is recommended.
>>> startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]

>>> rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
>>> rc = RedisCluster(startup_nodes=startup_nodes)

>>> rc.set("foo", "bar")
True
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ def timeit_pipeline(rc, num):

if not args["--nocluster"]:
from rediscluster import RedisCluster
rc = RedisCluster(startup_nodes=startup_nodes, max_connections=32, socket_timeout=0.1, decode_responses=True)
rc = RedisCluster(startup_nodes=startup_nodes, max_connections=32, socket_timeout=0.1)
else:
from redis import Redis
rc = Redis(host=args["--host"], port=args["-p"], socket_timeout=0.1, decode_responses=True)
rc = Redis(host=args["--host"], port=args["-p"], socket_timeout=0.1)
# create specified number processes
processes = []
single_request = int(args["-n"]) // int(args["-c"])
Expand Down
2 changes: 0 additions & 2 deletions docs/client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ Example scripts:

rc = RedisCluster(
startup_nodes=startup_nodes,
decode_responses=True,
host_port_remap=[
{
'from_host': '172.18.0.2',
Expand Down Expand Up @@ -113,7 +112,6 @@ This feature is also useful in cases such as when one is trying to access AWS El
rc = RedisCluster(
startup_nodes=startup_nodes,
host_port_remap=host_port_remap,
decode_responses=True,
ssl=True,
ssl_cert_reqs=None,
# Needed for Elasticache Clusters
Expand Down
23 changes: 19 additions & 4 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Additional code examples of more advance functionality can be found in the `exam
>>> startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]

>>> # Note: See note on Python 3 for decode_responses behaviour
>>> rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
>>> rc = RedisCluster(startup_nodes=startup_nodes)

>>> rc.set("foo", "bar")
True
Expand All @@ -53,7 +53,7 @@ Additional code examples of more advance functionality can be found in the `exam
.. note:: Python 3

Since Python 3 changed to Unicode strings from Python 2's ASCII, the return type of *most* commands will be binary strings,
unless the class is instantiated with the option ``decode_responses=True``.
unless the class is instantiated with the option ``decode_responses=Tru``.

In this case, the responses will be Python 3 strings (Unicode).

Expand All @@ -63,6 +63,10 @@ Additional code examples of more advance functionality can be found in the `exam

If `decode_responses` is set to True, for Python 3 responses will be `str`, for Python 2 they will be `unicode`.

.. note:: Python 3

RedisCluster client class now defaults option `decode_responses=True` as redis-py-cluster 3.0.0 and above only supports python 3.5+ where this option should always be se to True.



Library Dependencies
Expand All @@ -85,16 +89,18 @@ Python versions should follow the same supported python versions as specificed b

If this library supports more then one major version line of `redis-py`, then the supported python versions must include the set of supported python versions by all major version lines.

- 2.7
- 3.5
- 3.6
- 3.7
- 3.8


Python 2 Compatibility Note

Python 2 Compatibility note
###########################

As of redis-py-cluster 3.0.0 and above, python 2.7.x will not be supported or maintained.

This library follows the announced change from our upstream package redis-py. Due to this,
we will follow the same python 2.7 deprecation timeline as stated in there.

Expand All @@ -105,6 +111,15 @@ version and will require Python 3.5+.



Supported redis-server versions
-------------------------------

This lib only tests for and aims to support redis-server 5.0 and above.

In release 3.0.0 redis-server 3.0.x, 3.2.x and 4.0.x was dropped as officially supported redis-server versions.



Regarding duplicate package name on pypi
----------------------------------------

Expand Down
6 changes: 3 additions & 3 deletions docs/readonly-mode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ redis-py-cluster also implements this mode. You can access slave by passing `rea

>>> from rediscluster import RedisCluster
>>> startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]
>>> rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
>>> rc = RedisCluster(startup_nodes=startup_nodes)
>>> rc.set("foo16706", "bar")
>>> rc.set("foo81", "foo")
True
>>> rc_readonly = RedisCluster(startup_nodes=startup_nodes, decode_responses=True, readonly_mode=True)
>>> rc_readonly = RedisCluster(startup_nodes=startup_nodes, readonly_mode=True)
>>> rc_readonly.get("foo16706")
u'bar'
>>> rc_readonly.get("foo81")
Expand All @@ -39,7 +39,7 @@ But this mode has some downside or limitations.

.. code-block:: python

>>> rc_readonly = RedisCluster(startup_nodes=startup_nodes, decode_responses=True, readonly_mode=True)
>>> rc_readonly = RedisCluster(startup_nodes=startup_nodes, readonly_mode=True)
>>> # NO: This works in almost case, but possibly emits Too many Cluster redirections error...
>>> rc_readonly.set('foo', 'bar')
>>> # OK: You should always use get related stuff...
Expand Down
10 changes: 9 additions & 1 deletion docs/release-notes.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
Release Notes
=============

2.1.0 (May **, 2020)
3.0.0 (xxx yy, 2020)
--------------------

* Removed support for python 2.7 following the updated support level of redis-py 4.0.0 release.
* RedisCluster client class now default "decode_responses=True" as that was always needed anyway in python 3.5+
* Redis-server version ranges 3.0.x, 3.2.x & 4.0.x was dropped as officially supported. Redis-server version 5.0 and above is now recommended to use in a cluster and with this client.


2.1.0 (September 26, 2020)
--------------------------

* Add new config option for Client and Pipeline classes to controll how many attempts will be made before bailing out from a ClusterDownError.
Use "cluster_down_retry_attempts=<int>" when creating the client class to controll this behaviour.
* Updated redis-py compatbile version to support any version in the major version 3.0.x, 3.1.x, 3.2.x, 3.3.x., 3.4.x, 3.5.x (#326)
Expand Down
10 changes: 10 additions & 0 deletions docs/upgrading.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ Upgrading redis-py-cluster

This document describes what must be done when upgrading between different versions to ensure that code still works.

2.1.0 --> 3.0.0
---------------

If you are running on pythoon 2.7 then you will not be guaranteed that this lib works in that version. You should upgrade your pythoon version to 3.5+ in order for this lib and redis-py to continue to function properly.

If you for any reason need to set `decode_responses=False` then you need to set that explicitly now as the default value was changed to `True`.

If you are using redis-server 3.0.x, 3.2.x or 4.0.x then you should upgrade to at least redis-server 5.0 or above/latest release. This client might work for older releases, but there will be no testing or validation or guarantes that it will work in the future.


2.0.0 --> 2.1.0
---------------

Expand Down
2 changes: 1 addition & 1 deletion examples/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]

# Note: decode_responses must be set to True when used with python3
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
rc = RedisCluster(startup_nodes=startup_nodes)

rc.set("foo", "bar")

Expand Down
1 change: 0 additions & 1 deletion examples/basic_elasticache_password_protected.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
port=6379,
password='password_is_protected',
skip_full_coverage_check=True, # Bypass Redis CONFIG call to elasticache
decode_responses=True, # decode_responses must be set to True when used with python3
ssl=True, # in-transit encryption, https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/in-transit-encryption.html
ssl_cert_reqs=None # see https://github.com/andymccurdy/redis-py#ssl-connections
)
Expand Down
2 changes: 1 addition & 1 deletion examples/basic_password_protected.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
startup_nodes = [{"host": "127.0.0.1", "port": "7100"}]

# Note: decode_responses must be set to True when used with python3
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True, password='password_is_protected')
rc = RedisCluster(startup_nodes=startup_nodes, password='password_is_protected')

rc.set("foo", "bar")

Expand Down
2 changes: 1 addition & 1 deletion examples/generate_slot_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]

# Note: decode_responses must be set to True when used with python3
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
rc = RedisCluster(startup_nodes=startup_nodes)

# 10 batches
batch_set = {i: [] for i in range(0, 16384)}
Expand Down
2 changes: 1 addition & 1 deletion examples/incr-test-writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from rediscluster import RedisCluster

startup_nodes = [{"host": "127.0.0.1", "port": 7000}]
r = RedisCluster(startup_nodes=startup_nodes, max_connections=32, decode_responses=True)
r = RedisCluster(startup_nodes=startup_nodes, max_connections=32)

for i in xrange(1000000):
d = str(i)
Expand Down
2 changes: 1 addition & 1 deletion examples/pipeline-incrby.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from rediscluster import RedisCluster

startup_nodes = [{"host": "127.0.0.1", "port": 7000}]
r = RedisCluster(startup_nodes=startup_nodes, max_connections=32, decode_responses=True)
r = RedisCluster(startup_nodes=startup_nodes, max_connections=32)

for i in xrange(1000000):
d = str(i)
Expand Down
2 changes: 1 addition & 1 deletion ptp-debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
startup_nodes = [{"host": "127.0.0.1", "port": "7000"}]

# Note: decode_responses must be set to True when used with python3
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
rc = RedisCluster(startup_nodes=startup_nodes)
url_client = RedisCluster.from_url('http://127.0.0.1:7000')

__import__('ptpdb').set_trace()
4 changes: 3 additions & 1 deletion rediscluster/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ class RedisCluster(Redis):

def __init__(self, host=None, port=None, startup_nodes=None, max_connections=None, max_connections_per_node=False, init_slot_cache=True,
readonly_mode=False, reinitialize_steps=None, skip_full_coverage_check=False, nodemanager_follow_cluster=False,
connection_class=None, read_from_replicas=False, cluster_down_retry_attempts=3, host_port_remap=None, **kwargs):
connection_class=None, read_from_replicas=False, cluster_down_retry_attempts=3, host_port_remap=None, decode_responses=True,
**kwargs):
"""
:startup_nodes:
List of nodes that initial bootstrapping can be done from
Expand Down Expand Up @@ -372,6 +373,7 @@ def __init__(self, host=None, port=None, startup_nodes=None, max_connections=Non
nodemanager_follow_cluster=nodemanager_follow_cluster,
connection_class=connection_class,
host_port_remap=host_port_remap,
decode_responses=decode_responses,
**kwargs
)

Expand Down
20 changes: 1 addition & 19 deletions rediscluster/crc.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# -*- coding: utf-8 -*-

# python std lib
import sys

x_mode_m_crc16_lookup = [
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
Expand Down Expand Up @@ -39,25 +36,10 @@
]


def _crc16_py3(data):
def crc16(data):
"""
"""
crc = 0
for byte in data:
crc = ((crc << 8) & 0xff00) ^ x_mode_m_crc16_lookup[((crc >> 8) & 0xff) ^ byte]
return crc & 0xffff


def _crc16_py2(data):
"""
"""
crc = 0
for byte in data:
crc = ((crc << 8) & 0xff00) ^ x_mode_m_crc16_lookup[((crc >> 8) & 0xff) ^ ord(byte)]
return crc & 0xffff


if sys.version_info >= (3, 0, 0):
crc16 = _crc16_py3
else:
crc16 = _crc16_py2
5 changes: 2 additions & 3 deletions rediscluster/nodemanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def __init__(self, startup_nodes=None, reinitialize_steps=None, skip_full_covera
self.encoder = Encoder(
connection_kwargs.get('encoding', 'utf-8'),
connection_kwargs.get('encoding_errors', 'strict'),
connection_kwargs.get('decode_responses', False)
connection_kwargs.get('decode_responses', True),
)
self._validate_host_port_remap(host_port_remap)
self.host_port_remap = host_port_remap
Expand Down Expand Up @@ -99,7 +99,6 @@ def _validate_host_port_remap(self, host_port_remap):
def keyslot(self, key):
"""
Calculate keyslot for a given key.
Tuned for compatibility with python 2.7.x
"""
k = self.encoder.encode(key)

Expand Down Expand Up @@ -153,7 +152,7 @@ def random_node(self):

return self.nodes[key]

def get_redis_link(self, host, port, decode_responses=False):
def get_redis_link(self, host, port, decode_responses=True):
"""
"""
allowed_keys = (
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
redis>=3.0.0,<4.0.0
# Pin this to the latest released version for now. Should use development branch of redis-py in reality but will do for now
redis>=3.5.3
Loading