Opened 4 years ago

Last modified 4 years ago

#31140 closed Bug

Caching of dict containing django.utils.safestring.SafeText objects fails with bmemcached. — at Version 1

Reported by: Hugo Rodger-Brown Owned by: nobody
Component: Core (Cache system) Version: 2.2
Severity: Normal Keywords: cache bmemcached
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Hugo Rodger-Brown)

Not sure if this is a Django issue per se. but we have recently started having an issue where cache.set is failing where we have certain SafeText objects inside a dict. (Issue has already

The underlying exception is raised within bmemcached, but posting here in case someone else has had a similar issue, and any insight.


Expected behaviour - object can be cached:

>>> from django.utils.safestring import SafeString
>>> from django.core.cache import cache
>>> cache.set("test", SafeString("foo"))
>>> cache.set("test", SafeString("£"))

Actual outcome - cache.set fails with a recursion error when the value being stored is a dict that contains a SafeText value.

>>> from django.utils.safestring import SafeString
>>> from django.core.cache import cache
>>> cache.set("test", {"foo": SafeString("£")})
Traceback (most recent call last):
  File "/python3.7/site-packages/django/core/cache/backends/memcached.py", line 78, in set
    if not self._cache.set(key, value, self.get_backend_timeout(timeout)):
  File "/python3.7/site-packages/bmemcached/client/replicating.py", line 112, in set
    returns.append(server.set(key, value, time, compress_level=compress_level))
  File "/python3.7/site-packages/bmemcached/protocol.py", line 604, in set
    return self._set_add_replace('set', key, value, time, compress_level=compress_level)
  File "/python3.7/site-packages/bmemcached/protocol.py", line 561, in _set_add_replace
    flags, value = self.serialize(value, compress_level=compress_level)
  File "/python3.7/site-packages/bmemcached/protocol.py", line 347, in serialize
    pickler.dump(value)
  File "/python3.7/copyreg.py", line 66, in _reduce_ex
    state = base(self)
RecursionError: maximum recursion depth exceeded while getting the str of an object

Running on Python 3.7, Django 2.2

Configuration:

CACHES = {
    "default": {
        "BACKEND": "django_bmemcached.memcached.BMemcached",
        "BINARY": True,
        "OPTIONS": {
            "no_block": True,
            "tcp_nodelay": True,
            "tcp_keepalive": True,
            "remove_failed": 4,
            "retry_timeout": 2,
            "dead_timeout": 10,
            "_poll_timeout": 2000,
        },
    },
}

Change History (1)

comment:1 by Hugo Rodger-Brown, 4 years ago

Description: modified (diff)

Can't be sure, but I think it's the internal implementation of SafeText and how bmemcached is serializing that is causing the problem: https://github.com/django/django/blob/master/django/utils/safestring.py#L36-L37

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