diff options
Diffstat (limited to 'rest_framework')
| -rw-r--r-- | rest_framework/__init__.py | 2 | ||||
| -rw-r--r-- | rest_framework/fields.py | 88 | ||||
| -rw-r--r-- | rest_framework/settings.py | 14 | ||||
| -rw-r--r-- | rest_framework/tests/fields.py | 26 | ||||
| -rw-r--r-- | rest_framework/utils/dates.py | 14 |
5 files changed, 83 insertions, 61 deletions
diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index d26bb6bf..14ab7ff0 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -6,4 +6,4 @@ VERSION = __version__ # synonym HTTP_HEADER_ENCODING = 'iso-8859-1' # Default input and output format -ISO8601 = 'iso-8601'
\ No newline at end of file +ISO_8601 = 'iso-8601' diff --git a/rest_framework/fields.py b/rest_framework/fields.py index e65f0307..fe555ee5 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -14,13 +14,12 @@ from django.forms import widgets from django.utils.encoding import is_protected_type from django.utils.translation import ugettext_lazy as _ -from rest_framework import ISO8601 +from rest_framework import ISO_8601 from rest_framework.compat import timezone, parse_date, parse_datetime, parse_time from rest_framework.compat import BytesIO from rest_framework.compat import six from rest_framework.compat import smart_text from rest_framework.settings import api_settings -from rest_framework.utils.dates import get_readable_date_format def is_simple_callable(obj): @@ -52,6 +51,46 @@ def get_component(obj, attr_name): return val +def readable_datetime_formats(formats): + format = ', '.join(formats).replace(ISO_8601, 'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HHMM|-HHMM|Z]') + return humanize_strptime(format) + + +def readable_date_formats(formats): + format = ', '.join(formats).replace(ISO_8601, 'YYYY[-MM[-DD]]') + return humanize_strptime(format) + + +def readable_time_formats(formats): + format = ', '.join(formats).replace(ISO_8601, 'hh:mm[:ss[.uuuuuu]]') + return humanize_strptime(format) + + +def humanize_strptime(format_string): + # Note that we're missing some of the locale specific mappings that + # don't really make sense. + mapping = { + "%Y": "YYYY", + "%y": "YY", + "%m": "MM", + "%b": "[Jan-Dec]", + "%B": "[January-December]", + "%d": "DD", + "%H": "hh", + "%I": "hh", # Requires '%p' to differentiate from '%H'. + "%M": "mm", + "%S": "ss", + "%f": "uuuuuu", + "%a": "[Mon-Sun]", + "%A": "[Monday-Sunday]", + "%p": "[AM|PM]", + "%z": "[+HHMM|-HHMM]" + } + for key, val in mapping.items(): + format_string = format_string.replace(key, val) + return format_string + + class Field(object): read_only = True creation_counter = 0 @@ -453,11 +492,11 @@ class DateField(WritableField): } empty = None input_formats = api_settings.DATE_INPUT_FORMATS - output_format = api_settings.DATE_OUTPUT_FORMAT + format = api_settings.DATE_FORMAT - def __init__(self, input_formats=None, output_format=None, *args, **kwargs): + def __init__(self, input_formats=None, format=None, *args, **kwargs): self.input_formats = input_formats if input_formats is not None else self.input_formats - self.output_format = output_format if output_format is not None else self.output_format + self.format = format if format is not None else self.format super(DateField, self).__init__(*args, **kwargs) def from_native(self, value): @@ -475,7 +514,7 @@ class DateField(WritableField): return value for format in self.input_formats: - if format.lower() == ISO8601: + if format.lower() == ISO_8601: try: parsed = parse_date(value) except (ValueError, TypeError): @@ -491,16 +530,15 @@ class DateField(WritableField): else: return parsed.date() - date_input_formats = '; '.join(self.input_formats).replace(ISO8601, 'YYYY-MM-DD') - msg = self.error_messages['invalid'] % get_readable_date_format(date_input_formats) + msg = self.error_messages['invalid'] % readable_date_formats(self.input_formats) raise ValidationError(msg) def to_native(self, value): if isinstance(value, datetime.datetime): value = value.date() - if self.output_format.lower() == ISO8601: + if self.format.lower() == ISO_8601: return value.isoformat() - return value.strftime(self.output_format) + return value.strftime(self.format) class DateTimeField(WritableField): @@ -513,11 +551,11 @@ class DateTimeField(WritableField): } empty = None input_formats = api_settings.DATETIME_INPUT_FORMATS - output_format = api_settings.DATETIME_OUTPUT_FORMAT + format = api_settings.DATETIME_FORMAT - def __init__(self, input_formats=None, output_format=None, *args, **kwargs): + def __init__(self, input_formats=None, format=None, *args, **kwargs): self.input_formats = input_formats if input_formats is not None else self.input_formats - self.output_format = output_format if output_format is not None else self.output_format + self.format = format if format is not None else self.format super(DateTimeField, self).__init__(*args, **kwargs) def from_native(self, value): @@ -541,7 +579,7 @@ class DateTimeField(WritableField): return value for format in self.input_formats: - if format.lower() == ISO8601: + if format.lower() == ISO_8601: try: parsed = parse_datetime(value) except (ValueError, TypeError): @@ -557,14 +595,13 @@ class DateTimeField(WritableField): else: return parsed - datetime_input_formats = '; '.join(self.input_formats).replace(ISO8601, 'YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]') - msg = self.error_messages['invalid'] % get_readable_date_format(datetime_input_formats) + msg = self.error_messages['invalid'] % readable_datetime_formats(self.input_formats) raise ValidationError(msg) def to_native(self, value): - if self.output_format.lower() == ISO8601: + if self.format.lower() == ISO_8601: return value.isoformat() - return value.strftime(self.output_format) + return value.strftime(self.format) class TimeField(WritableField): @@ -577,11 +614,11 @@ class TimeField(WritableField): } empty = None input_formats = api_settings.TIME_INPUT_FORMATS - output_format = api_settings.TIME_OUTPUT_FORMAT + format = api_settings.TIME_FORMAT - def __init__(self, input_formats=None, output_format=None, *args, **kwargs): + def __init__(self, input_formats=None, format=None, *args, **kwargs): self.input_formats = input_formats if input_formats is not None else self.input_formats - self.output_format = output_format if output_format is not None else self.output_format + self.format = format if format is not None else self.format super(TimeField, self).__init__(*args, **kwargs) def from_native(self, value): @@ -592,7 +629,7 @@ class TimeField(WritableField): return value for format in self.input_formats: - if format.lower() == ISO8601: + if format.lower() == ISO_8601: try: parsed = parse_time(value) except (ValueError, TypeError): @@ -608,16 +645,15 @@ class TimeField(WritableField): else: return parsed.time() - time_input_formats = '; '.join(self.input_formats).replace(ISO8601, 'HH:MM[:ss[.uuuuuu]]') - msg = self.error_messages['invalid'] % get_readable_date_format(time_input_formats) + msg = self.error_messages['invalid'] % readable_time_formats(self.input_formats) raise ValidationError(msg) def to_native(self, value): if isinstance(value, datetime.datetime): value = value.time() - if self.output_format.lower() == ISO8601: + if self.format.lower() == ISO_8601: return value.isoformat() - return value.strftime(self.output_format) + return value.strftime(self.format) class IntegerField(WritableField): diff --git a/rest_framework/settings.py b/rest_framework/settings.py index 02d751e1..eede0c5a 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -22,7 +22,7 @@ from __future__ import unicode_literals from django.conf import settings from django.utils import importlib -from rest_framework import ISO8601 +from rest_framework import ISO_8601 from rest_framework.compat import six @@ -82,19 +82,19 @@ DEFAULTS = { # Input and output formats 'DATE_INPUT_FORMATS': ( - ISO8601, + ISO_8601, ), - 'DATE_OUTPUT_FORMAT': ISO8601, + 'DATE_FORMAT': ISO_8601, 'DATETIME_INPUT_FORMATS': ( - ISO8601, + ISO_8601, ), - 'DATETIME_OUTPUT_FORMAT': ISO8601, + 'DATETIME_FORMAT': ISO_8601, 'TIME_INPUT_FORMATS': ( - ISO8601, + ISO_8601, ), - 'TIME_OUTPUT_FORMAT': ISO8601, + 'TIME_FORMAT': ISO_8601, } diff --git a/rest_framework/tests/fields.py b/rest_framework/tests/fields.py index 17ef2f2c..28f18ed8 100644 --- a/rest_framework/tests/fields.py +++ b/rest_framework/tests/fields.py @@ -59,7 +59,7 @@ class BasicFieldTests(TestCase): PK fields other than AutoField fields should not be read_only by default. """ serializer = CharPrimaryKeyModelSerializer() - self.assertEquals(serializer.fields['id'].read_only, False) + self.assertEqual(serializer.fields['id'].read_only, False) class DateFieldTest(TestCase): @@ -134,7 +134,7 @@ class DateFieldTest(TestCase): try: f.from_native('1984-13-31') except validators.ValidationError as e: - self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY-MM-DD"]) + self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]"]) else: self.fail("ValidationError was not properly raised") @@ -147,7 +147,7 @@ class DateFieldTest(TestCase): try: f.from_native('1984 -- 31') except validators.ValidationError as e: - self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY-MM-DD"]) + self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]"]) else: self.fail("ValidationError was not properly raised") @@ -165,7 +165,7 @@ class DateFieldTest(TestCase): """ Make sure to_native() returns correct custom format. """ - f = serializers.DateField(output_format="%Y - %m.%d") + f = serializers.DateField(format="%Y - %m.%d") result_1 = f.to_native(datetime.date(1984, 7, 31)) @@ -221,7 +221,7 @@ class DateTimeFieldTest(TestCase): try: f.from_native('1984-07-31 04:31:59') except validators.ValidationError as e: - self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: YYYY -- HH:MM"]) + self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: YYYY -- hh:mm"]) else: self.fail("ValidationError was not properly raised") @@ -253,7 +253,7 @@ class DateTimeFieldTest(TestCase): f.from_native('04:61:59') except validators.ValidationError as e: self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: " - "YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]"]) + "YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HHMM|-HHMM|Z]"]) else: self.fail("ValidationError was not properly raised") @@ -267,7 +267,7 @@ class DateTimeFieldTest(TestCase): f.from_native('04 -- 31') except validators.ValidationError as e: self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: " - "YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]"]) + "YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HHMM|-HHMM|Z]"]) else: self.fail("ValidationError was not properly raised") @@ -291,7 +291,7 @@ class DateTimeFieldTest(TestCase): """ Make sure to_native() returns correct custom format. """ - f = serializers.DateTimeField(output_format="%Y - %H:%M") + f = serializers.DateTimeField(format="%Y - %H:%M") result_1 = f.to_native(datetime.datetime(1984, 7, 31)) result_2 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31)) @@ -353,7 +353,7 @@ class TimeFieldTest(TestCase): try: f.from_native('04:31:59') except validators.ValidationError as e: - self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: HH -- MM"]) + self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: hh -- mm"]) else: self.fail("ValidationError was not properly raised") @@ -385,7 +385,7 @@ class TimeFieldTest(TestCase): f.from_native('04:61:59') except validators.ValidationError as e: self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: " - "HH:MM[:ss[.uuuuuu]]"]) + "hh:mm[:ss[.uuuuuu]]"]) else: self.fail("ValidationError was not properly raised") @@ -399,7 +399,7 @@ class TimeFieldTest(TestCase): f.from_native('04 -- 31') except validators.ValidationError as e: self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: " - "HH:MM[:ss[.uuuuuu]]"]) + "hh:mm[:ss[.uuuuuu]]"]) else: self.fail("ValidationError was not properly raised") @@ -420,11 +420,11 @@ class TimeFieldTest(TestCase): """ Make sure to_native() returns correct custom format. """ - f = serializers.TimeField(output_format="%H - %S [%f]") + f = serializers.TimeField(format="%H - %S [%f]") result_1 = f.to_native(datetime.time(4, 31)) result_2 = f.to_native(datetime.time(4, 31, 59)) result_3 = f.to_native(datetime.time(4, 31, 59, 200)) self.assertEqual('04 - 00 [000000]', result_1) self.assertEqual('04 - 59 [000000]', result_2) - self.assertEqual('04 - 59 [000200]', result_3)
\ No newline at end of file + self.assertEqual('04 - 59 [000200]', result_3) diff --git a/rest_framework/utils/dates.py b/rest_framework/utils/dates.py deleted file mode 100644 index f094f72d..00000000 --- a/rest_framework/utils/dates.py +++ /dev/null @@ -1,14 +0,0 @@ -def get_readable_date_format(date_format): - mapping = [("%Y", "YYYY"), - ("%y", "YY"), - ("%m", "MM"), - ("%b", "[Jan through Dec]"), - ("%B", "[January through December]"), - ("%d", "DD"), - ("%H", "HH"), - ("%M", "MM"), - ("%S", "SS"), - ("%f", "uuuuuu")] - for k, v in mapping: - date_format = date_format.replace(k, v) - return date_format
\ No newline at end of file |
