diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index bfcefc7..0000000 --- a/pytest.ini +++ /dev/null @@ -1,13 +0,0 @@ -[pytest] -addopts = -s -markers = - redismod: run only the redis module tests - pipeline: pipeline tests - onlycluster: marks tests to be run only with cluster mode redis - onlynoncluster: marks tests to be run only with standalone redis - ssl: marker for only the ssl tests - asyncio: marker for async tests - replica: replica tests - experimental: run only experimental tests -asyncio_mode = auto -timeout = 30 diff --git a/python-redis.changes b/python-redis.changes index 7860776..19589b5 100644 --- a/python-redis.changes +++ b/python-redis.changes @@ -1,44 +1,3 @@ -------------------------------------------------------------------- -Tue Jul 18 15:13:06 UTC 2023 - Matej Cepl - -- Update to 5.0.0rc2: - - RESP3 response-callbacks cleanup (#2841) - - Change SISMEMBER return type to int by (#2813) - - rocket New Features - - RESP3 modules support (#2803) - - bug Bug Fixes - - Fixing asyncio import (#2759) - - Fix sharded pubsub threads issue (#2799) - - toolbox Maintenance - - RESP3 tests (#2780) (#2806) - - RESP3 response callbacks (#2798) - - Adding RESP3 tests support (#2793) -- Update to 4.6.0: - - Support JSON.MERGE command (#2761) - - Support JSON.MSET command (#2766) - - rocket New Features - - Extract abstract async connection class (#2734) - - Add support for WAITAOF (#2760) - - Introduce OutOfMemoryError exception for Redis write - command rejections due to OOM errors (#2778) - - Add WITHSCORE argument to ZRANK (#2758) - - bug Bug Fixes - - Fix dead weakref in sentinel connection causing - ReferenceError (#2767) (#2771) - - Fix Key Error in parse_xinfo_stream (#2788) - - Remove unnecessary __del__ handlers (#2755) - - Added support for missing argument to - SentinelManagedConnection.read_response() (#2756) - - toolbox Maintenance - - Fix type hint for retry_on_error in async cluster (#2804) - - Clean up documents and fix some redirects (#2801) - - Add unit tests for the connect method of all Redis - connection classes (#2631) - - Docstring formatting fix (#2796) -- Update to 5.0.0b: - - Add support for sharded pubsub in sync client (#2762) - - Fixed resp3 dict parse response (#2757) - ------------------------------------------------------------------- Sat May 20 12:11:45 UTC 2023 - Andreas Stieger diff --git a/python-redis.spec b/python-redis.spec index 5358189..c605208 100644 --- a/python-redis.spec +++ b/python-redis.spec @@ -18,13 +18,13 @@ %{?sle15_python_module_pythons} Name: python-redis -Version: 5.0.0rc2 +Version: 4.5.5 Release: 0 Summary: Python client for Redis key-value store License: MIT URL: https://github.com/redis/redis-py Source0: https://files.pythonhosted.org/packages/source/r/redis/redis-%{version}.tar.gz -Source1: https://github.com/redis/redis-py/raw/v%{version}/pytest.ini +Source1: https://github.com/redis/redis-py/raw/v%{version}/tox.ini BuildRequires: %{python_module async-timeout >= 4.0.2} BuildRequires: %{python_module base >= 3.7} BuildRequires: %{python_module packaging} @@ -47,7 +47,7 @@ The Python interface to the Redis key-value store. %prep %autosetup -p1 -n redis-%{version} -# pytest.ini for pytest markers +# tox.ini for pytest markers cp %{SOURCE1} . %build @@ -80,6 +80,8 @@ if [ $(getconf LONG_BIT) -ne 64 ]; then # reference precision issues on 32-bit donttest=" or test_geopos" fi +# gh#redis/redis-py#2554 and gh#redis/redis-py#2679 +donttest="$donttest or test_xautoclaim or test_acl_list" %pytest -m 'not (onlycluster or redismod)' -k "not (dummyprefix $donttest)" --ignore tests/test_ssl.py --ignore tests/test_asyncio/test_cluster.py --redis-url=redis://localhost:6379/ %files %{python_files} diff --git a/redis-4.5.5.tar.gz b/redis-4.5.5.tar.gz new file mode 100644 index 0000000..3b2ba66 --- /dev/null +++ b/redis-4.5.5.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc87a0bdef6c8bfe1ef1e1c40be7034390c2ae02d92dcd0c7ca1729443899880 +size 4557115 diff --git a/redis-5.0.0rc2.tar.gz b/redis-5.0.0rc2.tar.gz deleted file mode 100644 index 68e4424..0000000 --- a/redis-5.0.0rc2.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c728ec06056a4bf069dbb64b6fa1cfd76b6721100ec357e578fb516064f64670 -size 4574075 diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..420b081 --- /dev/null +++ b/tox.ini @@ -0,0 +1,379 @@ +[pytest] +addopts = -s +markers = + redismod: run only the redis module tests + pipeline: pipeline tests + onlycluster: marks tests to be run only with cluster mode redis + onlynoncluster: marks tests to be run only with standalone redis + ssl: marker for only the ssl tests + asyncio: marker for async tests + replica: replica tests + experimental: run only experimental tests +asyncio_mode = auto + +[tox] +minversion = 3.2.0 +requires = tox-docker +envlist = {standalone,cluster}-{plain,hiredis,ocsp}-{uvloop,asyncio}-{py37,py38,py39,pypy3},linters,docs + +[docker:master] +name = master +image = redisfab/redis-py:6.2.6 +ports = + 6379:6379/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',6379)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis6.2/master/redis.conf:/redis.conf + +[docker:replica] +name = replica +image = redisfab/redis-py:6.2.6 +links = + master:master +ports = + 6380:6380/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',6380)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis6.2/replica/redis.conf:/redis.conf + +[docker:unstable] +name = unstable +image = redisfab/redis-py:unstable +ports = + 6378:6378/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',6378)) else False" +volumes = + bind:rw:{toxinidir}/docker/unstable/redis.conf:/redis.conf + +[docker:unstable_cluster] +name = unstable_cluster +image = redisfab/redis-py-cluster:unstable +ports = + 6372:6372/tcp + 6373:6373/tcp + 6374:6374/tcp + 6375:6375/tcp + 6376:6376/tcp + 6377:6377/tcp +healtcheck_cmd = python -c "import socket;print(True) if all([0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',port)) for port in range(6372,6377)]) else False" +volumes = + bind:rw:{toxinidir}/docker/unstable_cluster/redis.conf:/redis.conf + +[docker:sentinel_1] +name = sentinel_1 +image = redisfab/redis-py-sentinel:6.2.6 +links = + master:master +ports = + 26379:26379/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',26379)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis6.2/sentinel/sentinel_1.conf:/sentinel.conf + +[docker:sentinel_2] +name = sentinel_2 +image = redisfab/redis-py-sentinel:6.2.6 +links = + master:master +ports = + 26380:26380/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',26380)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis6.2/sentinel/sentinel_2.conf:/sentinel.conf + +[docker:sentinel_3] +name = sentinel_3 +image = redisfab/redis-py-sentinel:6.2.6 +links = + master:master +ports = + 26381:26381/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',26381)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis6.2/sentinel/sentinel_3.conf:/sentinel.conf + +[docker:redis_stack] +name = redis_stack +image = redis/redis-stack-server:edge +ports = + 36379:6379/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',36379)) else False" + +[docker:redis_cluster] +name = redis_cluster +image = redisfab/redis-py-cluster:6.2.6 +ports = + 16379:16379/tcp + 16380:16380/tcp + 16381:16381/tcp + 16382:16382/tcp + 16383:16383/tcp + 16384:16384/tcp +healtcheck_cmd = python -c "import socket;print(True) if all([0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',port)) for port in range(16379,16384)]) else False" +volumes = + bind:rw:{toxinidir}/docker/cluster/redis.conf:/redis.conf + +[docker:redismod_cluster] +name = redismod_cluster +image = redisfab/redis-py-modcluster:edge +ports = + 46379:46379/tcp + 46380:46380/tcp + 46381:46381/tcp + 46382:46382/tcp + 46383:46383/tcp + 46384:46384/tcp +healtcheck_cmd = python -c "import socket;print(True) if all([0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',port)) for port in range(46379,46384)]) else False" +volumes = + bind:rw:{toxinidir}/docker/redismod_cluster/redis.conf:/redis.conf + +[docker:stunnel] +name = stunnel +image = redisfab/stunnel:latest +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',6666)) else False" +links = + master:master +ports = + 6666:6666/tcp +volumes = + bind:ro:{toxinidir}/docker/stunnel/conf:/etc/stunnel/conf.d + bind:ro:{toxinidir}/docker/stunnel/keys:/etc/stunnel/keys + +[docker:redis5_master] +name = redis5_master +image = redisfab/redis-py:5.0-buster +ports = + 6382:6382/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',6382)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis5/master/redis.conf:/redis.conf + +[docker:redis5_replica] +name = redis5_replica +image = redisfab/redis-py:5.0-buster +links = + redis5_master:redis5_master +ports = + 6383:6383/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',6383)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis5/replica/redis.conf:/redis.conf + +[docker:redis5_sentinel_1] +name = redis5_sentinel_1 +image = redisfab/redis-py-sentinel:5.0-buster +links = + redis5_master:redis5_master +ports = + 26382:26382/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',26382)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis5/sentinel/sentinel_1.conf:/sentinel.conf + +[docker:redis5_sentinel_2] +name = redis5_sentinel_2 +image = redisfab/redis-py-sentinel:5.0-buster +links = + redis5_master:redis5_master +ports = + 26383:26383/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',26383)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis5/sentinel/sentinel_2.conf:/sentinel.conf + +[docker:redis5_sentinel_3] +name = redis5_sentinel_3 +image = redisfab/redis-py-sentinel:5.0-buster +links = + redis5_master:redis5_master +ports = + 26384:26384/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',26384)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis5/sentinel/sentinel_3.conf:/sentinel.conf + +[docker:redis5_cluster] +name = redis5_cluster +image = redisfab/redis-py-cluster:5.0-buster +ports = + 16385:16385/tcp + 16386:16386/tcp + 16387:16387/tcp + 16388:16388/tcp + 16389:16389/tcp + 16390:16390/tcp +healtcheck_cmd = python -c "import socket;print(True) if all([0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',port)) for port in range(16385,16390)]) else False" +volumes = + bind:rw:{toxinidir}/docker/cluster/redis.conf:/redis.conf + +[docker:redis4_master] +name = redis4_master +image = redisfab/redis-py:4.0-buster +ports = + 6381:6381/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',6381)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis4/master/redis.conf:/redis.conf + +[docker:redis4_sentinel_1] +name = redis4_sentinel_1 +image = redisfab/redis-py-sentinel:4.0-buster +links = + redis4_master:redis4_master +ports = + 26385:26385/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',26385)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis4/sentinel/sentinel_1.conf:/sentinel.conf + +[docker:redis4_sentinel_2] +name = redis4_sentinel_2 +image = redisfab/redis-py-sentinel:4.0-buster +links = + redis4_master:redis4_master +ports = + 26386:26386/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',26386)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis4/sentinel/sentinel_2.conf:/sentinel.conf + +[docker:redis4_sentinel_3] +name = redis4_sentinel_3 +image = redisfab/redis-py-sentinel:4.0-buster +links = + redis4_master:redis4_master +ports = + 26387:26387/tcp +healtcheck_cmd = python -c "import socket;print(True) if 0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',26387)) else False" +volumes = + bind:rw:{toxinidir}/docker/redis4/sentinel/sentinel_3.conf:/sentinel.conf + +[docker:redis4_cluster] +name = redis4_cluster +image = redisfab/redis-py-cluster:4.0-buster +ports = + 16391:16391/tcp + 16392:16392/tcp + 16393:16393/tcp + 16394:16394/tcp + 16395:16395/tcp + 16396:16396/tcp +healtcheck_cmd = python -c "import socket;print(True) if all([0 == socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('127.0.0.1',port)) for port in range(16391,16396)]) else False" +volumes = + bind:rw:{toxinidir}/docker/cluster/redis.conf:/redis.conf + +[isort] +profile = black +multi_line_output = 3 + +[testenv] +deps = + -r {toxinidir}/requirements.txt + -r {toxinidir}/dev_requirements.txt +docker = + unstable + unstable_cluster + master + replica + sentinel_1 + sentinel_2 + sentinel_3 + redis_cluster + redis_stack + stunnel +extras = + hiredis: hiredis + ocsp: cryptography, pyopenssl, requests +setenv = + CLUSTER_URL = "redis://localhost:16379/0" + UNSTABLE_CLUSTER_URL = "redis://localhost:6372/0" +commands = + standalone: pytest --cov=./ --cov-report=xml:coverage_redis.xml -W always -m 'not onlycluster' --junit-xml=standalone-results.xml {posargs} + standalone-uvloop: pytest --cov=./ --cov-report=xml:coverage_redis.xml -W always -m 'not onlycluster' --junit-xml=standalone-uvloop-results.xml --uvloop {posargs} + cluster: pytest --cov=./ --cov-report=xml:coverage_cluster.xml -W always -m 'not onlynoncluster and not redismod' --redis-url={env:CLUSTER_URL:} --redis-unstable-url={env:UNSTABLE_CLUSTER_URL:} --junit-xml=cluster-results.xml {posargs} + cluster-uvloop: pytest --cov=./ --cov-report=xml:coverage_cluster.xml -W always -m 'not onlynoncluster and not redismod' --redis-url={env:CLUSTER_URL:} --redis-unstable-url={env:UNSTABLE_CLUSTER_URL:} --junit-xml=cluster-uvloop-results.xml --uvloop {posargs} + +[testenv:redis5] +deps = + -r {toxinidir}/requirements.txt + -r {toxinidir}/dev_requirements.txt +docker = + redis5_master + redis5_replica + redis5_sentinel_1 + redis5_sentinel_2 + redis5_sentinel_3 + redis5_cluster +extras = + hiredis: hiredis + cryptography: cryptography, requests +setenv = + CLUSTER_URL = "redis://localhost:16385/0" +commands = + standalone: pytest --cov=./ --cov-report=xml:coverage_redis.xml -W always -m 'not onlycluster and not redismod' {posargs} + cluster: pytest --cov=./ --cov-report=xml:coverage_cluster.xml -W always -m 'not onlynoncluster and not redismod' --redis-url={env:CLUSTER_URL:} {posargs} + +[testenv:redis4] +deps = + -r {toxinidir}/requirements.txt + -r {toxinidir}/dev_requirements.txt +docker = + redis4_master + redis4_sentinel_1 + redis4_sentinel_2 + redis4_sentinel_3 + redis4_cluster +extras = + hiredis: hiredis + cryptography: cryptography, requests +setenv = + CLUSTER_URL = "redis://localhost:16391/0" +commands = + standalone: pytest --cov=./ --cov-report=xml:coverage_redis.xml -W always -m 'not onlycluster and not redismod' {posargs} + cluster: pytest --cov=./ --cov-report=xml:coverage_cluster.xml -W always -m 'not onlynoncluster and not redismod' --redis-url={env:CLUSTER_URL:} {posargs} + +[testenv:devenv] +skipsdist = true +skip_install = true +deps = -r {toxinidir}/dev_requirements.txt +docker = {[testenv]docker} + +[testenv:linters] +deps_files = dev_requirements.txt +docker = +commands = + flake8 + black --target-version py37 --check --diff . + isort --check-only --diff . + vulture redis whitelist.py --min-confidence 80 + flynt --fail-on-change --dry-run . +skipsdist = true +skip_install = true + +[testenv:docs] +deps = -r docs/requirements.txt +docker = +changedir = {toxinidir}/docs +allowlist_externals = make +commands = make html + +[flake8] +max-line-length = 88 +exclude = + *.egg-info, + *.pyc, + .git, + .tox, + .venv*, + build, + docs/*, + dist, + docker, + venv*, + .venv*, + whitelist.py +ignore = + F405 + W503 + E203 + E126