[Checkins] SVN: Zope3/branches/3.3/ Rolled back the famous Date(time)Widget fix (see revison 68818 for details).

Dmitry Vasiliev dima at hlabs.spb.ru
Sat Jul 1 13:18:57 EDT 2006


Log message for revision 68937:
  Rolled back the famous Date(time)Widget fix (see revison 68818 for details).
  Added Date(time)I18nWidget instead.
  

Changed:
  U   Zope3/branches/3.3/doc/CHANGES.txt
  U   Zope3/branches/3.3/src/zope/app/form/browser/__init__.py
  U   Zope3/branches/3.3/src/zope/app/form/browser/ftests/test_datetimewidget.py
  U   Zope3/branches/3.3/src/zope/app/form/browser/tests/test_datetimewidget.py
  U   Zope3/branches/3.3/src/zope/app/form/browser/tests/test_datewidget.py
  U   Zope3/branches/3.3/src/zope/app/form/browser/textwidgets.py
  U   Zope3/branches/3.3/src/zope/formlib/form.txt

-=-
Modified: Zope3/branches/3.3/doc/CHANGES.txt
===================================================================
--- Zope3/branches/3.3/doc/CHANGES.txt	2006-07-01 13:53:26 UTC (rev 68936)
+++ Zope3/branches/3.3/doc/CHANGES.txt	2006-07-01 17:18:56 UTC (rev 68937)
@@ -11,8 +11,9 @@
     Bugfixes
 
       - Fixed issue 525: DateWidget ru-format.
-        If you plan to use DatetimeWidget with timezone information take a look
-        at the note in the DatetimeWidget docstring;
+        Added new Date(time)I18nWidget. Note: if you plan to use
+        DatetimeI18nWidget with timezone information take a look
+        at the note in the DatetimeI18nWidget docstring;
 
       - Fixed issue 531: Spurious i18n deprecation warnings;
 

Modified: Zope3/branches/3.3/src/zope/app/form/browser/__init__.py
===================================================================
--- Zope3/branches/3.3/src/zope/app/form/browser/__init__.py	2006-07-01 13:53:26 UTC (rev 68936)
+++ Zope3/branches/3.3/src/zope/app/form/browser/__init__.py	2006-07-01 17:18:56 UTC (rev 68937)
@@ -26,6 +26,8 @@
 from zope.app.form.browser.textwidgets import ASCIIWidget, ASCIIAreaWidget
 from zope.app.form.browser.textwidgets import IntWidget, FloatWidget
 from zope.app.form.browser.textwidgets import DatetimeWidget, DateWidget
+from zope.app.form.browser.textwidgets import DatetimeI18nWidget
+from zope.app.form.browser.textwidgets import DateI18nWidget
 from zope.app.form.browser.textwidgets import DatetimeDisplayWidget
 from zope.app.form.browser.textwidgets import DateDisplayWidget
 from zope.app.form.browser.textwidgets import BytesDisplayWidget

Modified: Zope3/branches/3.3/src/zope/app/form/browser/ftests/test_datetimewidget.py
===================================================================
--- Zope3/branches/3.3/src/zope/app/form/browser/ftests/test_datetimewidget.py	2006-07-01 13:53:26 UTC (rev 68936)
+++ Zope3/branches/3.3/src/zope/app/form/browser/ftests/test_datetimewidget.py	2006-07-01 17:18:56 UTC (rev 68937)
@@ -22,7 +22,7 @@
 from datetime import datetime
 
 import zope.security.checker
-from zope.datetime import tzinfo
+from zope.datetime import parseDatetimetz, tzinfo
 from zope.interface import Interface, implements
 from zope.schema import Datetime, Choice
 from zope.traversing.api import traverse
@@ -39,22 +39,22 @@
     d3 = Choice(
         required=False,
         values=(
-            datetime(2003, 9, 15),
-            datetime(2003, 10, 15)),
-        missing_value=datetime(2000, 1, 1))
+            datetime(2003, 9, 15, tzinfo=tzinfo(0)),
+            datetime(2003, 10, 15, tzinfo=tzinfo(0))),
+        missing_value=datetime(2000, 1, 1, tzinfo=tzinfo(0)))
 
     d1 = Datetime(
         required=True,
-        min=datetime(2003, 1, 1),
-        max=datetime(2020, 12, 31))
+        min=datetime(2003, 1, 1, tzinfo=tzinfo(0)),
+        max=datetime(2020, 12, 31, tzinfo=tzinfo(0)))
 
 class DatetimeTest(Persistent):
 
     implements(IDatetimeTest)
 
     def __init__(self):
-        self.d1 = datetime(2003, 4, 6)
-        self.d2 = datetime(2003, 8, 6)
+        self.d1 = datetime(2003, 4, 6, tzinfo=tzinfo(0))
+        self.d2 = datetime(2003, 8, 6, tzinfo=tzinfo(0))
         self.d3 = None
 
 class Test(BrowserTestCase):
@@ -80,13 +80,8 @@
             m = re.search(pattern, source, re.DOTALL)
             if m is None:
                 return None
+        return parseDatetimetz(m.group(1))
 
-        request = self.makeRequest(env={"HTTP_ACCEPT_LANGUAGE": "ru"})
-
-        formatter = request.locale.dates.getFormatter("dateTime")
-
-        return formatter.parse(m.group(1))
-
     def test_display_editform(self):
         self.getRootFolder()['test'] = DatetimeTest()
         transaction.commit()
@@ -112,9 +107,9 @@
         # submit edit view
         response = self.publish('/test/edit.html', form={
             'UPDATE_SUBMIT' : '',
-            'field.d1' : u'Feb 1, 2003 12:00:00 AM',
-            'field.d2' : u'Feb 2, 2003 12:00:00 AM',
-            'field.d3' : u'2003-10-15 00:00:00' },
+            'field.d1' : u'2003-02-01 00:00:00+00:00',
+            'field.d2' : u'2003-02-02 00:00:00+00:00',
+            'field.d3' : u'2003-10-15 00:00:00+00:00' },
             env={"HTTP_ACCEPT_LANGUAGE": "en"})
         self.assertEqual(response.getStatus(), 200)
         self.assert_(updatedMsgExists(response.getBody()))
@@ -122,9 +117,9 @@
         # check new values in object
         object = traverse(self.getRootFolder(), 'test')
 
-        self.assertEqual(object.d1, datetime(2003, 2, 1))
-        self.assertEqual(object.d2, datetime(2003, 2, 2))
-        self.assertEqual(object.d3, datetime(2003, 10, 15))
+        self.assertEqual(object.d1, datetime(2003, 2, 1, tzinfo=tzinfo(0)))
+        self.assertEqual(object.d2, datetime(2003, 2, 2, tzinfo=tzinfo(0)))
+        self.assertEqual(object.d3, datetime(2003, 10, 15, tzinfo=tzinfo(0)))
 
 
     def test_missing_value(self):
@@ -143,7 +138,7 @@
         object = traverse(self.getRootFolder(), 'test')
         self.assert_(object.d2 is None) # default missing_value for dates
         # 2000-1-1 is missing_value for d3
-        self.assertEqual(object.d3, datetime(2000, 1, 1))
+        self.assertEqual(object.d3, datetime(2000, 1, 1, tzinfo=tzinfo(0)))
 
 
     def test_required_validation(self):
@@ -171,7 +166,7 @@
         # submit a value for d3 that isn't allowed
         response = self.publish('/test/edit.html', form={
             'UPDATE_SUBMIT' : '',
-            'field.d3' : u'Feb 1, 2003 12:00:00 AM'})
+            'field.d3' : u'2003-02-01 12:00:00+00:00'})
         self.assertEqual(response.getStatus(), 200)
         self.assert_(invalidValueErrorExists('d3', response.getBody()))
 
@@ -183,7 +178,7 @@
         # submit value for d1 that is too low
         response = self.publish('/test/edit.html', form={
             'UPDATE_SUBMIT' : '',
-            'field.d1' : u'Dec 31, 2002 12:00:00 AM'},
+            'field.d1' : u'2002-12-31 12:00:00+00:00'},
             env={"HTTP_ACCEPT_LANGUAGE": "en"})
         self.assertEqual(response.getStatus(), 200)
         self.assert_(validationErrorExists('d1', 'Value is too small',
@@ -192,7 +187,7 @@
         # submit value for i1 that is too high
         response = self.publish('/test/edit.html', form={
             'UPDATE_SUBMIT' : '',
-            'field.d1' : u'Dec 1, 2021 12:00:00 AM'},
+            'field.d1' : u'2021-12-01 12:00:00+00:00'},
             env={"HTTP_ACCEPT_LANGUAGE": "en"})
         self.assertEqual(response.getStatus(), 200)
         self.assert_(validationErrorExists('d1', 'Value is too big',

Modified: Zope3/branches/3.3/src/zope/app/form/browser/tests/test_datetimewidget.py
===================================================================
--- Zope3/branches/3.3/src/zope/app/form/browser/tests/test_datetimewidget.py	2006-07-01 13:53:26 UTC (rev 68936)
+++ Zope3/branches/3.3/src/zope/app/form/browser/tests/test_datetimewidget.py	2006-07-01 17:18:56 UTC (rev 68937)
@@ -19,12 +19,13 @@
 import unittest, doctest
 
 from zope.schema import Datetime
-from zope.datetime import tzinfo
+from zope.datetime import parseDatetimetz, tzinfo
 from zope.interface.verify import verifyClass
 
 from zope.app.form.browser.tests.test_browserwidget import SimpleInputWidgetTest
 from zope.app.form.interfaces import IInputWidget
 from zope.app.form.browser import DatetimeWidget
+from zope.app.form.browser import DatetimeI18nWidget
 from zope.app.form.interfaces import ConversionError, WidgetInputError
 
 
@@ -38,32 +39,67 @@
     _FieldFactory = Datetime
     _WidgetFactory = DatetimeWidget
 
+    def testRender(self):
+        super(DatetimeWidgetTest, self).testRender(
+            datetime.datetime(2004, 3, 26, 12, 58, 59),
+            ('type="text"', 'id="field.foo"', 'name="field.foo"',
+                'value="2004-03-26 12:58:59"'))
+
+    def test_hasInput(self):
+        del self._widget.request.form['field.foo']
+        self.failIf(self._widget.hasInput())
+        # widget has input, even if input is an empty string
+        self._widget.request.form['field.foo'] = u''
+        self.failUnless(self._widget.hasInput())
+        self._widget.request.form['field.foo'] = u'2003-03-26 12:00:00'
+        self.failUnless(self._widget.hasInput())
+
+    def test_getInputValue(self,
+            value=u'2004-03-26 12:58:59',
+            check_value=parseDatetimetz('2004-03-26 12:58:59')):
+        self._widget.request.form['field.foo'] = u''
+        self.assertRaises(WidgetInputError, self._widget.getInputValue)
+        self._widget.request.form['field.foo'] = value
+        self.assertEquals(self._widget.getInputValue(), check_value)
+        self._widget.request.form['field.foo'] = u'abc'
+        self.assertRaises(ConversionError, self._widget.getInputValue)
+
+class DatetimeI18nWidgetTest(SimpleInputWidgetTest):
+    """Documents and tests the i18n datetime widget.
+
+        >>> verifyClass(IInputWidget, DatetimeI18nWidget)
+        True
+    """
+
+    _FieldFactory = Datetime
+    _WidgetFactory = DatetimeI18nWidget
+
     def testDefaultDisplayStyle(self):
         self.failIf(self._widget.displayStyle)
 
     def testRender(self):
-        super(DatetimeWidgetTest, self).testRender(
+        super(DatetimeI18nWidgetTest, self).testRender(
             datetime.datetime(2004, 3, 26, 12, 58, 59),
             ('type="text"', 'id="field.foo"', 'name="field.foo"',
                 'value="26.03.2004 12:58:59"'))
 
     def testRenderShort(self):
         self._widget.displayStyle = "short"
-        super(DatetimeWidgetTest, self).testRender(
+        super(DatetimeI18nWidgetTest, self).testRender(
             datetime.datetime(2004, 3, 26, 12, 58, 59),
             ('type="text"', 'id="field.foo"', 'name="field.foo"',
                 'value="26.03.04 12:58"'))
 
     def testRenderMedium(self):
         self._widget.displayStyle = "medium"
-        super(DatetimeWidgetTest, self).testRender(
+        super(DatetimeI18nWidgetTest, self).testRender(
             datetime.datetime(2004, 3, 26, 12, 58, 59),
             ('type="text"', 'id="field.foo"', 'name="field.foo"',
                 'value="26.03.2004 12:58:59"'))
 
     def testRenderLong(self):
         self._widget.displayStyle = "long"
-        super(DatetimeWidgetTest, self).testRender(
+        super(DatetimeI18nWidgetTest, self).testRender(
             datetime.datetime(2004, 3, 26, 12, 58, 59),
             ('type="text"', 'id="field.foo"', 'name="field.foo"',
                 u'value="26 \u041c\u0430\u0440\u0442 2004 \u0433.'
@@ -71,7 +107,7 @@
 
     def testRenderFull(self):
         self._widget.displayStyle = "full"
-        super(DatetimeWidgetTest, self).testRender(
+        super(DatetimeI18nWidgetTest, self).testRender(
             datetime.datetime(2004, 3, 26, 12, 58, 59),
             ('type="text"', 'id="field.foo"', 'name="field.foo"',
                 u'value="26 \u041c\u0430\u0440\u0442 2004 \u0433.'
@@ -132,6 +168,7 @@
 def test_suite():
     return unittest.TestSuite((
         unittest.makeSuite(DatetimeWidgetTest),
+        unittest.makeSuite(DatetimeI18nWidgetTest),
         doctest.DocTestSuite(),
         ))
 

Modified: Zope3/branches/3.3/src/zope/app/form/browser/tests/test_datewidget.py
===================================================================
--- Zope3/branches/3.3/src/zope/app/form/browser/tests/test_datewidget.py	2006-07-01 13:53:26 UTC (rev 68936)
+++ Zope3/branches/3.3/src/zope/app/form/browser/tests/test_datewidget.py	2006-07-01 17:18:56 UTC (rev 68937)
@@ -25,6 +25,7 @@
 from zope.app.form.browser.tests.test_browserwidget import SimpleInputWidgetTest
 from zope.app.form.interfaces import IInputWidget
 from zope.app.form.browser import DateWidget
+from zope.app.form.browser import DateI18nWidget
 from zope.app.form.interfaces import ConversionError, WidgetInputError
 
 
@@ -38,39 +39,73 @@
     _FieldFactory = Date
     _WidgetFactory = DateWidget
 
+    def testRender(self):
+        super(DateWidgetTest, self).testRender(
+            datetime.date(2003, 3, 26),
+            ('type="text"', 'id="field.foo"', 'name="field.foo"',
+                'value="2003-03-26"'))
+
+    def test_hasInput(self):
+        del self._widget.request.form['field.foo']
+        self.failIf(self._widget.hasInput())
+        self._widget.request.form['field.foo'] = u''
+        self.failUnless(self._widget.hasInput())
+        self._widget.request.form['field.foo'] = u'2003-03-26'
+        self.failUnless(self._widget.hasInput())
+
+    def test_getInputValue(self,
+            value=u'2004-03-26',
+            check_value=datetime.date(2004, 3, 26)):
+        self._widget.request.form['field.foo'] = u''
+        self.assertRaises(WidgetInputError, self._widget.getInputValue)
+        self._widget.request.form['field.foo'] = value
+        self.assertEquals(self._widget.getInputValue(), check_value)
+        self._widget.request.form['field.foo'] = u'abc'
+        self.assertRaises(ConversionError, self._widget.getInputValue)
+
+class DateI18nWidgetTest(SimpleInputWidgetTest):
+    """Documents and tests the i18n date widget.
+
+        >>> verifyClass(IInputWidget, DateI18nWidget)
+        True
+    """
+
+    _FieldFactory = Date
+    _WidgetFactory = DateI18nWidget
+
     def testDefaultDisplayStyle(self):
         self.failIf(self._widget.displayStyle)
 
     def testRender(self):
-        super(DateWidgetTest, self).testRender(
+        super(DateI18nWidgetTest, self).testRender(
             datetime.date(2003, 3, 26),
             ('type="text"', 'id="field.foo"', 'name="field.foo"',
                 'value="26.03.2003"'))
 
     def testRenderShort(self):
         self._widget.displayStyle = "short"
-        super(DateWidgetTest, self).testRender(
+        super(DateI18nWidgetTest, self).testRender(
             datetime.datetime(2004, 3, 26, 12, 58, 59),
             ('type="text"', 'id="field.foo"', 'name="field.foo"',
                 'value="26.03.04"'))
 
     def testRenderMedium(self):
         self._widget.displayStyle = "medium"
-        super(DateWidgetTest, self).testRender(
+        super(DateI18nWidgetTest, self).testRender(
             datetime.datetime(2004, 3, 26, 12, 58, 59),
             ('type="text"', 'id="field.foo"', 'name="field.foo"',
                 'value="26.03.2004"'))
 
     def testRenderLong(self):
         self._widget.displayStyle = "long"
-        super(DateWidgetTest, self).testRender(
+        super(DateI18nWidgetTest, self).testRender(
             datetime.datetime(2004, 3, 26, 12, 58, 59),
             ('type="text"', 'id="field.foo"', 'name="field.foo"',
                 u'value="26 \u041c\u0430\u0440\u0442 2004 \u0433."'))
 
     def testRenderFull(self):
         self._widget.displayStyle = "full"
-        super(DateWidgetTest, self).testRender(
+        super(DateI18nWidgetTest, self).testRender(
             datetime.datetime(2004, 3, 26, 12, 58, 59),
             ('type="text"', 'id="field.foo"', 'name="field.foo"',
                 u'value="26 \u041c\u0430\u0440\u0442 2004 \u0433."'))
@@ -117,6 +152,7 @@
 def test_suite():
     return unittest.TestSuite((
         unittest.makeSuite(DateWidgetTest),
+        unittest.makeSuite(DateI18nWidgetTest),
         doctest.DocTestSuite(),
         ))
 

Modified: Zope3/branches/3.3/src/zope/app/form/browser/textwidgets.py
===================================================================
--- Zope3/branches/3.3/src/zope/app/form/browser/textwidgets.py	2006-07-01 13:53:26 UTC (rev 68936)
+++ Zope3/branches/3.3/src/zope/app/form/browser/textwidgets.py	2006-07-01 17:18:56 UTC (rev 68937)
@@ -19,6 +19,8 @@
 
 from xml.sax import saxutils
 from zope.interface import implements
+from zope.datetime import parseDatetimetz
+from zope.datetime import DateTimeError
 from zope.i18n.format import DateTimeParseError
 
 from zope.app.form.interfaces import IInputWidget, ConversionError
@@ -483,9 +485,37 @@
             except ValueError, v:
                 raise ConversionError(_("Invalid floating point data"), v)
 
-class DateWidget(TextWidget):
+class DatetimeWidget(TextWidget):
+    """Datetime entry widget."""
+
+    displayWidth = 20
+
+    def _toFieldValue(self, input):
+        if input == self._missing:
+            return self.context.missing_value
+        else:
+            try:
+                # TODO: Currently datetimes return in local (server)
+                # time zone if no time zone information was given.
+                # Maybe offset-naive datetimes should be returned in
+                # this case? (DV)
+                return parseDatetimetz(input)
+            except (DateTimeError, ValueError, IndexError), v:
+                raise ConversionError(_("Invalid datetime data"), v)
+
+class DateWidget(DatetimeWidget):
     """Date entry widget.
+    """
 
+    def _toFieldValue(self, input):
+        v = super(DateWidget, self)._toFieldValue(input)
+        if v != self.context.missing_value:
+            v = v.date()
+        return v
+
+class DateI18nWidget(TextWidget):
+    """I18n date entry widget.
+
     The `displayStyle` attribute may be set to control the formatting of the
     value.
 
@@ -513,15 +543,15 @@
                     "%s (%r)" % (v, input))
 
     def _toFormValue(self, value):
-        value = super(DateWidget, self)._toFormValue(value)
+        value = super(DateI18nWidget, self)._toFormValue(value)
         if value:
             formatter = self.request.locale.dates.getFormatter(
                 self._category, (self.displayStyle or None))
             value = formatter.format(value)
         return value
 
-class DatetimeWidget(DateWidget):
-    """Datetime entry widget.
+class DatetimeI18nWidget(DateI18nWidget):
+    """I18n datetime entry widget.
 
     The `displayStyle` attribute may be set to control the formatting of the
     value.

Modified: Zope3/branches/3.3/src/zope/formlib/form.txt
===================================================================
--- Zope3/branches/3.3/src/zope/formlib/form.txt	2006-07-01 13:53:26 UTC (rev 68936)
+++ Zope3/branches/3.3/src/zope/formlib/form.txt	2006-07-01 17:18:56 UTC (rev 68937)
@@ -1554,7 +1554,7 @@
     <input class="textType" id="form.max_size" name="form.max_size" 
            size="10" type="text" value=""  />
     <input class="textType" id="form.now" name="form.now" size="20" 
-           type="text" value="2002 12 2  12:30:00 "  />
+           type="text" value="2002-12-02 12:30:00"  />
 
 Note that a EditForm can't make use of a get_rendered method. The get_rendered
 method does only set initial values.



More information about the Checkins mailing list