Commit 8e35fc67 by Clinton Blackburn

Merge pull request #9328 from edx/clintonb/compressed-text-field-fix

Resolved decompression errors during tests
parents de15f8ec 207ce4ed
...@@ -4,12 +4,10 @@ import gzip ...@@ -4,12 +4,10 @@ import gzip
import logging import logging
from django.db import models from django.db import models
from django.db.models.signals import post_init
from django.utils.text import compress_string from django.utils.text import compress_string
from config_models.models import ConfigurationModel from config_models.models import ConfigurationModel
logger = logging.getLogger(__name__) # pylint: disable=invalid-name logger = logging.getLogger(__name__) # pylint: disable=invalid-name
...@@ -25,27 +23,31 @@ class RateLimitConfiguration(ConfigurationModel): ...@@ -25,27 +23,31 @@ class RateLimitConfiguration(ConfigurationModel):
pass pass
def uncompress_string(s): def decompress_string(value):
""" """
Helper function to reverse CompressedTextField.get_prep_value. Helper function to reverse CompressedTextField.get_prep_value.
""" """
try: try:
val = s.encode('utf').decode('base64') val = value.encode('utf').decode('base64')
zbuf = cStringIO.StringIO(val) zbuf = cStringIO.StringIO(val)
zfile = gzip.GzipFile(fileobj=zbuf) zfile = gzip.GzipFile(fileobj=zbuf)
ret = zfile.read() ret = zfile.read()
zfile.close() zfile.close()
except Exception as e: except Exception as e:
logger.error('String decompression failed. There may be corrupted data in the database: %s', e) logger.error('String decompression failed. There may be corrupted data in the database: %s', e)
ret = s ret = value
return ret return ret
class CompressedTextField(models.TextField): class CompressedTextField(models.TextField):
"""transparently compress data before hitting the db and uncompress after fetching""" """ TextField that transparently compresses data when saving to the database, and decompresses the data
when retrieving it from the database. """
__metaclass__ = models.SubfieldBase
def get_prep_value(self, value): def get_prep_value(self, value):
""" Compress the text data. """
if value is not None: if value is not None:
if isinstance(value, unicode): if isinstance(value, unicode):
value = value.encode('utf8') value = value.encode('utf8')
...@@ -53,28 +55,12 @@ class CompressedTextField(models.TextField): ...@@ -53,28 +55,12 @@ class CompressedTextField(models.TextField):
value = value.encode('base64').decode('utf8') value = value.encode('base64').decode('utf8')
return value return value
def post_init(self, instance=None, **kwargs): # pylint: disable=unused-argument def to_python(self, value):
value = self._get_val_from_obj(instance) """ Decompresses the value from the database. """
if value: if isinstance(value, unicode):
setattr(instance, self.attname, value) value = decompress_string(value)
def contribute_to_class(self, cls, name):
super(CompressedTextField, self).contribute_to_class(cls, name)
post_init.connect(self.post_init, sender=cls)
def _get_val_from_obj(self, obj):
if obj:
value = uncompress_string(getattr(obj, self.attname))
if value is not None:
try:
value = value.decode('utf8')
except UnicodeDecodeError:
pass
return value return value
else:
return self.get_default()
else:
return self.get_default()
def south_field_triple(self): def south_field_triple(self):
"""Returns a suitable description of this field for South.""" """Returns a suitable description of this field for South."""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment