From 0234b6161bf83006e9dd278b3299548239f145d6 Mon Sep 17 00:00:00 2001 From: Juan Riaza Date: Sat, 5 Jan 2013 23:28:15 +0100 Subject: [PATCH] include dateutil and some cleaning --- optionals.txt | 3 ++- rest_framework/compat.py | 6 ++++++ rest_framework/parsers.py | 23 +++++++++++----------- rest_framework/renderers.py | 3 +-- rest_framework/utils/encoders.py | 33 ++++++++++---------------------- 5 files changed, 30 insertions(+), 38 deletions(-) diff --git a/optionals.txt b/optionals.txt index a4f4db8de..338b300fe 100644 --- a/optionals.txt +++ b/optionals.txt @@ -1,4 +1,5 @@ markdown>=2.1.0 PyYAML>=3.10 django-filter>=0.5.4 -msgpack-python==0.3.0dev1 +msgpack-python>=0.2.4 +python-dateutil==2.1 diff --git a/rest_framework/compat.py b/rest_framework/compat.py index df042c2ac..89e438424 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -397,6 +397,12 @@ try: except ImportError: msgpack = None +# dateutil is optional +try: + from dateutil import parser as dateutil_parser +except ImportError: + dateutil_parser = None + # xml.etree.parse only throws ParseError for python >= 2.7 try: diff --git a/rest_framework/parsers.py b/rest_framework/parsers.py index b16df4f11..801a9229b 100644 --- a/rest_framework/parsers.py +++ b/rest_framework/parsers.py @@ -8,7 +8,7 @@ on the request, such as form content or json encoded data. from django.http import QueryDict from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser from django.http.multipartparser import MultiPartParserError -from rest_framework.compat import yaml, msgpack, ETParseError +from rest_framework.compat import yaml, msgpack, dateutil_parser, ETParseError from rest_framework.exceptions import ParseError from xml.etree import ElementTree as ET from xml.parsers.expat import ExpatError @@ -101,18 +101,17 @@ class MessagePackParser(BaseParser): except Exception, exc: raise ParseError('MessagePack parse error - %s' % unicode(exc)) - def _decode_object(self, o): - # TODO(juanriaza): decode objects - if b'__datetime__' in o: - return o['as_str'] - elif b'__date__' in o: - return o['as_str'] - elif b'__time__' in o: - return o['as_str'] - elif b'__decimal__' in o: - return o['as_str'] + def _decode_object(self, obj): + if '__datetime__' in obj: + return dateutil_parser.parse(obj['as_str']) + elif b'__date__' in obj: + return dateutil_parser.parse(obj['as_str']).date() + elif b'__time__' in obj: + return dateutil_parser.parse(obj['as_str']).time() + elif b'__decimal__' in obj: + return decimal.Decimal(obj['as_str']) else: - return o + return obj class FormParser(BaseParser): diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index b21037ec5..ea5341adc 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -146,7 +146,6 @@ class MessagePackRenderer(BaseRenderer): media_type = 'application/msgpack' format = 'msgpack' - encoder = encoders.msgpack_encoder def render(self, data, accepted_media_type=None, renderer_context=None): """ @@ -154,7 +153,7 @@ class MessagePackRenderer(BaseRenderer): """ if data is None: return '' - return msgpack.packb(data, default=self.encoder) + return msgpack.packb(data, default=encoders.msgpack_encoder) class TemplateHTMLRenderer(BaseRenderer): diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index 2e309ba4d..7015a009f 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -92,29 +92,16 @@ else: if msgpack: - def msgpack_encoder(o): - # For Date Time string spec, see ECMA 262 - # http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15 - if isinstance(o, datetime.datetime): - r = o.isoformat() - if o.microsecond: - r = r[:23] + r[26:] - if r.endswith('+00:00'): - r = r[:-6] + 'Z' - return {'__datetime__': True, 'as_str': r} - elif isinstance(o, datetime.date): - r = o.isoformat() - return {'__date__': True, 'as_str': r} - elif isinstance(o, datetime.time): - if timezone and timezone.is_aware(o): - raise ValueError("MessagePack can't represent timezone-aware times.") - r = o.isoformat() - if o.microsecond: - r = r[:12] - return {'__time__': True, 'as_str': r} - elif isinstance(o, decimal.Decimal): - return {'__decimal__': True, 'as_str': str(o)} + def msgpack_encoder(obj): + if isinstance(obj, datetime.datetime): + return {'__datetime__': True, 'as_str': obj.isoformat()} + elif isinstance(obj, datetime.date): + return {'__date__': True, 'as_str': obj.isoformat()} + elif isinstance(obj, datetime.time): + return {'__time__': True, 'as_str': obj.isoformat()} + elif isinstance(obj, decimal.Decimal): + return {'__decimal__': True, 'as_str': str(obj)} else: - return o + return obj else: msgpack_encoder = None