diff --git a/rest_framework/compat.py b/rest_framework/compat.py index fa0f0bfb1..8979339c1 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -265,3 +265,30 @@ except ImportError: klass.__unicode__ = klass.__str__ klass.__str__ = lambda self: self.__unicode__().encode('utf-8') return klass + +""" +SortedDict deprecated since django 1.8. There is collections.OrderedDict +which available since python 2.7 and python 3.1. There are no need of other +checks because of django 1.7+ requires python 2.7+ +""" +try: + from collections import OrderedDict as SortedDict +except ImportError: + from django.utils.datastructures import SortedDict + +""" +GenericForeignKey moves from generic to fields in django 1.9 and in 1.8 shows +deprecation warnings +""" +if django.VERSION >= (1, 8): + from django.contrib.contenttypes.fields import GenericForeignKey +else: + from django.contrib.contenttypes.generic import GenericForeignKey + +""" +django.utils.importlib is deprecated since django 1.8 +""" +try: + import importlib +except ImportError: + from django.utils import importlib diff --git a/rest_framework/fields.py b/rest_framework/fields.py index a2d2d5feb..d310c5df3 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -22,11 +22,10 @@ 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 ( - BytesIO, smart_text, + BytesIO, smart_text, SortedDict, force_text, is_non_str_iterable ) from rest_framework.settings import api_settings diff --git a/rest_framework/routers.py b/rest_framework/routers.py index 169e6e8bc..9e5813b39 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -20,8 +20,8 @@ from collections import namedtuple 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.compat import SortedDict from rest_framework.response import Response from rest_framework.reverse import reverse from rest_framework.urlpatterns import format_suffix_patterns diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 7d85894f6..0ce54731d 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -16,14 +16,13 @@ import datetime import inspect import types from decimal import Decimal -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 import six -from django.utils.datastructures import SortedDict from django.utils.functional import cached_property from django.core.exceptions import ObjectDoesNotExist +from rest_framework.compat import SortedDict, GenericForeignKey from rest_framework.settings import api_settings @@ -110,9 +109,17 @@ class SortedDictWithMetadata(SortedDict): """ A sorted dict-like object, that can have additional properties attached. """ + def __reduce__(self): + """ + Used by pickle (e.g., caching) if OrderedDict is used instead of SortedDict + Overriden to remove the metadata from the dict, since it shouldn't be + pickle and may in some instances be unpickleable. + """ + return self.__class__, (SortedDict(self), ) + def __getstate__(self): """ - Used by pickle (e.g., caching). + Used by pickle (e.g., caching) in SortedDict Overriden to remove the metadata from the dict, since it shouldn't be pickle and may in some instances be unpickleable. """ diff --git a/rest_framework/settings.py b/rest_framework/settings.py index 644751f87..e77ec754f 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -19,8 +19,9 @@ back to the defaults. """ from __future__ import unicode_literals from django.conf import settings -from django.utils import importlib, six +from django.utils import six from rest_framework import ISO_8601 +from rest_framework.compat import importlib USER_SETTINGS = getattr(settings, 'REST_FRAMEWORK', None) diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index 00ffdfbae..813108b77 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -4,9 +4,8 @@ Helper classes for parsers. from __future__ import unicode_literals 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.compat import force_text, SortedDict from rest_framework.serializers import DictWithMetadata, SortedDictWithMetadata import datetime import decimal diff --git a/rest_framework/views.py b/rest_framework/views.py index 38346ab79..fb30775b1 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -5,10 +5,9 @@ from __future__ import unicode_literals 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 +from rest_framework.compat import smart_text, HttpResponseBase, SortedDict, View from rest_framework.request import Request from rest_framework.response import Response from rest_framework.settings import api_settings diff --git a/tests/test_fields.py b/tests/test_fields.py index 0ddbe48b5..058ad7035 100644 --- a/tests/test_fields.py +++ b/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 SortedDict from tests.models import RESTFrameworkModel