Skip to content

Commit

Permalink
Adds AsyncRedis support
Browse files Browse the repository at this point in the history
  • Loading branch information
bstrausser committed Feb 29, 2024
1 parent 30f859e commit 5d5f64b
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 5 deletions.
32 changes: 32 additions & 0 deletions modules/redis/testcontainers/redis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from typing import Optional

import redis
from redis.asyncio import Redis as asyncRedis
from testcontainers.core.container import DockerContainer
from testcontainers.core.utils import raise_for_deprecated_parameter
from testcontainers.core.waiting_utils import wait_container_is_ready
Expand Down Expand Up @@ -69,3 +70,34 @@ def start(self) -> "RedisContainer":
super().start()
self._connect()
return self



class AsyncRedisContainer(RedisContainer):
"""
Redis container.
Example
-------
.. doctest::
>>> from testcontainers.redis import AsyncRedisContainer
>>> with AsyncRedisContainer() as redis_container:
... redis_client =await redis_container.get_async_client()
"""

def __init__(
self, image="redis:latest", port_to_expose=6379, password=None, **kwargs
):
super(AsyncRedisContainer, self).__init__(
image, port_to_expose, password, **kwargs
)

async def get_async_client(self, **kwargs):
return await asyncRedis(
host=self.get_container_host_ip(),
port=self.get_exposed_port(self.port),
password=self.password,
**kwargs,
)
63 changes: 61 additions & 2 deletions modules/redis/tests/test_redis.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import time

from testcontainers.redis import RedisContainer
from testcontainers.redis import RedisContainer, AsyncRedisContainer
import redis
import pytest




def test_docker_run_redis():
Expand All @@ -22,6 +26,61 @@ def test_docker_run_redis_with_password():
client.set("hello", "world")
assert client.get("hello") == "world"

pytest.mark.usefixtures('anyio_backend')
@pytest.mark.parametrize('anyio_backend', ['asyncio'])
async def test_key_set_in_async_redis(anyio_backend):
with AsyncRedisContainer() as container:
async_redis_client: redis.Redis = await container.get_async_client(
decode_responses=True
)
key = "key"
expected_value = 1
await async_redis_client.set(key, expected_value)
actual_value = await async_redis_client.get(key)
assert int(actual_value) == expected_value

pytest.mark.usefixtures('anyio_backend')
@pytest.mark.parametrize('anyio_backend', ['asyncio'])
@pytest.mark.skip(reason="Need to sort out async pub/sub")
async def test_docker_run_async_redis(anyio_backend):
config = AsyncRedisContainer()
with config as container:
client: redis.Redis = await container.get_async_client(
decode_responses=True
)
p = await client.pubsub()
await p.subscribe("test")
await client.publish("test", "new_msg")
msg = wait_for_message(p)
assert "data" in msg
assert b"new_msg", msg["data"]

pytest.mark.usefixtures('anyio_backend')
@pytest.mark.parametrize('anyio_backend', ['asyncio'])
async def test_docker_run_async_redis_with_password(anyio_backend):
config = AsyncRedisContainer(password="mypass")
with config as container:
client: redis.Redis = await container.get_async_client(
decode_responses=True
)
await client.set("hello", "world")
assert await client.get("hello") == "world"



pytest.mark.usefixtures('anyio_backend')
@pytest.mark.parametrize('anyio_backend', ['asyncio'])
async def test_key_set_in_async(anyio_backend):
with AsyncRedisContainer() as container:
async_redis_client: redis.Redis = await container.get_async_client(
decode_responses=True
)
key = "key"
expected_value = 1
await async_redis_client.set(key, expected_value)
actual_value = await async_redis_client.get(key)
assert int(actual_value) == expected_value


def wait_for_message(pubsub, timeout=1, ignore_subscribe_messages=True):
now = time.time()
Expand All @@ -32,4 +91,4 @@ def wait_for_message(pubsub, timeout=1, ignore_subscribe_messages=True):
return message
time.sleep(0.01)
now = time.time()
return None
return None
42 changes: 39 additions & 3 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ psycopg2-binary = { version = "*", optional = true }
pika = { version = "*", optional = true }
redis = { version = "*", optional = true }
selenium = { version = "*", optional = true }
anyio = "^4.3.0"

[tool.poetry.extras]
arangodb = ["python-arango"]
Expand Down

0 comments on commit 5d5f64b

Please sign in to comment.