From 73978c95607f40f333ccfa3a9c202bde18e1d395 Mon Sep 17 00:00:00 2001 From: kazmiruk Date: Wed, 22 Apr 2015 13:12:12 +0700 Subject: [PATCH] change SortedDict to OrderedDict --- rest_framework/fields.py | 5 ++--- rest_framework/routers.py | 7 +++---- rest_framework/serializers.py | 27 +++++++++++++++------------ rest_framework/utils/encoders.py | 12 ++++++------ rest_framework/views.py | 4 ++-- 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index a2d2d5feb..aad49ed5c 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -22,7 +22,6 @@ from django.forms import widgets from django.utils import six, timezone from django.utils.encoding import is_protected_type from django.utils.translation import ugettext_lazy as _ -from django.utils.datastructures import SortedDict from django.utils.dateparse import parse_date, parse_datetime, parse_time from rest_framework import ISO_8601 from rest_framework.compat import ( @@ -225,7 +224,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 = collections.OrderedDict() for key, val in value.items(): ret[key] = self.to_native(val) return ret @@ -240,7 +239,7 @@ class Field(object): return {} def metadata(self): - metadata = SortedDict() + metadata = collections.OrderedDict() metadata['type'] = self.type_label metadata['required'] = getattr(self, 'required', False) optional_attrs = ['read_only', 'label', 'help_text', diff --git a/rest_framework/routers.py b/rest_framework/routers.py index 169e6e8bc..9937566d2 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -16,11 +16,10 @@ For example, you might have a `urls.py` that looks something like this: from __future__ import unicode_literals import itertools -from collections import namedtuple +from collections import namedtuple, OrderedDict from django.conf.urls import patterns, url from django.core.exceptions import ImproperlyConfigured from django.core.urlresolvers import NoReverseMatch -from django.utils.datastructures import SortedDict from rest_framework import views from rest_framework.response import Response from rest_framework.reverse import reverse @@ -278,7 +277,7 @@ class DefaultRouter(SimpleRouter): """ Return a view to use as the API root. """ - api_root_dict = SortedDict() + api_root_dict = OrderedDict() list_name = self.routes[0].name for prefix, viewset, basename in self.registry: api_root_dict[prefix] = list_name.format(basename=basename) @@ -287,7 +286,7 @@ class DefaultRouter(SimpleRouter): _ignore_model_permissions = True def get(self, request, *args, **kwargs): - ret = SortedDict() + ret = OrderedDict() for key, url_name in api_root_dict.items(): try: ret[key] = reverse( diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 7d85894f6..29187c92c 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -11,6 +11,7 @@ python primitives. response content is handled by parsers and renderers. """ from __future__ import unicode_literals +from collections import OrderedDict import copy import datetime import inspect @@ -21,7 +22,6 @@ from django.core.paginator import Page from django.db import models from django.forms import widgets from django.utils import six -from django.utils.datastructures import SortedDict from django.utils.functional import cached_property from django.core.exceptions import ObjectDoesNotExist from rest_framework.settings import api_settings @@ -106,7 +106,7 @@ class DictWithMetadata(dict): return dict(self) -class SortedDictWithMetadata(SortedDict): +class OrderedDictWithMetadata(OrderedDict): """ A sorted dict-like object, that can have additional properties attached. """ @@ -116,7 +116,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): @@ -152,7 +152,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): @@ -180,7 +180,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=False, @@ -229,7 +229,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) @@ -245,7 +245,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 @@ -606,7 +606,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) @@ -683,7 +683,7 @@ class ModelSerializer(Serializer): self.__class__.__name__ ) opts = cls._meta.concrete_model._meta - ret = SortedDict() + ret = OrderedDict() nested = bool(self.opts.depth) # Deal with adding the primary key field @@ -985,13 +985,16 @@ class ModelSerializer(Serializer): if field_name in attrs: m2m_data[field_name] = attrs.pop(field_name) - # Forward m2m relations - for field in meta.many_to_many + meta.virtual_fields: + def _inner_loop_code(field): if isinstance(field, GenericForeignKey): - continue + return if field.name in attrs: m2m_data[field.name] = attrs.pop(field.name) + # Forward m2m relations + _ = [_inner_loop_code(field) for field in meta.many_to_many] + _ = [_inner_loop_code(field) for field in meta.virtual_fields] + # Nested forward relations - These need to be marked so we can save # them before saving the parent model instance. for field_name in attrs.keys(): diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index 00ffdfbae..1e570cdde 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -2,12 +2,12 @@ Helper classes for parsers. """ from __future__ import unicode_literals +from collections import OrderedDict from django.utils import timezone from django.db.models.query import QuerySet -from django.utils.datastructures import SortedDict from django.utils.functional import Promise from rest_framework.compat import force_text -from rest_framework.serializers import DictWithMetadata, SortedDictWithMetadata +from rest_framework.serializers import DictWithMetadata, OrderedDictWithMetadata import datetime import decimal import types @@ -67,7 +67,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): @@ -81,7 +81,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) @@ -103,7 +103,7 @@ else: SafeDumper.represent_decimal ) SafeDumper.add_representer( - SortedDict, + OrderedDict, yaml.representer.SafeRepresenter.represent_dict ) SafeDumper.add_representer( @@ -111,7 +111,7 @@ else: yaml.representer.SafeRepresenter.represent_dict ) SafeDumper.add_representer( - SortedDictWithMetadata, + OrderedDictWithMetadata, yaml.representer.SafeRepresenter.represent_dict ) SafeDumper.add_representer( diff --git a/rest_framework/views.py b/rest_framework/views.py index 38346ab79..89b592177 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 @@ -421,7 +421,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]