Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

floats are no longer serialized to support atomic float operations #14

Merged
merged 1 commit into from
Dec 17, 2024
Merged
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
11 changes: 7 additions & 4 deletions django_valkey/async_cache/client/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,12 +403,15 @@ async def clear(self, client: AValkey | Any | None = None) -> bool:

aclear = clear

async def decode(self, value) -> Any:
async def decode(self, value: bytes) -> Any:
"""
Decode the given value.
"""
try:
value = int(value)
if value.isdigit():
value = int(value)
else:
value = float(value)
except (ValueError, TypeError):
# Handle values that weren't compressed (small stuff)
with suppress(CompressorError):
Expand All @@ -419,11 +422,11 @@ async def decode(self, value) -> Any:

adecode = decode

async def encode(self, value) -> bytes | int:
async def encode(self, value) -> bytes | int | float:
"""
Encode the given value.
"""
if isinstance(value, bool) or not isinstance(value, int):
if type(value) is not int and type(value) is not float:
value = self._serializer.dumps(value)
return self._compressor.compress(value)

Expand Down
11 changes: 7 additions & 4 deletions django_valkey/base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,25 +524,28 @@ def clear(self, client: Backend | Any | None = None) -> bool:
except _main_exceptions as e:
raise ConnectionInterrupted(connection=client) from e

def decode(self, value: EncodableT) -> Any:
def decode(self, value: bytes) -> Any:
"""
Decode the given value.
"""
try:
value = int(value)
if value.isdigit():
value = int(value)
else:
value = float(value)
except (ValueError, TypeError):
# Handle little values, chosen to be not compressed
with suppress(CompressorError):
value = self._compressor.decompress(value)
value = self._serializer.loads(value)
return value

def encode(self, value: EncodableT) -> bytes | int:
def encode(self, value: EncodableT) -> bytes | int | float:
"""
Encode the given value.
"""

if isinstance(value, bool) or not isinstance(value, int):
if type(value) is not int and type(value) is not float:
value = self._serializer.dumps(value)
return self._compressor.compress(value)

Expand Down
43 changes: 43 additions & 0 deletions tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,31 @@ def patch_itersize_setting() -> Iterable[None]:


class TestDjangoValkeyCache:
def test_set_int(self, cache: ValkeyCache):
if isinstance(cache.client, herd.HerdClient):
pytest.skip("herd client's set method works differently")
cache.set("test_key", 1)
result = cache.get("test_key")
assert type(result) is int
# shard client doesn't have get_client()
if not isinstance(cache.client, ShardClient):
raw_client = cache.client._get_client(write=False, client=None)
else:
raw_client = cache.client.get_server(":1:test_key")
assert raw_client.get(":1:test_key") == b"1"

def test_set_float(self, cache: ValkeyCache):
if isinstance(cache.client, herd.HerdClient):
pytest.skip("herd client's set method works differently")
cache.set("test_key2", 1.1)
result = cache.get("test_key2")
assert type(result) is float
if not isinstance(cache.client, ShardClient):
raw_client = cache.client._get_client(write=False, client=None)
else:
raw_client = cache.client.get_server(":1:test_key2")
assert raw_client.get(":1:test_key2") == b"1.1"

def test_setnx(self, cache: ValkeyCache):
# we should ensure there is no test_key_nx in valkey
cache.delete("test_key_nx")
Expand Down Expand Up @@ -867,6 +892,24 @@ def test_sadd(self, cache: ValkeyCache):
assert cache.sadd("foo", "bar") == 1
assert cache.smembers("foo") == {"bar"}

def test_sadd_int(self, cache: ValkeyCache):
cache.sadd("foo", 1)
assert cache.smembers("foo") == {1}
if not isinstance(cache.client, ShardClient):
raw_client = cache.client._get_client(write=False, client=None)
else:
raw_client = cache.client.get_server(":1:foo")
assert raw_client.smembers(":1:foo") == [b"1"]

def test_sadd_float(self, cache: ValkeyCache):
cache.sadd("foo", 1.2)
assert cache.smembers("foo") == {1.2}
if not isinstance(cache.client, ShardClient):
raw_client = cache.client._get_client(write=False, client=None)
else:
raw_client = cache.client.get_server(":1:foo")
assert raw_client.smembers(":1:foo") == [b"1.2"]

def test_scard(self, cache: ValkeyCache):
cache.sadd("foo", "bar", "bar2")
assert cache.scard("foo") == 2
Expand Down
30 changes: 30 additions & 0 deletions tests/tests_async/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@ async def patch_itersize_setting() -> Iterable[None]:

@pytest.mark.asyncio(loop_scope="session")
class TestAsyncDjangoValkeyCache:
async def test_set_int(self, cache: AsyncValkeyCache):
if isinstance(cache.client, AsyncHerdClient):
pytest.skip("Herd client's set method works differently")
await cache.aset("test_key", 1)
result = await cache.aget("test_key")
assert type(result) is int
raw_client = await cache.client._get_client(write=False, client=None)
assert await raw_client.get(":1:test_key") == b"1"

async def test_set_float(self, cache: AsyncValkeyCache):
if isinstance(cache.client, AsyncHerdClient):
pytest.skip("Herd client's set method works differently")
await cache.aset("test_key2", 1.1)
result = await cache.aget("test_key2")
assert type(result) is float
raw_client = await cache.client._get_client(write=False, client=None)
assert await raw_client.get(":1:test_key2") == b"1.1"

async def test_setnx(self, cache: AsyncValkeyCache):
await cache.delete("test_key_nx")
res = await cache.get("test_key_nx")
Expand Down Expand Up @@ -895,6 +913,18 @@ async def test_sadd(self, cache: AsyncValkeyCache):
assert await cache.asadd("foo", "bar") == 1
assert await cache.asmembers("foo") == {"bar"}

async def test_sadd_int(self, cache: AsyncValkeyCache):
await cache.asadd("foo", 1)
assert await cache.asmembers("foo") == {1}
raw_client = await cache.client._get_client(write=False, client=None)
assert await raw_client.smembers(":1:foo") == [b"1"]

async def test_sadd_float(self, cache: AsyncValkeyCache):
await cache.asadd("foo", 1.2)
assert await cache.asmembers("foo") == {1.2}
raw_client = await cache.client._get_client(write=False, client=None)
assert await raw_client.smembers(":1:foo") == [b"1.2"]

async def test_scard(self, cache: AsyncValkeyCache):
await cache.asadd("foo", "bar", "bar2")
assert await cache.ascard("foo") == 2
Expand Down
Loading