From d2cc98efedc5a9b437c704696be66b62082ae7cb Mon Sep 17 00:00:00 2001 From: Daniel M Date: Mon, 1 Jan 2024 13:17:41 -0500 Subject: [PATCH] feat:support for redis 5.1.0b1 --- .github/workflows/test.yml | 2 +- docs/guides/implement-command.md | 2 +- docs/guides/test-case.md | 5 +++-- test/test_json/test_json.py | 4 ++-- test/test_mixins/test_hash_commands.py | 2 +- test/test_mixins/test_pubsub_commands.py | 10 +++++----- test/test_mixins/test_streams_commands.py | 4 ++-- test/test_redis_asyncio.py | 13 +++++++++++-- test/testtools.py | 10 ++++++++-- 9 files changed, 34 insertions(+), 18 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a03afdf5..67633153 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,7 +53,7 @@ jobs: matrix: redis-image: [ "redis:6.2.13", "redis:7.0.12", "redis:7.2.2" ] python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ] - redis-py: [ "4.3.6", "4.6.0", "5.0.1" ] + redis-py: [ "4.3.6", "4.6.0", "5.0.1", "5.1.0b1" ] include: - python-version: "3.11" redis-image: "redis:6.2.13" diff --git a/docs/guides/implement-command.md b/docs/guides/implement-command.md index bace1658..4f8e15a6 100644 --- a/docs/guides/implement-command.md +++ b/docs/guides/implement-command.md @@ -91,7 +91,7 @@ to the real server output. decorator `@testtools.run_test_if_redispy_ver` on your tests. example: ```python -@testtools.run_test_if_redispy_ver('above', '4.2.0') # This will run for redis-py 4.2.0 or above. +@testtools.run_test_if_redispy_ver('gte', '4.2.0') # This will run for redis-py 4.2.0 or above. def test_expire_should_not_expire__when_no_expire_is_set(r): r.set('foo', 'bar') assert r.get('foo') == b'bar' diff --git a/docs/guides/test-case.md b/docs/guides/test-case.md index cc1c2ea7..02163d52 100644 --- a/docs/guides/test-case.md +++ b/docs/guides/test-case.md @@ -13,14 +13,15 @@ To write a new test case for a command: - Determine when support for the command was introduced - To limit the redis-server versions, it will run on use: `@pytest.mark.max_server(version)` and `@pytest.mark.min_server(version)` - - To limit the redis-py version use `@run_test_if_redispy_ver(above/below, version)` + - To limit the redis-py version use `@run_test_if_redispy_ver('gte', version)` + (you can use `ge`/`gte`/`lte`/`lt`/`eq`/`ne`). - pytest will inject a redis connection to the argument `r` of the test. Sample of running a test for redis-py v4.2.0 and above, redis-server 7.0 and above. ```python @pytest.mark.min_server('7') -@testtools.run_test_if_redispy_ver('above', '4.2.0') +@testtools.run_test_if_redispy_ver('gte', '4.2.0') def test_expire_should_not_expire__when_no_expire_is_set(r): r.set('foo', 'bar') assert r.get('foo') == b'bar' diff --git a/test/test_json/test_json.py b/test/test_json/test_json.py index 75927b8e..4caba391 100644 --- a/test/test_json/test_json.py +++ b/test/test_json/test_json.py @@ -558,7 +558,7 @@ def test_nummultby(r: redis.Redis): assert r.json().nummultby("doc1", ".b[0].a", 3) == 6 -@testtools.run_test_if_redispy_ver('above', '4.6') +@testtools.run_test_if_redispy_ver('gte', '4.6') @pytest.mark.min_server('7.1') def test_json_merge(r: redis.Redis): # Test with root path $ @@ -579,7 +579,7 @@ def test_json_merge(r: redis.Redis): } -@testtools.run_test_if_redispy_ver('above', '4.6') +@testtools.run_test_if_redispy_ver('gte', '4.6') @pytest.mark.min_server('7.1') def test_mset(r: redis.Redis): r.json().mset([("1", Path.root_path(), 1), ("2", Path.root_path(), 2)]) diff --git a/test/test_mixins/test_hash_commands.py b/test/test_mixins/test_hash_commands.py index 1d2f6e3b..3043d875 100644 --- a/test/test_mixins/test_hash_commands.py +++ b/test/test_mixins/test_hash_commands.py @@ -227,7 +227,7 @@ def test_hmset_empty_raises_error(r: redis.Redis): r.hmset('foo', {}) -@testtools.run_test_if_redispy_ver('below', '4.6') +@testtools.run_test_if_redispy_ver('lte', '4.6') def test_hmset_redispy4(r: redis.Redis): r.hset('foo', 'k1', 'v1') assert r.hmset('foo', {'k2': 'v2', 'k3': 'v3'}) is True diff --git a/test/test_mixins/test_pubsub_commands.py b/test/test_mixins/test_pubsub_commands.py index a48c06bb..a59d3b82 100644 --- a/test/test_mixins/test_pubsub_commands.py +++ b/test/test_mixins/test_pubsub_commands.py @@ -314,7 +314,7 @@ def test_pubsub_run_in_thread(r: redis.Redis): @pytest.mark.slow @pytest.mark.parametrize("timeout_value", [ - 1, pytest.param(None, marks=testtools.run_test_if_redispy_ver('above', '3.2')) + 1, pytest.param(None, marks=testtools.run_test_if_redispy_ver('gte', '3.2')) ]) def test_pubsub_timeout(r, timeout_value): def publish(): @@ -448,7 +448,7 @@ def test_pubsub_numsub(r: redis.Redis): @pytest.mark.min_server('7') -@testtools.run_test_if_redispy_ver('above', '5.0.0rc2') +@testtools.run_test_if_redispy_ver('gte', '5.0.0rc2') def test_published_message_to_shard_channel(r: redis.Redis): p = r.pubsub() p.ssubscribe("foo") @@ -461,7 +461,7 @@ def test_published_message_to_shard_channel(r: redis.Redis): @pytest.mark.min_server('7') -@testtools.run_test_if_redispy_ver('above', '5.0.0rc2') +@testtools.run_test_if_redispy_ver('gte', '5.0.0rc2') def test_subscribe_property_with_shard_channels_cluster(r: redis.Redis): p = r.pubsub() keys = ["foo", "bar", "uni" + chr(4456) + "code"] @@ -507,7 +507,7 @@ def test_subscribe_property_with_shard_channels_cluster(r: redis.Redis): @pytest.mark.min_server('7') -@testtools.run_test_if_redispy_ver('above', '5.0.0') +@testtools.run_test_if_redispy_ver('gte', '5.0.0') def test_pubsub_shardnumsub(r: redis.Redis): channels = {b"foo", b"bar", b"baz"} p1 = r.pubsub() @@ -527,7 +527,7 @@ def test_pubsub_shardnumsub(r: redis.Redis): @pytest.mark.min_server('7') -@testtools.run_test_if_redispy_ver('above', '5.0.0rc2') +@testtools.run_test_if_redispy_ver('gte', '5.0.0rc2') def test_pubsub_shardchannels(r: redis.Redis): p = r.pubsub() p.ssubscribe("foo", "bar", "baz", "quux") diff --git a/test/test_mixins/test_streams_commands.py b/test/test_mixins/test_streams_commands.py index fca408ee..b74b333f 100644 --- a/test/test_mixins/test_streams_commands.py +++ b/test/test_mixins/test_streams_commands.py @@ -638,7 +638,7 @@ def test_xpending_range_negative(r: redis.Redis): @pytest.mark.max_server('6.3') -@testtools.run_test_if_redispy_ver('above', '4.4') +@testtools.run_test_if_redispy_ver('gte', '4.4') def test_xautoclaim_redis6(r: redis.Redis): stream, group, consumer1, consumer2 = "stream", "group", "consumer1", "consumer2" @@ -666,7 +666,7 @@ def test_xautoclaim_redis6(r: redis.Redis): @pytest.mark.min_server('7') -@testtools.run_test_if_redispy_ver('above', '4.4') +@testtools.run_test_if_redispy_ver('gte', '4.4') def test_xautoclaim_redis7(r: redis.Redis): stream, group, consumer1, consumer2 = "stream", "group", "consumer1", "consumer2" diff --git a/test/test_redis_asyncio.py b/test/test_redis_asyncio.py index 71a0a98c..488ad9a1 100644 --- a/test/test_redis_asyncio.py +++ b/test/test_redis_asyncio.py @@ -221,13 +221,22 @@ async def test_failed_script_error7(self, req_aioredis2): @fake_only -async def test_repr(req_aioredis2: redis.asyncio.Redis): +@testtools.run_test_if_redispy_ver('lte', '5.0.9') +async def test_repr_redis_until_51(req_aioredis2: redis.asyncio.Redis): assert re.fullmatch( r'ConnectionPool,db=0>>', repr(req_aioredis2.connection_pool) ) +@testtools.run_test_if_redispy_ver('gte', '5.1.0') +async def test_repr_redis_51(req_aioredis2: redis.asyncio.Redis): + assert re.fullmatch( + r',db=0)>)>', + repr(req_aioredis2.connection_pool) + ) + + @fake_only @pytest.mark.disconnected async def test_not_connected(req_aioredis2: redis.asyncio.Redis): @@ -332,7 +341,7 @@ async def test_async(): assert x == b"plz" -@testtools.run_test_if_redispy_ver('above', '4.4.0') +@testtools.run_test_if_redispy_ver('gte', '4.4.0') @pytest.mark.parametrize('nowait', [False, True]) @pytest.mark.fake async def test_connection_disconnect(nowait): diff --git a/test/testtools.py b/test/testtools.py index 93bc0edc..ce92aa08 100644 --- a/test/testtools.py +++ b/test/testtools.py @@ -22,13 +22,19 @@ def raw_command(r: redis.Redis, *args): r.response_callbacks = response_callbacks -ALLOWED_CONDITIONS = {'above', 'below'} +ALLOWED_CONDITIONS = {'eq', 'gte', 'lte', 'lt', 'gt', 'ne'} def run_test_if_redispy_ver(condition: str, ver: str): if condition not in ALLOWED_CONDITIONS: raise ValueError(f'condition {condition} is not in allowed conditions ({ALLOWED_CONDITIONS})') - cond = REDIS_VERSION >= Version(ver) if condition == 'above' else REDIS_VERSION <= Version(ver) + cond = False + cond = cond or condition == 'eq' and REDIS_VERSION == Version(ver) + cond = cond or condition == 'gte' and REDIS_VERSION >= Version(ver) + cond = cond or condition == 'lte' and REDIS_VERSION <= Version(ver) + cond = cond or condition == 'lt' and REDIS_VERSION < Version(ver) + cond = cond or condition == 'gt' and REDIS_VERSION > Version(ver) + cond = cond or condition == 'ne' and REDIS_VERSION != Version(ver) return pytest.mark.skipif( not cond, reason=f"Test is not applicable to redis-py {REDIS_VERSION} ({condition}, {ver})"