﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
9180	Low-level cache interface incorrectly tries to typecast bytestring	Paul Smith	nobody	"The low-level Django cache API encodes basestrings as UTF-8 when {{{set}}}ting, and decodes basestrings as Unicode when {{{get}}}ting.

If you're trying to store a string of bytes in the cache -- for instance, the raw bytes of an image -- the set operation will possibly modify the data by encoding it, and the get operation will potentially raise a !DjangoUnicodeDecodeError if the codec can't decode bytes in the string.

{{{
#!python
from django.core.cache import cache
from django.utils.encoding import DjangoUnicodeDecodeError

# The simplest possible GIF: a 43-byte, 1x1-pixel transparent image
EMPTY_GIF_BYTES = 'GIF89a\x01\x00\x01\x00\xf0\x00\x00\xb0\x8cZ\x00\x00\x00!\xf9\x04\x00\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;'

cache.set('empty_gif', EMPTY_GIF_BYTES)

try:
    cache.get('empty_gif')
except DjangoUnicodeDecodeError:
    print 'Tried to decode GIF bytestring as a Unicode string'
else:
    print 'Got the raw GIF bytestring'
}}}

A workaround is to create a one-tuple from the bytestring when storing, and when retrieving, returning the single element from the tuple.

{{{
#!python

def raw_cache_set(key, value, timeout_seconds=None):
    cache.set(key, (value,), timeout_seconds=timeout_seconds)

def raw_cache_get(key):
    value = cache.get(key)
    if value is not None:
        return value[0]

raw_cache_set('empty_gif', EMPTY_GIF_BYTES)

assert raw_cache_get('empty_gif') == EMPTY_GIF_BYTES
}}}

One possible fix would be to expose a {{{raw}}} keyword argument boolean to {{{cache.get}}}, {{{cache.set}}}, {{{cache.add}}}, {{{cache.get_many}}} that would conditionally skip any {{{smart_unicode}}} or other encoding/decoding logic when storing or retrieving from the cache.
"		closed	Core (Cache system)	1.1		duplicate		django.9180@… Gonzalo Saavedra lvscar Oliver Beattie	Ready for checkin	1	0	0	0	0	0
