From d9d4c4353edca584b5227431d082e649f5652ed0 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Wed, 26 Mar 2014 12:05:32 +0100 Subject: [PATCH] Fix deprecation warnings (replace SortedDict by OrderedDict) --- rest_framework/fields.py | 6 ++--- rest_framework/serializers.py | 33 ++++++++++++------------- rest_framework/tests/test_fields.py | 4 +-- rest_framework/tests/test_serializer.py | 6 ++--- rest_framework/utils/encoders.py | 12 ++++----- rest_framework/views.py | 4 +-- 6 files changed, 32 insertions(+), 33 deletions(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 2da895500..16035062d 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -10,6 +10,7 @@ import datetime import inspect import re import warnings +from collections import OrderedDict from decimal import Decimal, DecimalException from django import forms from django.core import validators @@ -20,7 +21,6 @@ from django.http import QueryDict from django.forms import widgets from django.utils.encoding import is_protected_type from django.utils.translation import ugettext_lazy as _ -from django.utils.datastructures import SortedDict from rest_framework import ISO_8601 from rest_framework.compat import ( timezone, parse_date, parse_datetime, parse_time, BytesIO, six, smart_text, @@ -220,7 +220,7 @@ class Field(object): return [self.to_native(item) for item in value] elif isinstance(value, dict): # Make sure we preserve field ordering, if it exists - ret = SortedDict() + ret = OrderedDict() for key, val in value.items(): ret[key] = self.to_native(val) return ret @@ -235,7 +235,7 @@ class Field(object): return {} def metadata(self): - metadata = SortedDict() + metadata = OrderedDict() metadata['type'] = self.type_label metadata['required'] = getattr(self, 'required', False) optional_attrs = ['read_only', 'label', 'help_text', diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 87d20cfce..db1bc4fd6 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -20,9 +20,8 @@ from django.contrib.contenttypes.generic import GenericForeignKey from django.core.paginator import Page from django.db import models from django.forms import widgets -from django.utils.datastructures import SortedDict from django.core.exceptions import ObjectDoesNotExist -from rest_framework.compat import get_concrete_model, six +from rest_framework.compat import get_concrete_model, OrderedDict, six from rest_framework.settings import api_settings @@ -105,9 +104,9 @@ class DictWithMetadata(dict): return dict(self) -class SortedDictWithMetadata(SortedDict): +class OrderedDictWithMetadata(OrderedDict): """ - A sorted dict-like object, that can have additional properties attached. + An ordered dict-like object, that can have additional properties attached. """ def __getstate__(self): """ @@ -115,7 +114,7 @@ class SortedDictWithMetadata(SortedDict): 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__ + return OrderedDict(self).__dict__ def _is_protected_type(obj): @@ -151,7 +150,7 @@ def _get_declared_fields(bases, attrs): if hasattr(base, 'base_fields'): fields = list(base.base_fields.items()) + fields - return SortedDict(fields) + return OrderedDict(fields) class SerializerMetaclass(type): @@ -179,7 +178,7 @@ class BaseSerializer(WritableField): pass _options_class = SerializerOptions - _dict_class = SortedDictWithMetadata + _dict_class = OrderedDictWithMetadata def __init__(self, instance=None, data=None, files=None, context=None, partial=False, many=None, @@ -225,7 +224,7 @@ class BaseSerializer(WritableField): This will be the set of any explicitly declared fields, plus the set of fields returned by get_default_fields(). """ - ret = SortedDict() + ret = OrderedDict() # Get the explicitly declared fields base_fields = copy.deepcopy(self.base_fields) @@ -241,7 +240,7 @@ class BaseSerializer(WritableField): # If 'fields' is specified, use those fields, in that order. if self.opts.fields: assert isinstance(self.opts.fields, (list, tuple)), '`fields` must be a list or tuple' - new = SortedDict() + new = OrderedDict() for key in self.opts.fields: new[key] = ret[key] ret = new @@ -605,7 +604,7 @@ class BaseSerializer(WritableField): Useful for things like responding to OPTIONS requests, or generating API schemas for auto-documentation. """ - return SortedDict( + return OrderedDict( [(field_name, field.metadata()) for field_name, field in six.iteritems(self.fields)] ) @@ -664,7 +663,7 @@ class ModelSerializer(Serializer): assert cls is not None, \ "Serializer class '%s' is missing 'model' Meta option" % self.__class__.__name__ opts = get_concrete_model(cls)._meta - ret = SortedDict() + ret = OrderedDict() nested = bool(self.opts.depth) # Deal with adding the primary key field @@ -759,9 +758,9 @@ class ModelSerializer(Serializer): field.read_only = True ret[accessor_name] = field - + # Ensure that 'read_only_fields' is an iterable - assert isinstance(self.opts.read_only_fields, (list, tuple)), '`read_only_fields` must be a list or tuple' + assert isinstance(self.opts.read_only_fields, (list, tuple)), '`read_only_fields` must be a list or tuple' # Add the `read_only` flag to any fields that have been specified # in the `read_only_fields` option @@ -776,10 +775,10 @@ class ModelSerializer(Serializer): "on serializer '%s'." % (field_name, self.__class__.__name__)) ret[field_name].read_only = True - + # Ensure that 'write_only_fields' is an iterable - assert isinstance(self.opts.write_only_fields, (list, tuple)), '`write_only_fields` must be a list or tuple' - + assert isinstance(self.opts.write_only_fields, (list, tuple)), '`write_only_fields` must be a list or tuple' + for field_name in self.opts.write_only_fields: assert field_name not in self.base_fields.keys(), ( "field '%s' on serializer '%s' specified in " @@ -790,7 +789,7 @@ class ModelSerializer(Serializer): "Non-existant field '%s' specified in `write_only_fields` " "on serializer '%s'." % (field_name, self.__class__.__name__)) - ret[field_name].write_only = True + ret[field_name].write_only = True return ret diff --git a/rest_framework/tests/test_fields.py b/rest_framework/tests/test_fields.py index b04b947f2..2b2417fb6 100644 --- a/rest_framework/tests/test_fields.py +++ b/rest_framework/tests/test_fields.py @@ -10,8 +10,8 @@ from uuid import uuid4 from django.core import validators from django.db import models from django.test import TestCase -from django.utils.datastructures import SortedDict from rest_framework import serializers +from rest_framework.compat import OrderedDict from rest_framework.tests.models import RESTFrameworkModel @@ -95,7 +95,7 @@ class BasicFieldTests(TestCase): Field should preserve dictionary ordering, if it exists. See: https://github.com/tomchristie/django-rest-framework/issues/832 """ - ret = SortedDict() + ret = OrderedDict() ret['c'] = 1 ret['b'] = 1 ret['a'] = 1 diff --git a/rest_framework/tests/test_serializer.py b/rest_framework/tests/test_serializer.py index e688c8239..30a29ba74 100644 --- a/rest_framework/tests/test_serializer.py +++ b/rest_framework/tests/test_serializer.py @@ -1271,7 +1271,7 @@ class SerializerPickleTests(TestCase): def test_pickle_inner_serializer(self): """ - Test pickling a serializer whose resulting .data (a SortedDictWithMetadata) will + Test pickling a serializer whose resulting .data (a OrderedDictWithMetadata) will have unpickleable meta data--in order to make sure metadata doesn't get pulled into the pickle. See DictWithMetadata.__getstate__ """ @@ -1286,13 +1286,13 @@ class SerializerPickleTests(TestCase): Regression test for #645. """ data = serializers.DictWithMetadata({1: 1}) - self.assertEqual(data.__getstate__(), serializers.SortedDict({1: 1})) + self.assertEqual(data.__getstate__(), serializers.OrderedDict({1: 1})) def test_serializer_data_is_pickleable(self): """ Another regression test for #645. """ - data = serializers.SortedDictWithMetadata({1: 1}) + data = serializers.OrderedDictWithMetadata({1: 1}) repr(pickle.loads(pickle.dumps(data, 0))) diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index e5fa41947..e0ff53780 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -2,11 +2,11 @@ Helper classes for parsers. """ from __future__ import unicode_literals +from collections import OrderedDict from django.db.models.query import QuerySet -from django.utils.datastructures import SortedDict from django.utils.functional import Promise from rest_framework.compat import timezone, force_text -from rest_framework.serializers import DictWithMetadata, SortedDictWithMetadata +from rest_framework.serializers import DictWithMetadata, OrderedDictWithMetadata import datetime import decimal import types @@ -66,7 +66,7 @@ else: class SafeDumper(yaml.SafeDumper): """ Handles decimals as strings. - Handles SortedDicts as usual dicts, but preserves field order, rather + Handles OrderedDicts as usual dicts, but preserves field order, rather than the usual behaviour of sorting the keys. """ def represent_decimal(self, data): @@ -80,7 +80,7 @@ else: best_style = True if hasattr(mapping, 'items'): mapping = list(mapping.items()) - if not isinstance(mapping, SortedDict): + if not isinstance(mapping, OrderedDict): mapping.sort() for item_key, item_value in mapping: node_key = self.represent_data(item_key) @@ -100,11 +100,11 @@ else: SafeDumper.add_representer(decimal.Decimal, SafeDumper.represent_decimal) - SafeDumper.add_representer(SortedDict, + SafeDumper.add_representer(OrderedDict, yaml.representer.SafeRepresenter.represent_dict) SafeDumper.add_representer(DictWithMetadata, yaml.representer.SafeRepresenter.represent_dict) - SafeDumper.add_representer(SortedDictWithMetadata, + SafeDumper.add_representer(OrderedDictWithMetadata, yaml.representer.SafeRepresenter.represent_dict) SafeDumper.add_representer(types.GeneratorType, yaml.representer.SafeRepresenter.represent_list) diff --git a/rest_framework/views.py b/rest_framework/views.py index a2668f2c0..9d96b8014 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -3,9 +3,9 @@ Provides an APIView class that is the base of all views in REST framework. """ from __future__ import unicode_literals +from collections import OrderedDict from django.core.exceptions import PermissionDenied from django.http import Http404 -from django.utils.datastructures import SortedDict from django.views.decorators.csrf import csrf_exempt from rest_framework import status, exceptions from rest_framework.compat import smart_text, HttpResponseBase, View @@ -418,7 +418,7 @@ class APIView(View): # By default we can't provide any form-like information, however the # generic views override this implementation and add additional # information for POST and PUT methods, based on the serializer. - ret = SortedDict() + ret = OrderedDict() ret['name'] = self.get_view_name() ret['description'] = self.get_view_description() ret['renders'] = [renderer.media_type for renderer in self.renderer_classes]