[pypy-svn] r30146 - in pypy/dist/pypy/module/rctime: . test

rhymes at codespeak.net rhymes at codespeak.net
Tue Jul 18 13:03:41 CEST 2006


Author: rhymes
Date: Tue Jul 18 13:03:24 2006
New Revision: 30146

Modified:
   pypy/dist/pypy/module/rctime/__init__.py
   pypy/dist/pypy/module/rctime/interp_time.py
   pypy/dist/pypy/module/rctime/test/test_rctime.py
Log:
added strftime() support.


Modified: pypy/dist/pypy/module/rctime/__init__.py
==============================================================================
--- pypy/dist/pypy/module/rctime/__init__.py	(original)
+++ pypy/dist/pypy/module/rctime/__init__.py	Tue Jul 18 13:03:24 2006
@@ -15,7 +15,8 @@
         'gmtime': 'interp_time.gmtime',
         'localtime': 'interp_time.localtime',
         'mktime': 'interp_time.mktime',
-        'tzset': 'interp_time.tzset'
+        'tzset': 'interp_time.tzset',
+        'strftime': 'interp_time.strftime',
     }
 
     # def init(self, space):

Modified: pypy/dist/pypy/module/rctime/interp_time.py
==============================================================================
--- pypy/dist/pypy/module/rctime/interp_time.py	(original)
+++ pypy/dist/pypy/module/rctime/interp_time.py	Tue Jul 18 13:03:24 2006
@@ -25,6 +25,7 @@
     CLOCKS_PER_SEC = ctypes_platform.ConstantInteger("CLOCKS_PER_SEC")
     clock_t = ctypes_platform.SimpleType("clock_t", c_ulong)
     time_t = ctypes_platform.SimpleType("time_t", c_long)
+    size_t = ctypes_platform.SimpleType("time_t", c_long)
 
 class cConfig:
     pass
@@ -35,6 +36,7 @@
 CLOCKS_PER_SEC = cConfig.CLOCKS_PER_SEC
 clock_t = cConfig.clock_t
 time_t = cConfig.time_t
+size_t = cConfig.size_t
 timeval = cConfig.timeval
 tm = cConfig.tm
 
@@ -59,6 +61,8 @@
 libc.asctime.argtypes = [POINTER(tm)]
 libc.asctime.restype = c_char_p
 libc.tzset.restype = None # tzset() returns void
+libc.strftime.argtypes = [c_char_p, size_t, c_char_p, POINTER(tm)]
+libc.strftime.restype = size_t
 
 def _init_accept2dyear():
     return (1, 0)[bool(os.getenv("PYTHONY2K"))]
@@ -413,3 +417,92 @@
         _set_module_list_object(space, 'tzname', tzname_w)
         _set_module_object(space, 'altzone', altzone)
     tzset.unwrap_spec = [ObjSpace]
+
+def strftime(space, w_format, w_tup=None):
+    """strftime(format[, tuple]) -> string
+
+    Convert a time tuple to a string according to a format specification.
+    See the library reference manual for formatting codes. When the time tuple
+    is not present, current time as returned by localtime() is used."""
+    
+    tup = None
+    tuple_len = 0
+    buf_value = tm()
+    
+    format = space.str_w(w_format)
+    
+    # if len(tup_w):
+    #     w_tup = tup_w[0]
+    if not space.is_w(w_tup, space.w_None):
+        tuple_len = space.int_w(space.len(w_tup))
+        
+        #if space.is_w(w_tup, space.w_None) or 1 < tuple_len < 9:
+        if 1 < tuple_len < 9:
+            raise OperationError(space.w_TypeError, 
+                space.wrap("argument must be 9-item sequence"))
+
+        # check if every passed object is a int
+        tup = space.unpackiterable(w_tup)
+        for t in tup:
+            space.int_w(t)
+        # map(space.int_w, tup) # XXX: can't use it
+        
+        buf_value = _gettmarg(space, tup, buf_value)
+    else:
+        # empty list
+        buf = None
+        
+        tt = time_t(int(_floattime())) 
+        buf = libc.localtime(byref(tt))
+        if not buf:
+            raise OperationError(space.w_ValueError,
+                space.wrap(_get_error_msg()))
+        buf_value = buf.contents
+
+    # Checks added to make sure strftime() does not crash Python by
+    # indexing blindly into some array for a textual representation
+    # by some bad index (fixes bug #897625).
+    # No check for year since handled in gettmarg().
+    if buf_value.tm_mon < 0 or buf_value.tm_mon > 11:
+        raise OperationError(space.w_ValueError,
+            space.wrap("month out of range"))
+    if buf_value.tm_mday < 1 or buf_value.tm_mday > 31:
+        raise OperationError(space.w_ValueError,
+            space.wrap("day of month out of range"))
+    if buf_value.tm_hour < 0 or buf_value.tm_hour > 23:
+        raise OperationError(space.w_ValueError,
+            space.wrap("hour out of range"))
+    if buf_value.tm_min < 0 or buf_value.tm_min > 59:
+        raise OperationError(space.w_ValueError,
+            space.wrap("minute out of range"))
+    if buf_value.tm_sec < 0 or buf_value.tm_sec > 61:
+        raise OperationError(space.w_ValueError,
+            space.wrap("seconds out of range"))
+    # tm_wday does not need checking of its upper-bound since taking
+    #   "% 7" in gettmarg() automatically restricts the range.
+    if buf_value.tm_wday < 0:
+        raise OperationError(space.w_ValueError,
+            space.wrap("day of week out of range"))
+    if buf_value.tm_yday < 0 or buf_value.tm_yday > 365:
+        raise OperationError(space.w_ValueError,
+            space.wrap("day of year out of range"))
+    if buf_value.tm_isdst < -1 or buf_value.tm_isdst > 1:
+        raise OperationError(space.w_ValueError,
+            space.wrap("daylight savings flag out of range"))
+
+    i = 1024
+    while True:
+        outbuf = create_string_buffer(i)
+        buflen = libc.strftime(outbuf, i, format, byref(buf_value))
+
+        if buflen > 0 or i >= 256 * len(format):
+            # if the buffer is 256 times as long as the format,
+            # it's probably not failing for lack of room!
+            # More likely, the format yields an empty result,
+            # e.g. an empty format, or %Z when the timezone
+            # is unknown.
+            if buflen > 0:
+                return space.wrap(outbuf.value[:buflen])
+
+        i += i
+strftime.unwrap_spec = [ObjSpace, W_Root, W_Root]

Modified: pypy/dist/pypy/module/rctime/test/test_rctime.py
==============================================================================
--- pypy/dist/pypy/module/rctime/test/test_rctime.py	(original)
+++ pypy/dist/pypy/module/rctime/test/test_rctime.py	Tue Jul 18 13:03:24 2006
@@ -190,55 +190,57 @@
             elif os.environ.has_key('TZ'):
                 del os.environ['TZ']
             rctime.tzset()
-        #     
-    # def test_strftime():
-    #     tt = rctime.gmtime(t)
-    #     for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I',
-    #                       'j', 'm', 'M', 'p', 'S',
-    #                       'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'):
-    #         format = ' %' + directive
-    #         assert rctime.strftime(format, tt) != None
-    #         assert rctime.strftime(format, tt) != ""
-    # 
-    # def test_strftime_bounds_checking():
-    #     # make sure that strftime() checks the bounds of the various parts
-    #     # of the time tuple.
-    # 
-    #     raises = py.test.raises
-    # 
-    #     # check year
-    #     raises(ValueError, rctime.strftime, '', (1899, 1, 1, 0, 0, 0, 0, 1, -1))
-    #     if rctime.accept2dyear:
-    #         raises(ValueError, rctime.strftime, '', (-1, 1, 1, 0, 0, 0, 0, 1, -1))
-    #         raises(ValueError, rctime.strftime, '', (100, 1, 1, 0, 0, 0, 0, 1, -1))
-    #     # check month
-    #     raises(ValueError, rctime.strftime, '', (1900, 0, 1, 0, 0, 0, 0, 1, -1))
-    #     raises(ValueError, rctime.strftime, '', (1900, 13, 1, 0, 0, 0, 0, 1, -1))
-    #     # check day of month
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 0, 0, 0, 0, 0, 1, -1))
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 32, 0, 0, 0, 0, 1, -1))
-    #     # check hour
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, -1, 0, 0, 0, 1, -1))
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, 24, 0, 0, 0, 1, -1))
-    #     # check minute
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, -1, 0, 0, 1, -1))
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 60, 0, 0, 1, -1))
-    #     # check second
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, -1, 0, 1, -1))
-    #     # C99 only requires allowing for one leap second, but Python's docs say
-    #     # allow two leap seconds (0..61)
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 62, 0, 1, -1))
-    #     # no check for upper-bound day of week;
-    #     #  value forced into range by a "% 7" calculation.
-    #     # start check at -2 since gettmarg() increments value before taking
-    #     #  modulo.
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, -2, 1, -1))
-    #     # check day of the year
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, 0, 0, -1))
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, 0, 367, -1))
-    #     # check daylight savings flag
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, 0, 1, -2))
-    #     raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, 0, 1, 2))
+            
+    def test_strftime(self):
+        import rctime
+        
+        t = rctime.time()
+        tt = rctime.gmtime(t)
+        for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I',
+                          'j', 'm', 'M', 'p', 'S',
+                          'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'):
+            format = ' %' + directive
+            rctime.strftime(format, tt)
+
+    def test_strftime_bounds_checking(self):
+        import rctime
+        
+        # make sure that strftime() checks the bounds of the various parts
+        # of the time tuple.
+    
+        # check year
+        raises(ValueError, rctime.strftime, '', (1899, 1, 1, 0, 0, 0, 0, 1, -1))
+        if rctime.accept2dyear:
+            raises(ValueError, rctime.strftime, '', (-1, 1, 1, 0, 0, 0, 0, 1, -1))
+            raises(ValueError, rctime.strftime, '', (100, 1, 1, 0, 0, 0, 0, 1, -1))
+        # check month
+        raises(ValueError, rctime.strftime, '', (1900, 0, 1, 0, 0, 0, 0, 1, -1))
+        raises(ValueError, rctime.strftime, '', (1900, 13, 1, 0, 0, 0, 0, 1, -1))
+        # check day of month
+        raises(ValueError, rctime.strftime, '', (1900, 1, 0, 0, 0, 0, 0, 1, -1))
+        raises(ValueError, rctime.strftime, '', (1900, 1, 32, 0, 0, 0, 0, 1, -1))
+        # check hour
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, -1, 0, 0, 0, 1, -1))
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, 24, 0, 0, 0, 1, -1))
+        # check minute
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, -1, 0, 0, 1, -1))
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 60, 0, 0, 1, -1))
+        # check second
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, -1, 0, 1, -1))
+        # C99 only requires allowing for one leap second, but Python's docs say
+        # allow two leap seconds (0..61)
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 62, 0, 1, -1))
+        # no check for upper-bound day of week;
+        #  value forced into range by a "% 7" calculation.
+        # start check at -2 since gettmarg() increments value before taking
+        #  modulo.
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, -2, 1, -1))
+        # check day of the year
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, 0, 0, -1))
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, 0, 367, -1))
+        # check daylight savings flag
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, 0, 1, -2))
+        raises(ValueError, rctime.strftime, '', (1900, 1, 1, 0, 0, 0, 0, 1, 2))
     # 
     # def test_strptime():
     #     tt = rctime.gmtime(t)



More information about the Pypy-commit mailing list