Describe the bug
When trying to update our app from redis-py==3.5.3 to redis-py==4.2.0 we stumbled onto a problem. While it only started breaking with the new redis-py version, I believe it's actually a bug here in django-redis. This also happens with any version of redis-py>=4.0.2.
I'm happy to provide a PR if this is seen as a bug.
I see in DefaultClient.encode that we have special behaviour where everything that isinstance(obj, int) will not be passed through the serializer (pickle in our case) or the compressor. In DefaultClient.decode we just try int(value) to bypass deserialization and decompression for these.
The problem is: for models.IntegerChoices and an integer-enum (see example) instance(enum_variant, int) is True. This then leads to a text representation of the enum being stored in redis (something like <Values1.CHOICE_1: 1>), which of course cannot be converted back to an integer via int(). And also it cannot be decoded with pickle.
The diff between 3.5.3 and 4.0.2 is huge ( redis/redis-py@3.5.3...v4.0.2 ) and I couldn't directly see why this worked before, but I believe our encode/decode mapping is in the wrong here.
To Reproduce
This is with a default django-redis setup.
With models.IntegerChoices:
from django.core.cache import cache
from django.db import models
class Values1(models.IntegerChoices):
CHOICE_1 = 1
CHOICE_2 = 2
cache.set("key", Values1.CHOICE_1)
# this breaks with :
# UnpicklingError: invalid load key, '<'.
cache.get("key")
With a python standard int-enum:
import enum
from django.core.cache import cache
class Values2(int, enum.Enum):
SOMETHING_1 = 1
SOMETHING_2 = 2
cache.set("key", Values2.SOMETHING_1)
# this breaks with :
# UnpicklingError: invalid load key, '<'.
cache.get("key")
Expected behavior
I would expect the enum-variant to be cached and returned as enum-variant.
Stack trace
I don't think we need this, I'm happy to provide one if needed.
Environment (please complete the following information):
- Python version: 3.9.12
- Django Redis Version: 5.2.0
- Django Version: 3.2.12
- Redis Version: [e.g. 2.5.0]
- redis-py Version: 4.2.0
Additional context
Add any other context about the problem here.
Describe the bug
When trying to update our app from
redis-py==3.5.3toredis-py==4.2.0we stumbled onto a problem. While it only started breaking with the new redis-py version, I believe it's actually a bug here indjango-redis. This also happens with any version ofredis-py>=4.0.2.I'm happy to provide a PR if this is seen as a bug.
I see in
DefaultClient.encodethat we have special behaviour where everything thatisinstance(obj, int)will not be passed through the serializer (pickle in our case) or the compressor. InDefaultClient.decodewe just tryint(value)to bypass deserialization and decompression for these.The problem is: for
models.IntegerChoicesand an integer-enum (see example)instance(enum_variant, int) is True. This then leads to a text representation of the enum being stored in redis (something like<Values1.CHOICE_1: 1>), which of course cannot be converted back to an integer viaint(). And also it cannot be decoded with pickle.The diff between 3.5.3 and 4.0.2 is huge ( redis/redis-py@3.5.3...v4.0.2 ) and I couldn't directly see why this worked before, but I believe our encode/decode mapping is in the wrong here.
To Reproduce
This is with a default django-redis setup.
With
models.IntegerChoices:With a python standard int-enum:
Expected behavior
I would expect the enum-variant to be cached and returned as enum-variant.
Stack trace
I don't think we need this, I'm happy to provide one if needed.
Environment (please complete the following information):
Additional context
Add any other context about the problem here.