diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 971dee9cf..17814136b 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -33,6 +33,14 @@ def unicode_to_repr(value): return value +def total_seconds(timedelta): + # TimeDelta.total_seconds() is only available in Python 2.7 + if hasattr(timedelta, 'total_seconds'): + return timedelta.total_seconds() + else: + return (timedelta.days * 86400.0) + float(timedelta.seconds) + (timedelta.microseconds / 1000000.0) + + # OrderedDict only available in Python 2.7. # This will always be the case in Django 1.7 and above, as these versions # no longer support Python 2.6. diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 634338e9e..ba6c9cc15 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -46,7 +46,7 @@ class BaseRenderer(object): render_style = 'text' def render(self, data, accepted_media_type=None, renderer_context=None): - raise NotImplemented('Renderer class requires .render() to be implemented') + raise NotImplementedError('Renderer class requires .render() to be implemented') class JSONRenderer(BaseRenderer): diff --git a/rest_framework/routers.py b/rest_framework/routers.py index 61f3ccab0..827da0340 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -65,13 +65,13 @@ class BaseRouter(object): If `base_name` is not specified, attempt to automatically determine it from the viewset. """ - raise NotImplemented('get_default_base_name must be overridden') + raise NotImplementedError('get_default_base_name must be overridden') def get_urls(self): """ Return a list of URL patterns, given the registered viewsets. """ - raise NotImplemented('get_urls must be overridden') + raise NotImplementedError('get_urls must be overridden') @property def urls(self): diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index 73cbe5d8a..bf7532711 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -6,12 +6,13 @@ from django.db.models.query import QuerySet from django.utils import six, timezone from django.utils.encoding import force_text from django.utils.functional import Promise -from rest_framework.compat import OrderedDict +from rest_framework.compat import OrderedDict, total_seconds from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList import datetime import decimal import types import json +import uuid class JSONEncoder(json.JSONEncoder): @@ -41,10 +42,12 @@ class JSONEncoder(json.JSONEncoder): representation = representation[:12] return representation elif isinstance(obj, datetime.timedelta): - return six.text_type(obj.total_seconds()) + return six.text_type(total_seconds(obj)) elif isinstance(obj, decimal.Decimal): # Serializers will coerce decimals to strings by default. return float(obj) + elif isinstance(obj, uuid.UUID): + return six.text_type(obj) elif isinstance(obj, QuerySet): return tuple(obj) elif hasattr(obj, 'tolist'): diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py index 65a04d06b..f99606039 100644 --- a/rest_framework/utils/serializer_helpers.py +++ b/rest_framework/utils/serializer_helpers.py @@ -16,6 +16,9 @@ class ReturnDict(OrderedDict): def copy(self): return ReturnDict(self, serializer=self.serializer) + def __repr__(self): + return dict.__repr__(self) + class ReturnList(list): """ @@ -27,6 +30,9 @@ class ReturnList(list): self.serializer = kwargs.pop('serializer') super(ReturnList, self).__init__(*args, **kwargs) + def __repr__(self): + return list.__repr__(self) + class BoundField(object): """