Skip to content

Commit

Permalink
Replace hiredis dependency with valkey
Browse files Browse the repository at this point in the history
Signed-off-by: Mikhail Koviazin <[email protected]>
  • Loading branch information
mkmkme committed Aug 3, 2024
1 parent 652669c commit 414963f
Show file tree
Hide file tree
Showing 36 changed files with 178 additions and 234 deletions.
2 changes: 1 addition & 1 deletion .github/wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ firsttimersonly
fo
genindex
gmail
hiredis
html
http
https
Expand All @@ -101,6 +100,7 @@ json
keyslot
keyspace
kwarg
libvalkey
linters
localhost
lua
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.9', 'pypy-3.10']
test-type: ['standalone', 'cluster']
connection-type: ['hiredis', 'plain']
connection-type: ['libvalkey', 'plain']
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
name: Python ${{ matrix.python-version }} ${{matrix.test-type}}-${{matrix.connection-type}} tests
Expand All @@ -74,8 +74,8 @@ jobs:
pip install -U setuptools wheel
pip install -r requirements.txt
pip install -r dev_requirements.txt
if [ "${{matrix.connection-type}}" == "hiredis" ]; then
pip install "hiredis<3.0.0"
if [ "${{matrix.connection-type}}" == "libvalkey" ]; then
pip install libvalkey
fi
invoke devenv
sleep 10 # time to settle
Expand Down Expand Up @@ -104,10 +104,10 @@ jobs:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.9', 'pypy-3.10']
test-type: ['standalone', 'cluster']
connection-type: ['hiredis', 'plain']
connection-type: ['libvalkey', 'plain']
exclude:
- test-type: 'cluster'
connection-type: 'hiredis'
connection-type: 'libvalkey'
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
name: RESP3 [${{ matrix.python-version }} ${{matrix.test-type}}-${{matrix.connection-type}}]
Expand All @@ -122,8 +122,8 @@ jobs:
pip install -U setuptools wheel
pip install -r requirements.txt
pip install -r dev_requirements.txt
if [ "${{matrix.connection-type}}" == "hiredis" ]; then
pip install "hiredis<3.0.0"
if [ "${{matrix.connection-type}}" == "libvalkey" ]; then
pip install libvalkey
fi
invoke devenv
sleep 10 # time to settle
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ To install valkey-py, simply:
$ pip install valkey
```

For faster performance, install valkey with hiredis support, this provides a compiled response parser, and *for most cases* requires zero code changes.
By default, if hiredis >= 1.0 is available, valkey-py will attempt to use it for response parsing.
For faster performance, install valkey with libvalkey support, this provides a compiled response parser, and *for most cases* requires zero code changes.
By default, if libvalkey >= 2.3.2 is available, valkey-py will attempt to use it for response parsing.

``` bash
$ pip install "valkey[hiredis]"
$ pip install "valkey[libvalkey]"
```

## Usage
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/socket_read_size.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from base import Benchmark

from valkey.connection import PythonParser, _HiredisParser
from valkey.connection import PythonParser, _LibvalkeyParser


class SocketReadBenchmark(Benchmark):

ARGUMENTS = (
{"name": "parser", "values": [PythonParser, _HiredisParser]},
{"name": "parser", "values": [PythonParser, _LibvalkeyParser]},
{
"name": "value_size",
"values": [10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000],
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"Programming Language :: Python :: Implementation :: PyPy",
],
extras_require={
"hiredis": ["hiredis >=1.0.0, <3.0.0"],
"libvalkey": ["libvalkey>=4.0.0b1"],
"ocsp": ["cryptography>=36.0.1", "pyopenssl==20.0.1", "requests>=2.26.0"],
},
)
2 changes: 1 addition & 1 deletion tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def all_tests(c, color=False):
@task
def tests(c, uvloop=False, protocol=2, color=False):
"""Run the valkey-py test suite against the current python,
with and without hiredis.
with and without libvalkey.
"""
print("Starting Valkey tests")
standalone_tests(c, uvloop=uvloop, protocol=protocol, color=color)
Expand Down
7 changes: 1 addition & 6 deletions tests/test_asyncio/test_bloom.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
is_resp2_connection,
skip_ifmodversion_lt,
)
from valkey.exceptions import ModuleError, ValkeyError
from valkey.utils import HIREDIS_AVAILABLE
from valkey.exceptions import ValkeyError

pytestmark = pytest.mark.skip

Expand Down Expand Up @@ -96,10 +95,6 @@ async def do_verify():

await do_verify()
cmds = []
if HIREDIS_AVAILABLE:
with pytest.raises(ModuleError):
cur = await decoded_r.bf().scandump("myBloom", 0)
return

cur = await decoded_r.bf().scandump("myBloom", 0)
first = cur[0]
Expand Down
8 changes: 4 additions & 4 deletions tests/test_asyncio/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytest
import pytest_asyncio
from valkey._cache import EvictionPolicy, _LocalCache
from valkey.utils import HIREDIS_AVAILABLE
from valkey.utils import LIBVALKEY_AVAILABLE


@pytest_asyncio.fixture
Expand All @@ -19,7 +19,7 @@ async def local_cache():
yield _LocalCache()


@pytest.mark.skipif(HIREDIS_AVAILABLE, reason="PythonParser only")
@pytest.mark.skipif(LIBVALKEY_AVAILABLE, reason="PythonParser only")
class TestLocalCache:
@pytest.mark.parametrize("r", [{"cache": _LocalCache()}], indirect=True)
@pytest.mark.onlynoncluster
Expand Down Expand Up @@ -299,7 +299,7 @@ async def test_flush_entire_cache(self, r):
assert await r.get("c") == "1"


@pytest.mark.skipif(HIREDIS_AVAILABLE, reason="PythonParser only")
@pytest.mark.skipif(LIBVALKEY_AVAILABLE, reason="PythonParser only")
@pytest.mark.onlycluster
class TestClusterLocalCache:
@pytest.mark.parametrize("r", [{"cache": _LocalCache()}], indirect=True)
Expand Down Expand Up @@ -368,7 +368,7 @@ async def test_execute_command_keys_not_provided(self, r):
assert cache.get(("GET", "b")) is None


@pytest.mark.skipif(HIREDIS_AVAILABLE, reason="PythonParser only")
@pytest.mark.skipif(LIBVALKEY_AVAILABLE, reason="PythonParser only")
@pytest.mark.onlynoncluster
class TestSentinelLocalCache:

Expand Down
24 changes: 12 additions & 12 deletions tests/test_asyncio/test_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -1730,49 +1730,49 @@ async def test_cluster_rpoplpush(self, r: ValkeyCluster) -> None:

async def test_cluster_sdiff(self, r: ValkeyCluster) -> None:
await r.sadd("{foo}a", "1", "2", "3")
assert await r.sdiff("{foo}a", "{foo}b") == {b"1", b"2", b"3"}
assert set(await r.sdiff("{foo}a", "{foo}b")) == {b"1", b"2", b"3"}
await r.sadd("{foo}b", "2", "3")
assert await r.sdiff("{foo}a", "{foo}b") == {b"1"}
assert await r.sdiff("{foo}a", "{foo}b") == [b"1"]

async def test_cluster_sdiffstore(self, r: ValkeyCluster) -> None:
await r.sadd("{foo}a", "1", "2", "3")
assert await r.sdiffstore("{foo}c", "{foo}a", "{foo}b") == 3
assert await r.smembers("{foo}c") == {b"1", b"2", b"3"}
assert set(await r.smembers("{foo}c")) == {b"1", b"2", b"3"}
await r.sadd("{foo}b", "2", "3")
assert await r.sdiffstore("{foo}c", "{foo}a", "{foo}b") == 1
assert await r.smembers("{foo}c") == {b"1"}
assert await r.smembers("{foo}c") == [b"1"]

async def test_cluster_sinter(self, r: ValkeyCluster) -> None:
await r.sadd("{foo}a", "1", "2", "3")
assert await r.sinter("{foo}a", "{foo}b") == set()
assert await r.sinter("{foo}a", "{foo}b") == []
await r.sadd("{foo}b", "2", "3")
assert await r.sinter("{foo}a", "{foo}b") == {b"2", b"3"}
assert set(await r.sinter("{foo}a", "{foo}b")) == {b"2", b"3"}

async def test_cluster_sinterstore(self, r: ValkeyCluster) -> None:
await r.sadd("{foo}a", "1", "2", "3")
assert await r.sinterstore("{foo}c", "{foo}a", "{foo}b") == 0
assert await r.smembers("{foo}c") == set()
assert await r.smembers("{foo}c") == []
await r.sadd("{foo}b", "2", "3")
assert await r.sinterstore("{foo}c", "{foo}a", "{foo}b") == 2
assert await r.smembers("{foo}c") == {b"2", b"3"}
assert set(await r.smembers("{foo}c")) == {b"2", b"3"}

async def test_cluster_smove(self, r: ValkeyCluster) -> None:
await r.sadd("{foo}a", "a1", "a2")
await r.sadd("{foo}b", "b1", "b2")
assert await r.smove("{foo}a", "{foo}b", "a1")
assert await r.smembers("{foo}a") == {b"a2"}
assert await r.smembers("{foo}b") == {b"b1", b"b2", b"a1"}
assert await r.smembers("{foo}a") == [b"a2"]
assert set(await r.smembers("{foo}b")) == {b"b1", b"b2", b"a1"}

async def test_cluster_sunion(self, r: ValkeyCluster) -> None:
await r.sadd("{foo}a", "1", "2")
await r.sadd("{foo}b", "2", "3")
assert await r.sunion("{foo}a", "{foo}b") == {b"1", b"2", b"3"}
assert set(await r.sunion("{foo}a", "{foo}b")) == {b"1", b"2", b"3"}

async def test_cluster_sunionstore(self, r: ValkeyCluster) -> None:
await r.sadd("{foo}a", "1", "2")
await r.sadd("{foo}b", "2", "3")
assert await r.sunionstore("{foo}c", "{foo}a", "{foo}b") == 3
assert await r.smembers("{foo}c") == {b"1", b"2", b"3"}
assert set(await r.smembers("{foo}c")) == {b"1", b"2", b"3"}

@skip_if_server_version_lt("6.2.0")
async def test_cluster_zdiff(self, r: ValkeyCluster) -> None:
Expand Down
36 changes: 17 additions & 19 deletions tests/test_asyncio/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -1406,7 +1406,7 @@ async def test_zscan_iter(self, r: valkey.Valkey):
async def test_sadd(self, r: valkey.Valkey):
members = {b"1", b"2", b"3"}
await r.sadd("a", *members)
assert await r.smembers("a") == members
assert set(await r.smembers("a")) == members

async def test_scard(self, r: valkey.Valkey):
await r.sadd("a", "1", "2", "3")
Expand All @@ -1415,34 +1415,34 @@ async def test_scard(self, r: valkey.Valkey):
@pytest.mark.onlynoncluster
async def test_sdiff(self, r: valkey.Valkey):
await r.sadd("a", "1", "2", "3")
assert await r.sdiff("a", "b") == {b"1", b"2", b"3"}
assert set(await r.sdiff("a", "b")) == {b"1", b"2", b"3"}
await r.sadd("b", "2", "3")
assert await r.sdiff("a", "b") == {b"1"}
assert await r.sdiff("a", "b") == [b"1"]

@pytest.mark.onlynoncluster
async def test_sdiffstore(self, r: valkey.Valkey):
await r.sadd("a", "1", "2", "3")
assert await r.sdiffstore("c", "a", "b") == 3
assert await r.smembers("c") == {b"1", b"2", b"3"}
assert set(await r.smembers("c")) == {b"1", b"2", b"3"}
await r.sadd("b", "2", "3")
assert await r.sdiffstore("c", "a", "b") == 1
assert await r.smembers("c") == {b"1"}
assert await r.smembers("c") == [b"1"]

@pytest.mark.onlynoncluster
async def test_sinter(self, r: valkey.Valkey):
await r.sadd("a", "1", "2", "3")
assert await r.sinter("a", "b") == set()
assert await r.sinter("a", "b") == []
await r.sadd("b", "2", "3")
assert await r.sinter("a", "b") == {b"2", b"3"}
assert set(await r.sinter("a", "b")) == {b"2", b"3"}

@pytest.mark.onlynoncluster
async def test_sinterstore(self, r: valkey.Valkey):
await r.sadd("a", "1", "2", "3")
assert await r.sinterstore("c", "a", "b") == 0
assert await r.smembers("c") == set()
assert await r.smembers("c") == []
await r.sadd("b", "2", "3")
assert await r.sinterstore("c", "a", "b") == 2
assert await r.smembers("c") == {b"2", b"3"}
assert set(await r.smembers("c")) == {b"2", b"3"}

async def test_sismember(self, r: valkey.Valkey):
await r.sadd("a", "1", "2", "3")
Expand All @@ -1453,22 +1453,22 @@ async def test_sismember(self, r: valkey.Valkey):

async def test_smembers(self, r: valkey.Valkey):
await r.sadd("a", "1", "2", "3")
assert await r.smembers("a") == {b"1", b"2", b"3"}
assert set(await r.smembers("a")) == {b"1", b"2", b"3"}

@pytest.mark.onlynoncluster
async def test_smove(self, r: valkey.Valkey):
await r.sadd("a", "a1", "a2")
await r.sadd("b", "b1", "b2")
assert await r.smove("a", "b", "a1")
assert await r.smembers("a") == {b"a2"}
assert await r.smembers("b") == {b"b1", b"b2", b"a1"}
assert await r.smembers("a") == [b"a2"]
assert set(await r.smembers("b")) == {b"b1", b"b2", b"a1"}

async def test_spop(self, r: valkey.Valkey):
s = [b"1", b"2", b"3"]
await r.sadd("a", *s)
value = await r.spop("a")
assert value in s
assert await r.smembers("a") == set(s) - {value}
assert set(await r.smembers("a")) == set(s) - {value}

@skip_if_server_version_lt("3.2.0")
async def test_spop_multi_value(self, r: valkey.Valkey):
Expand All @@ -1481,9 +1481,7 @@ async def test_spop_multi_value(self, r: valkey.Valkey):
assert value in s

response = await r.spop("a", 1)
assert_resp_response(
r, response, list(set(s) - set(values)), set(s) - set(values)
)
assert set(response) == set(s) - set(values)

async def test_srandmember(self, r: valkey.Valkey):
s = [b"1", b"2", b"3"]
Expand All @@ -1502,20 +1500,20 @@ async def test_srem(self, r: valkey.Valkey):
await r.sadd("a", "1", "2", "3", "4")
assert await r.srem("a", "5") == 0
assert await r.srem("a", "2", "4") == 2
assert await r.smembers("a") == {b"1", b"3"}
assert set(await r.smembers("a")) == {b"1", b"3"}

@pytest.mark.onlynoncluster
async def test_sunion(self, r: valkey.Valkey):
await r.sadd("a", "1", "2")
await r.sadd("b", "2", "3")
assert await r.sunion("a", "b") == {b"1", b"2", b"3"}
assert set(await r.sunion("a", "b")) == {b"1", b"2", b"3"}

@pytest.mark.onlynoncluster
async def test_sunionstore(self, r: valkey.Valkey):
await r.sadd("a", "1", "2")
await r.sadd("b", "2", "3")
assert await r.sunionstore("c", "a", "b") == 3
assert await r.smembers("c") == {b"1", b"2", b"3"}
assert set(await r.smembers("c")) == {b"1", b"2", b"3"}

# SORTED SET COMMANDS
async def test_zadd(self, r: valkey.Valkey):
Expand Down
Loading

0 comments on commit 414963f

Please sign in to comment.