Opened 3 years ago

Last modified 3 years ago

#33361 closed Bug

Redis cache backend doesn't allow storing bool values — at Version 1

Reported by: Jeremy Lainé Owned by: nobody
Component: Core (Cache system) Version: 4.0
Severity: Release blocker Keywords:
Cc: Nick Pope, Daniyal Abbasi Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Mariusz Felisiak)

The following code raises an exception: redis.exceptions.DataError: Invalid input of type: 'bool'. Convert to a bytes, string, int or float first.

from django.core.cache import cache
cache.set("foo", True)

This contradicts the documentation which states that any data type supported by pickle can be stored to the cache.

The root cause seems to be because instances of int are special-cased and not send through pickle, but redis-py cannot send booleans to redis:

https://github.com/django/django/blob/2f73e5406d54cb8945e187eff302a3a3373350be/django/core/cache/backends/redis.py#L14

What was the rationale behind the int special-case? django-redis for instance consistently sends all data through pickle.

Change History (1)

comment:1 by Mariusz Felisiak, 3 years ago

Cc: Nick Pope Daniyal Abbasi added
Description: modified (diff)
Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

Thanks for report! It should be enough to special-case bool, e.g.

  • django/core/cache/backends/redis.py

    diff --git a/django/core/cache/backends/redis.py b/django/core/cache/backends/redis.py
    index 16556b1ded..bbb0e0320d 100644
    a b from django.utils.module_loading import import_string  
    1111
    1212class RedisSerializer(PickleSerializer):
    1313    def dumps(self, obj):
    14         if isinstance(obj, int):
     14        if isinstance(obj, int) and not isinstance(obj, bool):
    1515            return obj
    1616        return super().dumps(obj)
    1717

Would you like to prepare a patch?

What was the rationale behind the int special-case? django-redis for instance consistently sends all data through pickle.

We do this to have better atomicity of incr() and decr() operations (see discussion).

Note: See TracTickets for help on using tickets.
Back to Top