Browse Source

Fixed #16123 -- Ensured strptime receive proper string type

strptime generates an UnicodeEncodeError when using a non-ascii
unicode string on Python 2.
Claude Paroz 12 years ago
parent
commit
4b3f7110ae

+ 2 - 1
django/forms/extras/widgets.py

@@ -9,6 +9,7 @@ import re
 from django.forms.widgets import Widget, Select
 from django.utils import datetime_safe
 from django.utils.dates import MONTHS
+from django.utils.encoding import force_str
 from django.utils.safestring import mark_safe
 from django.utils.formats import get_format
 from django.utils import six
@@ -69,7 +70,7 @@ class SelectDateWidget(Widget):
                 if settings.USE_L10N:
                     try:
                         input_format = get_format('DATE_INPUT_FORMATS')[0]
-                        v = datetime.datetime.strptime(value, input_format)
+                        v = datetime.datetime.strptime(force_str(value), input_format)
                         year_val, month_val, day_val = v.year, v.month, v.day
                     except ValueError:
                         pass

+ 4 - 4
django/forms/fields.py

@@ -23,7 +23,7 @@ from django.forms.widgets import (TextInput, PasswordInput, HiddenInput,
     NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput,
     SplitDateTimeWidget, SplitHiddenDateTimeWidget, FILE_INPUT_CONTRADICTION)
 from django.utils import formats
-from django.utils.encoding import smart_text, force_text
+from django.utils.encoding import smart_text, force_str, force_text
 from django.utils.ipv6 import clean_ipv6_address
 from django.utils import six
 from django.utils.translation import ugettext_lazy as _
@@ -395,7 +395,7 @@ class DateField(BaseTemporalField):
         return super(DateField, self).to_python(value)
 
     def strptime(self, value, format):
-        return datetime.datetime.strptime(value, format).date()
+        return datetime.datetime.strptime(force_str(value), format).date()
 
 
 class TimeField(BaseTemporalField):
@@ -417,7 +417,7 @@ class TimeField(BaseTemporalField):
         return super(TimeField, self).to_python(value)
 
     def strptime(self, value, format):
-        return datetime.datetime.strptime(value, format).time()
+        return datetime.datetime.strptime(force_str(value), format).time()
 
 class DateTimeField(BaseTemporalField):
     widget = DateTimeInput
@@ -455,7 +455,7 @@ class DateTimeField(BaseTemporalField):
         return from_current_timezone(result)
 
     def strptime(self, value, format):
-        return datetime.datetime.strptime(value, format)
+        return datetime.datetime.strptime(force_str(value), format)
 
 class RegexField(CharField):
     def __init__(self, regex, max_length=None, min_length=None, error_message=None, *args, **kwargs):

+ 2 - 2
django/views/generic/dates.py

@@ -5,7 +5,7 @@ from django.conf import settings
 from django.db import models
 from django.core.exceptions import ImproperlyConfigured
 from django.http import Http404
-from django.utils.encoding import force_text
+from django.utils.encoding import force_str, force_text
 from django.utils.functional import cached_property
 from django.utils.translation import ugettext as _
 from django.utils import timezone
@@ -673,7 +673,7 @@ def _date_from_string(year, year_format, month='', month_format='', day='', day_
     format = delim.join((year_format, month_format, day_format))
     datestr = delim.join((year, month, day))
     try:
-        return datetime.datetime.strptime(datestr, format).date()
+        return datetime.datetime.strptime(force_str(datestr), format).date()
     except ValueError:
         raise Http404(_("Invalid date string '%(datestr)s' given format '%(format)s'") % {
             'datestr': datestr,

+ 10 - 0
tests/regressiontests/forms/tests/fields.py

@@ -370,6 +370,16 @@ class FieldsTests(SimpleTestCase):
         self.assertFalse(f._has_changed(d, '17/09/2007'))
         self.assertFalse(f._has_changed(d.strftime(format), '17/09/2007'))
 
+    def test_datefield_strptime(self):
+        """Test that field.strptime doesn't raise an UnicodeEncodeError (#16123)"""
+        f = DateField()
+        try:
+            f.strptime('31 мая 2011', '%d-%b-%y')
+        except Exception as e:
+            # assertIsInstance or assertRaises cannot be used because UnicodeEncodeError
+            # is a subclass of ValueError
+            self.assertEqual(e.__class__, ValueError)
+
     # TimeField ###################################################################
 
     def test_timefield_1(self):