[Python-checkins] r87845 - in python/branches/py3k: Lib/test/test_time.py Modules/timemodule.c

victor.stinner python-checkins at python.org
Sat Jan 8 02:56:31 CET 2011


Author: victor.stinner
Date: Sat Jan  8 02:56:31 2011
New Revision: 87845

Log:
Issue #1777412: strftime() accepts year >= 1 instead of year >= 1900

 * With Visual Studio, year have to be in [1; 9999]
 * Add more tests on the year field

Modified:
   python/branches/py3k/Lib/test/test_time.py
   python/branches/py3k/Modules/timemodule.c

Modified: python/branches/py3k/Lib/test/test_time.py
==============================================================================
--- python/branches/py3k/Lib/test/test_time.py	(original)
+++ python/branches/py3k/Lib/test/test_time.py	Sat Jan  8 02:56:31 2011
@@ -43,14 +43,8 @@
         # Make sure that strftime() checks the bounds of the various parts
         #of the time tuple (0 is valid for *all* values).
 
-        # Check year [1900, max(int)]
-        self.assertRaises(ValueError, func,
-                            (999, 1, 1, 0, 0, 0, 0, 1, -1))
-        if time.accept2dyear:
-            self.assertRaises(ValueError, func,
-                                (-1, 1, 1, 0, 0, 0, 0, 1, -1))
-            self.assertRaises(ValueError, func,
-                                (100, 1, 1, 0, 0, 0, 0, 1, -1))
+        # The year field is tested by other test cases above
+
         # Check month [1, 12] + zero support
         self.assertRaises(ValueError, func,
                             (1900, -1, 1, 0, 0, 0, 0, 1, -1))
@@ -267,8 +261,10 @@
         # This should not cause an exception
         time.strftime("%B", (2009,2,1,0,0,0,0,0,0))
 
-class TestAccept2Year(unittest.TestCase):
-    accept2dyear = 1
+
+class _BaseYearTest(unittest.TestCase):
+    accept2dyear = None
+
     def setUp(self):
         self.saved_accept2dyear = time.accept2dyear
         time.accept2dyear = self.accept2dyear
@@ -277,10 +273,37 @@
         time.accept2dyear = self.saved_accept2dyear
 
     def yearstr(self, y):
-        # return time.strftime('%Y', (y,) + (0,) * 8)
+        raise NotImplementedError()
+
+class _TestAsctimeYear:
+    def yearstr(self, y):
         return time.asctime((y,) + (0,) * 8).split()[-1]
 
-    def test_2dyear(self):
+    def test_large_year(self):
+        # Check that it doesn't crash with year > 9999
+        self.assertEqual(self.yearstr(12345), '12345')
+        self.assertEqual(self.yearstr(123456789), '123456789')
+
+class _TestStrftimeYear:
+    def yearstr(self, y):
+        return time.strftime('%Y', (y,) + (0,) * 8).split()[-1]
+
+    def test_large_year(self):
+        # Just check that it doesn't crash with year > 9999: it may or may not
+        # raise an error depending on the OS and compiler
+        try:
+            self.yearstr(12345)
+        except ValueError:
+            pass
+        try:
+            self.yearstr(123456)
+        except ValueError:
+            pass
+
+class _Test2dYear(_BaseYearTest):
+    accept2dyear = 1
+
+    def test_year(self):
         with support.check_warnings():
             self.assertEqual(self.yearstr(0), '2000')
             self.assertEqual(self.yearstr(69), '1969')
@@ -288,27 +311,41 @@
             self.assertEqual(self.yearstr(99), '1999')
 
     def test_invalid(self):
-        self.assertRaises(ValueError, self.yearstr, 999)
-        self.assertRaises(ValueError, self.yearstr, 100)
         self.assertRaises(ValueError, self.yearstr, -1)
+        self.assertRaises(ValueError, self.yearstr, 100)
+        self.assertRaises(ValueError, self.yearstr, 999)
 
-class TestAccept2YearBool(TestAccept2Year):
-    accept2dyear = True
-
-class TestDontAccept2Year(TestAccept2Year):
+class _Test4dYear(_BaseYearTest):
     accept2dyear = 0
-    def test_2dyear(self):
-        self.assertEqual(self.yearstr(0), '0')
+
+    def test_year(self):
+        self.assertEqual(self.yearstr(1), '1')
         self.assertEqual(self.yearstr(69), '69')
         self.assertEqual(self.yearstr(68), '68')
         self.assertEqual(self.yearstr(99), '99')
         self.assertEqual(self.yearstr(999), '999')
         self.assertEqual(self.yearstr(9999), '9999')
 
-    def test_invalid(self):
-        pass
+class TestAsctimeAccept2dYear(_TestAsctimeYear, _Test2dYear):
+    pass
+
+class TestStrftimeAccept2dYear(_TestStrftimeYear, _Test2dYear):
+    pass
 
-class TestAccept2YearBad(TestAccept2Year):
+class TestAsctime4dyear(_TestAsctimeYear, _Test4dYear):
+    pass
+
+class TestStrftime4dyear(_TestStrftimeYear, _Test4dYear):
+    def test_bounds(self):
+        self.assertRaises(ValueError, self.yearstr, 0)
+
+class Test2dyearBool(_TestAsctimeYear, _Test2dYear):
+    accept2dyear = True
+
+class Test4dyearBool(_TestAsctimeYear, _Test4dYear):
+    accept2dyear = False
+
+class TestAccept2YearBad(_TestAsctimeYear, _BaseYearTest):
     class X:
         def __bool__(self):
             raise RuntimeError('boo')
@@ -319,14 +356,17 @@
         self.assertRaises(RuntimeError, self.yearstr, 200)
 
 
-class TestDontAccept2YearBool(TestDontAccept2Year):
-    accept2dyear = False
-
-
 def test_main():
-    support.run_unittest(TimeTestCase, TestLocale,
-                         TestAccept2Year, TestAccept2YearBool, TestAccept2YearBad,
-                         TestDontAccept2Year, TestDontAccept2YearBool)
+    support.run_unittest(
+        TimeTestCase,
+        TestLocale,
+        TestAsctimeAccept2dYear,
+        TestStrftimeAccept2dYear,
+        TestAsctime4dyear,
+        TestStrftime4dyear,
+        Test2dyearBool,
+        Test4dyearBool,
+        TestAccept2YearBad)
 
 if __name__ == "__main__":
     test_main()

Modified: python/branches/py3k/Modules/timemodule.c
==============================================================================
--- python/branches/py3k/Modules/timemodule.c	(original)
+++ python/branches/py3k/Modules/timemodule.c	Sat Jan  8 02:56:31 2011
@@ -474,15 +474,21 @@
     else if (!gettmarg(tup, &buf) || !checktm(&buf))
         return NULL;
 
-    /* XXX: Reportedly, some systems have issues formating dates prior to year
-     * 1000.  These systems should be identified and this check should be
-     * moved to appropriate system specific section below. */
-    if (buf.tm_year < -900) {
-        PyErr_Format(PyExc_ValueError, "year=%d is before 1900; "
-                     "the strftime() method requires year >= 1900",
+#ifdef _MSC_VER
+    if (buf.tm_year + 1900 < 1 || 9999 < buf.tm_year + 1900) {
+        PyErr_Format(PyExc_ValueError,
+                     "strftime() requires year in [1; 9999]",
                      buf.tm_year + 1900);
         return NULL;
     }
+#else
+    if (buf.tm_year + 1900 < 1) {
+        PyErr_Format(PyExc_ValueError,
+                     "strftime() requires year >= 1",
+                     buf.tm_year + 1900);
+        return NULL;
+    }
+#endif
 
     /* Normalize tm_isdst just in case someone foolishly implements %Z
        based on the assumption that tm_isdst falls within the range of


More information about the Python-checkins mailing list