Skip to content

Commit d97f56e

Browse files
committed
floats are no longer serialized to support atomic float operations
1 parent 18169f0 commit d97f56e

File tree

4 files changed

+87
-8
lines changed

4 files changed

+87
-8
lines changed

django_valkey/async_cache/client/default.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -403,12 +403,15 @@ async def clear(self, client: AValkey | Any | None = None) -> bool:
403403

404404
aclear = clear
405405

406-
async def decode(self, value) -> Any:
406+
async def decode(self, value: bytes) -> Any:
407407
"""
408408
Decode the given value.
409409
"""
410410
try:
411-
value = int(value)
411+
if value.isdigit():
412+
value = int(value)
413+
else:
414+
value = float(value)
412415
except (ValueError, TypeError):
413416
# Handle values that weren't compressed (small stuff)
414417
with suppress(CompressorError):
@@ -419,11 +422,11 @@ async def decode(self, value) -> Any:
419422

420423
adecode = decode
421424

422-
async def encode(self, value) -> bytes | int:
425+
async def encode(self, value) -> bytes | int | float:
423426
"""
424427
Encode the given value.
425428
"""
426-
if isinstance(value, bool) or not isinstance(value, int):
429+
if type(value) is not int and type(value) is not float:
427430
value = self._serializer.dumps(value)
428431
return self._compressor.compress(value)
429432

django_valkey/base_client.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -524,25 +524,28 @@ def clear(self, client: Backend | Any | None = None) -> bool:
524524
except _main_exceptions as e:
525525
raise ConnectionInterrupted(connection=client) from e
526526

527-
def decode(self, value: EncodableT) -> Any:
527+
def decode(self, value: bytes) -> Any:
528528
"""
529529
Decode the given value.
530530
"""
531531
try:
532-
value = int(value)
532+
if value.isdigit():
533+
value = int(value)
534+
else:
535+
value = float(value)
533536
except (ValueError, TypeError):
534537
# Handle little values, chosen to be not compressed
535538
with suppress(CompressorError):
536539
value = self._compressor.decompress(value)
537540
value = self._serializer.loads(value)
538541
return value
539542

540-
def encode(self, value: EncodableT) -> bytes | int:
543+
def encode(self, value: EncodableT) -> bytes | int | float:
541544
"""
542545
Encode the given value.
543546
"""
544547

545-
if isinstance(value, bool) or not isinstance(value, int):
548+
if type(value) is not int and type(value) is not float:
546549
value = self._serializer.dumps(value)
547550
return self._compressor.compress(value)
548551

tests/test_backend.py

+43
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,31 @@ def patch_itersize_setting() -> Iterable[None]:
3030

3131

3232
class TestDjangoValkeyCache:
33+
def test_set_int(self, cache: ValkeyCache):
34+
if isinstance(cache.client, herd.HerdClient):
35+
pytest.skip("herd client's set method works differently")
36+
cache.set("test_key", 1)
37+
result = cache.get("test_key")
38+
assert type(result) is int
39+
# shard client doesn't have get_client()
40+
if not isinstance(cache.client, ShardClient):
41+
raw_client = cache.client._get_client(write=False, client=None)
42+
else:
43+
raw_client = cache.client.get_server(":1:test_key")
44+
assert raw_client.get(":1:test_key") == b"1"
45+
46+
def test_set_float(self, cache: ValkeyCache):
47+
if isinstance(cache.client, herd.HerdClient):
48+
pytest.skip("herd client's set method works differently")
49+
cache.set("test_key2", 1.1)
50+
result = cache.get("test_key2")
51+
assert type(result) is float
52+
if not isinstance(cache.client, ShardClient):
53+
raw_client = cache.client._get_client(write=False, client=None)
54+
else:
55+
raw_client = cache.client.get_server(":1:test_key2")
56+
assert raw_client.get(":1:test_key2") == b"1.1"
57+
3358
def test_setnx(self, cache: ValkeyCache):
3459
# we should ensure there is no test_key_nx in valkey
3560
cache.delete("test_key_nx")
@@ -867,6 +892,24 @@ def test_sadd(self, cache: ValkeyCache):
867892
assert cache.sadd("foo", "bar") == 1
868893
assert cache.smembers("foo") == {"bar"}
869894

895+
def test_sadd_int(self, cache: ValkeyCache):
896+
cache.sadd("foo", 1)
897+
assert cache.smembers("foo") == {1}
898+
if not isinstance(cache.client, ShardClient):
899+
raw_client = cache.client._get_client(write=False, client=None)
900+
else:
901+
raw_client = cache.client.get_server(":1:foo")
902+
assert raw_client.smembers(":1:foo") == [b"1"]
903+
904+
def test_sadd_float(self, cache: ValkeyCache):
905+
cache.sadd("foo", 1.2)
906+
assert cache.smembers("foo") == {1.2}
907+
if not isinstance(cache.client, ShardClient):
908+
raw_client = cache.client._get_client(write=False, client=None)
909+
else:
910+
raw_client = cache.client.get_server(":1:foo")
911+
assert raw_client.smembers(":1:foo") == [b"1.2"]
912+
870913
def test_scard(self, cache: ValkeyCache):
871914
cache.sadd("foo", "bar", "bar2")
872915
assert cache.scard("foo") == 2

tests/tests_async/test_backend.py

+30
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,24 @@ async def patch_itersize_setting() -> Iterable[None]:
3131

3232
@pytest.mark.asyncio(loop_scope="session")
3333
class TestAsyncDjangoValkeyCache:
34+
async def test_set_int(self, cache: AsyncValkeyCache):
35+
if isinstance(cache.client, AsyncHerdClient):
36+
pytest.skip("Herd client's set method works differently")
37+
await cache.aset("test_key", 1)
38+
result = await cache.aget("test_key")
39+
assert type(result) is int
40+
raw_client = await cache.client._get_client(write=False, client=None)
41+
assert await raw_client.get(":1:test_key") == b"1"
42+
43+
async def test_set_float(self, cache: AsyncValkeyCache):
44+
if isinstance(cache.client, AsyncHerdClient):
45+
pytest.skip("Herd client's set method works differently")
46+
await cache.aset("test_key2", 1.1)
47+
result = await cache.aget("test_key2")
48+
assert type(result) is float
49+
raw_client = await cache.client._get_client(write=False, client=None)
50+
assert await raw_client.get(":1:test_key2") == b"1.1"
51+
3452
async def test_setnx(self, cache: AsyncValkeyCache):
3553
await cache.delete("test_key_nx")
3654
res = await cache.get("test_key_nx")
@@ -895,6 +913,18 @@ async def test_sadd(self, cache: AsyncValkeyCache):
895913
assert await cache.asadd("foo", "bar") == 1
896914
assert await cache.asmembers("foo") == {"bar"}
897915

916+
async def test_sadd_int(self, cache: AsyncValkeyCache):
917+
await cache.asadd("foo", 1)
918+
assert await cache.asmembers("foo") == {1}
919+
raw_client = await cache.client._get_client(write=False, client=None)
920+
assert await raw_client.smembers(":1:foo") == [b"1"]
921+
922+
async def test_sadd_float(self, cache: AsyncValkeyCache):
923+
await cache.asadd("foo", 1.2)
924+
assert await cache.asmembers("foo") == {1.2}
925+
raw_client = await cache.client._get_client(write=False, client=None)
926+
assert await raw_client.smembers(":1:foo") == [b"1.2"]
927+
898928
async def test_scard(self, cache: AsyncValkeyCache):
899929
await cache.asadd("foo", "bar", "bar2")
900930
assert await cache.ascard("foo") == 2

0 commit comments

Comments
 (0)