Fix and test for #645

Yuck, pickle is weird.  Closes #645.
This commit is contained in:
Tom Christie 2013-02-22 22:59:55 +00:00
parent d62e4a7aa5
commit e1f0001f92
2 changed files with 22 additions and 13 deletions

View File

@ -28,20 +28,23 @@ class DictWithMetadata(dict):
def __getstate__(self):
"""
Used by pickle (e.g., caching).
Overriden to remove metadata from the dict, since it shouldn't be pickled
and may in some instances be unpickleable.
Overriden to remove the metadata from the dict, since it shouldn't be
pickled and may in some instances be unpickleable.
"""
# return an instance of the first dict in MRO that isn't a DictWithMetadata
for base in self.__class__.__mro__:
if not issubclass(base, DictWithMetadata) and issubclass(base, dict):
return base(self)
return dict(self)
class SortedDictWithMetadata(SortedDict, DictWithMetadata):
class SortedDictWithMetadata(SortedDict):
"""
A sorted dict-like object, that can have additional properties attached.
"""
pass
def __getstate__(self):
"""
Used by pickle (e.g., caching).
Overriden to remove the metadata from the dict, since it shouldn't be
pickle and may in some instances be unpickleable.
"""
return SortedDict(self).__dict__
def _is_protected_type(obj):

View File

@ -951,15 +951,21 @@ class SerializerPickleTests(TestCase):
class Meta:
model = Person
fields = ('name', 'age')
pickle.dumps(InnerPersonSerializer(Person(name="Noah", age=950)).data)
pickle.dumps(InnerPersonSerializer(Person(name="Noah", age=950)).data, 0)
def test_getstate_method_should_not_return_none(self):
"""
Regression test for
https://github.com/tomchristie/django-rest-framework/issues/645
Regression test for #645.
"""
d = serializers.DictWithMetadata({1: 1})
self.assertEqual(d.__getstate__(), serializers.SortedDict({1: 1}))
data = serializers.DictWithMetadata({1: 1})
self.assertEqual(data.__getstate__(), serializers.SortedDict({1: 1}))
def test_serializer_data_is_pickleable(self):
"""
Another regression test for #645.
"""
data = serializers.SortedDictWithMetadata({1: 1})
repr(pickle.loads(pickle.dumps(data, 0)))
class DepthTest(TestCase):