From 1ee54fb85ccc71ab689515dc33f9e99a4d872472 Mon Sep 17 00:00:00 2001 From: Sergey Petrunin Date: Wed, 15 Mar 2017 23:45:41 -0400 Subject: [PATCH 1/4] Added test for DateTimeField validation when server has timezone with DST and input is a native time in a DST shift interval. Added pytz to requirements-testing.txt to reproduce the case. --- requirements/requirements-testing.txt | 1 + tests/test_fields.py | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/requirements/requirements-testing.txt b/requirements/requirements-testing.txt index b9e168442d..ea20225124 100644 --- a/requirements/requirements-testing.txt +++ b/requirements/requirements-testing.txt @@ -2,3 +2,4 @@ pytest==3.0.5 pytest-django==3.1.2 pytest-cov==2.4.0 +pytz==2016.10 diff --git a/tests/test_fields.py b/tests/test_fields.py index 16221d4cca..971e7f0e1b 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -9,7 +9,7 @@ from django.http import QueryDict from django.test import TestCase, override_settings from django.utils import six -from django.utils.timezone import utc +from django.utils.timezone import utc, pytz import rest_framework from rest_framework import serializers @@ -1205,6 +1205,23 @@ class TestNaiveDateTimeField(FieldValues): field = serializers.DateTimeField(default_timezone=None) +class TestNaiveDayLightSavingTimeTimeZoneDateTimeField(FieldValues): + """ + Invalid values for `DateTimeField` with datetime in DST shift (non-existing or ambiguous) and timezone with DST. + Timezone America/New_York has DST shift from 2017-03-12T02:00:00 to 2017-03-12T03:00:00 and + from 2017-11-05T02:00:00 to 2017-11-05T01:00:00 in 2017. + """ + valid_inputs = {} + invalid_inputs = { + '2017-03-12T02:30:00': [ + 'Datetime can not be converted to server timezone due to NonExistentTimeError.'], + '2017-11-05T01:30:00': [ + 'Datetime can not be converted to server timezone due to AmbiguousTimeError.'] + } + outputs = {} + field = serializers.DateTimeField(default_timezone=pytz.timezone('America/New_York')) + + class TestTimeField(FieldValues): """ Valid and invalid values for `TimeField`. From d4726dab81412af779cb7fcdc7c29fc07edc4bea Mon Sep 17 00:00:00 2001 From: Sergey Petrunin Date: Sat, 18 Mar 2017 22:43:08 -0400 Subject: [PATCH 2/4] Fix bug for not existent or ambiguous datetime during native to aware conversion in timezone with DST. Ref: #4986 --- rest_framework/fields.py | 6 +++++- tests/test_fields.py | 8 +++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 5a881c772a..fa6ff0bf8d 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1085,6 +1085,7 @@ class DateTimeField(Field): default_error_messages = { 'invalid': _('Datetime has wrong format. Use one of these formats instead: {format}.'), 'date': _('Expected a datetime but got a date.'), + 'make_aware': _('Datetime can not be represented in timezone "{timezone}".') } datetime_parser = datetime.datetime.strptime @@ -1105,7 +1106,10 @@ def enforce_timezone(self, value): field_timezone = getattr(self, 'timezone', self.default_timezone()) if (field_timezone is not None) and not timezone.is_aware(value): - return timezone.make_aware(value, field_timezone) + try: + return timezone.make_aware(value, field_timezone) + except Exception: + self.fail('make_aware', timezone=field_timezone) elif (field_timezone is None) and timezone.is_aware(value): return timezone.make_naive(value, utc) return value diff --git a/tests/test_fields.py b/tests/test_fields.py index 971e7f0e1b..da4a05091b 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -9,7 +9,7 @@ from django.http import QueryDict from django.test import TestCase, override_settings from django.utils import six -from django.utils.timezone import utc, pytz +from django.utils.timezone import pytz, utc import rest_framework from rest_framework import serializers @@ -1213,10 +1213,8 @@ class TestNaiveDayLightSavingTimeTimeZoneDateTimeField(FieldValues): """ valid_inputs = {} invalid_inputs = { - '2017-03-12T02:30:00': [ - 'Datetime can not be converted to server timezone due to NonExistentTimeError.'], - '2017-11-05T01:30:00': [ - 'Datetime can not be converted to server timezone due to AmbiguousTimeError.'] + '2017-03-12T02:30:00': ['Datetime can not be represented in timezone "America/New_York".'], + '2017-11-05T01:30:00': ['Datetime can not be represented in timezone "America/New_York".'] } outputs = {} field = serializers.DateTimeField(default_timezone=pytz.timezone('America/New_York')) From e4a1bd140b3c96dd6724b413a337f639b5a949ef Mon Sep 17 00:00:00 2001 From: Sergey Petrunin Date: Mon, 20 Mar 2017 18:47:25 -0400 Subject: [PATCH 3/4] Update error message. Ref: #4986 --- rest_framework/fields.py | 2 +- tests/test_fields.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index fa6ff0bf8d..6dd40acd9d 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1085,7 +1085,7 @@ class DateTimeField(Field): default_error_messages = { 'invalid': _('Datetime has wrong format. Use one of these formats instead: {format}.'), 'date': _('Expected a datetime but got a date.'), - 'make_aware': _('Datetime can not be represented in timezone "{timezone}".') + 'make_aware': _('Invalid datetime for the timezone "{timezone}".') } datetime_parser = datetime.datetime.strptime diff --git a/tests/test_fields.py b/tests/test_fields.py index da4a05091b..457e368cc1 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1213,8 +1213,8 @@ class TestNaiveDayLightSavingTimeTimeZoneDateTimeField(FieldValues): """ valid_inputs = {} invalid_inputs = { - '2017-03-12T02:30:00': ['Datetime can not be represented in timezone "America/New_York".'], - '2017-11-05T01:30:00': ['Datetime can not be represented in timezone "America/New_York".'] + '2017-03-12T02:30:00': ['Invalid datetime for the timezone "America/New_York".'], + '2017-11-05T01:30:00': ['Invalid datetime for the timezone "America/New_York".'] } outputs = {} field = serializers.DateTimeField(default_timezone=pytz.timezone('America/New_York')) From b0a0c30bfe4643e6824a3ad4d428a9742997aabe Mon Sep 17 00:00:00 2001 From: Sergey Petrunin Date: Wed, 22 Mar 2017 00:01:07 -0400 Subject: [PATCH 4/4] Added pytz exception in compat module. Mock pytz.timezone localize in tests. Ref: #4986 --- requirements/requirements-testing.txt | 1 - rest_framework/compat.py | 9 +++++++++ rest_framework/fields.py | 5 +++-- tests/test_fields.py | 15 ++++++++++++--- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/requirements/requirements-testing.txt b/requirements/requirements-testing.txt index ea20225124..b9e168442d 100644 --- a/requirements/requirements-testing.txt +++ b/requirements/requirements-testing.txt @@ -2,4 +2,3 @@ pytest==3.0.5 pytest-django==3.1.2 pytest-cov==2.4.0 -pytz==2016.10 diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 45ac498417..168bccf83c 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -275,6 +275,14 @@ def pygments_highlight(text, lang, style): def pygments_css(style): return None + +try: + import pytz + from pytz.exceptions import InvalidTimeError +except ImportError: + InvalidTimeError = Exception + + # `separators` argument to `json.dumps()` differs between 2.x and 3.x # See: http://bugs.python.org/issue22767 if six.PY3: @@ -339,6 +347,7 @@ def set_many(instance, field, value): field = getattr(instance, field) field.set(value) + def include(module, namespace=None, app_name=None): from django.conf.urls import include if django.VERSION < (1,9): diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 6dd40acd9d..7ee3f10167 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -33,7 +33,8 @@ from rest_framework import ISO_8601 from rest_framework.compat import ( - get_remote_field, unicode_repr, unicode_to_repr, value_from_object + InvalidTimeError, get_remote_field, unicode_repr, unicode_to_repr, + value_from_object ) from rest_framework.exceptions import ErrorDetail, ValidationError from rest_framework.settings import api_settings @@ -1108,7 +1109,7 @@ def enforce_timezone(self, value): if (field_timezone is not None) and not timezone.is_aware(value): try: return timezone.make_aware(value, field_timezone) - except Exception: + except InvalidTimeError: self.fail('make_aware', timezone=field_timezone) elif (field_timezone is None) and timezone.is_aware(value): return timezone.make_naive(value, utc) diff --git a/tests/test_fields.py b/tests/test_fields.py index 457e368cc1..968c41d3f8 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -9,10 +9,10 @@ from django.http import QueryDict from django.test import TestCase, override_settings from django.utils import six -from django.utils.timezone import pytz, utc +from django.utils.timezone import utc import rest_framework -from rest_framework import serializers +from rest_framework import compat, serializers from rest_framework.fields import is_simple_callable try: @@ -1217,7 +1217,16 @@ class TestNaiveDayLightSavingTimeTimeZoneDateTimeField(FieldValues): '2017-11-05T01:30:00': ['Invalid datetime for the timezone "America/New_York".'] } outputs = {} - field = serializers.DateTimeField(default_timezone=pytz.timezone('America/New_York')) + + class MockTimezone: + @staticmethod + def localize(value, is_dst): + raise compat.InvalidTimeError() + + def __str__(self): + return 'America/New_York' + + field = serializers.DateTimeField(default_timezone=MockTimezone()) class TestTimeField(FieldValues): pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy