Check for collection.Mapping instead of dict

issue #4901
This commit is contained in:
Isaac Stone 2017-02-19 13:00:41 -08:00
parent 300e46a9e5
commit 289e1e440e
2 changed files with 36 additions and 5 deletions

View File

@ -15,7 +15,7 @@ from __future__ import unicode_literals
import copy
import inspect
import traceback
from collections import OrderedDict
from collections import Mapping, OrderedDict
from django.core.exceptions import ValidationError as DjangoValidationError
from django.core.exceptions import ImproperlyConfigured
@ -326,11 +326,11 @@ def as_serializer_error(exc):
else:
detail = exc.detail
if isinstance(detail, dict):
if isinstance(detail, Mapping):
# If errors may be a dict we use the standard {key: list of values}.
# Here we ensure that all the values are *lists* of errors.
return {
key: value if isinstance(value, (list, dict)) else [value]
key: value if isinstance(value, (list, Mapping)) else [value]
for key, value in detail.items()
}
elif isinstance(detail, list):
@ -442,7 +442,7 @@ class Serializer(BaseSerializer):
"""
Dict of native values <- Dict of primitive datatypes.
"""
if not isinstance(data, dict):
if not isinstance(data, Mapping):
message = self.error_messages['invalid'].format(
datatype=type(data).__name__
)

View File

@ -4,9 +4,10 @@ from __future__ import unicode_literals
import inspect
import pickle
import re
import unittest
from collections import Mapping
import pytest
from django.db import models
from rest_framework import fields, relations, serializers
@ -15,6 +16,11 @@ from rest_framework.fields import Field
from .utils import MockObject
try:
from collections import ChainMap
except ImportError:
ChainMap = False
# Test serializer fields imports.
# -------------------------------
@ -113,6 +119,31 @@ class TestSerializer:
assert not serializer.is_valid()
assert serializer.errors == {'non_field_errors': ['No data provided']}
@unittest.skipUnless(ChainMap, 'requires python 3.3')
def test_serialize_chainmap(self):
data = ChainMap({'char': 'abc'}, {'integer': 123})
serializer = self.Serializer(data=data)
assert serializer.is_valid()
assert serializer.validated_data == {'char': 'abc', 'integer': 123}
assert serializer.errors == {}
def test_serialize_custom_mapping(self):
class SinglePurposeMapping(Mapping):
def __getitem__(self, key):
return 'abc' if key == 'char' else 123
def __iter__(self):
yield 'char'
yield 'integer'
def __len__(self):
return 2
serializer = self.Serializer(data=SinglePurposeMapping())
assert serializer.is_valid()
assert serializer.validated_data == {'char': 'abc', 'integer': 123}
assert serializer.errors == {}
class TestValidateMethod:
def test_non_field_error_validate_method(self):