[pypy-svn] r64482 - in pypy/trunk/pypy: module/posix rlib rpython/module rpython/module/test

afa at codespeak.net afa at codespeak.net
Tue Apr 21 03:30:55 CEST 2009


Author: afa
Date: Tue Apr 21 03:30:53 2009
New Revision: 64482

Modified:
   pypy/trunk/pypy/module/posix/interp_posix.py
   pypy/trunk/pypy/rlib/rwin32.py
   pypy/trunk/pypy/rpython/module/ll_os.py
   pypy/trunk/pypy/rpython/module/ll_os_stat.py
   pypy/trunk/pypy/rpython/module/test/test_ll_os.py
Log:
On Windows, os.utime now calls the win32 API function SetFileTime.
This should fix the failure in test_os


Modified: pypy/trunk/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/trunk/pypy/module/posix/interp_posix.py	(original)
+++ pypy/trunk/pypy/module/posix/interp_posix.py	Tue Apr 21 03:30:53 2009
@@ -544,12 +544,6 @@
 Set the access and modified time of the file to the given values.  If the
 second form is used, set the access and modified times to the current time.
     """
-    # XXX for now, ignore calls on directories on Windows,
-    # just because they always give EACCES so far
-    if _WIN:
-        if os.path.isdir(path):
-            return
-
     if space.is_w(w_tuple, space.w_None):
         try:
             os.utime(path, None)

Modified: pypy/trunk/pypy/rlib/rwin32.py
==============================================================================
--- pypy/trunk/pypy/rlib/rwin32.py	(original)
+++ pypy/trunk/pypy/rlib/rwin32.py	Tue Apr 21 03:30:53 2009
@@ -42,6 +42,8 @@
         FILETIME = rffi_platform.Struct('FILETIME',
                                         [('dwLowDateTime', rffi.UINT),
                                          ('dwHighDateTime', rffi.UINT)])
+        SYSTEMTIME = rffi_platform.Struct('SYSTEMTIME',
+                                          [])
 
         LPSECURITY_ATTRIBUTES = rffi_platform.SimpleType(
             "LPSECURITY_ATTRIBUTES", rffi.CCHARP)
@@ -76,6 +78,7 @@
     FreeLibrary = winexternal('FreeLibrary', [rffi.VOIDP], BOOL)
 
     LocalFree = winexternal('LocalFree', [HLOCAL], DWORD)
+    CloseHandle = winexternal('CloseHandle', [HANDLE], lltype.Void)
 
     FormatMessage = winexternal(
         'FormatMessageA',

Modified: pypy/trunk/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/trunk/pypy/rpython/module/ll_os.py	(original)
+++ pypy/trunk/pypy/rpython/module/ll_os.py	Tue Apr 21 03:30:53 2009
@@ -31,12 +31,17 @@
 posix = __import__(os.name)
 
 if sys.platform.startswith('win'):
+    _WIN32 = True
+else:
+    _WIN32 = False
+
+if _WIN32:
     underscore_on_windows = '_'
 else:
     underscore_on_windows = ''
 
 includes = []
-if not sys.platform.startswith('win'):
+if not _WIN32:
     # XXX many of these includes are not portable at all
     includes += ['dirent.h', 'sys/stat.h',
                  'sys/times.h', 'utime.h', 'sys/types.h', 'unistd.h',
@@ -60,7 +65,7 @@
     _compilation_info_ = ExternalCompilationInfo(
         includes=includes
     )
-    if not sys.platform.startswith('win'):
+    if not _WIN32:
         CLOCK_T = platform.SimpleType('clock_t', rffi.INT)
 
         TMS = platform.Struct(
@@ -320,18 +325,97 @@
                 lltype.free(l_utimbuf, flavor='raw')
                 return error
 
-        def os_utime_llimpl(path, tp):
-            # NB. this function is specialized; we get one version where
-            # tp is known to be None, and one version where it is known
-            # to be a tuple of 2 floats.
-            if tp is None:
-                error = os_utime(path, lltype.nullptr(UTIMBUFP.TO))
-            else:
-                actime, modtime = tp
-                error = os_utime_platform(path, actime, modtime)
-            error = rffi.cast(lltype.Signed, error)
-            if error == -1:
-                raise OSError(rposix.get_errno(), "os_utime failed")
+        # NB. this function is specialized; we get one version where
+        # tp is known to be None, and one version where it is known
+        # to be a tuple of 2 floats.
+        if not _WIN32:
+            def os_utime_llimpl(path, tp):
+                if tp is None:
+                    error = os_utime(path, lltype.nullptr(UTIMBUFP.TO))
+                else:
+                    actime, modtime = tp
+                    error = os_utime_platform(path, actime, modtime)
+                    error = rffi.cast(lltype.Signed, error)
+                if error == -1:
+                    raise OSError(rposix.get_errno(), "os_utime failed")
+        else:
+            from pypy.rlib import rwin32
+            from pypy.rpython.module.ll_os_stat import time_t_to_FILE_TIME
+
+            class CConfig:
+                _compilation_info_ = ExternalCompilationInfo(
+                    includes = ['windows.h'],
+                    )
+
+                FILE_WRITE_ATTRIBUTES = platform.ConstantInteger(
+                    'FILE_WRITE_ATTRIBUTES')
+                OPEN_EXISTING = platform.ConstantInteger(
+                    'OPEN_EXISTING')
+                FILE_FLAG_BACKUP_SEMANTICS = platform.ConstantInteger(
+                    'FILE_FLAG_BACKUP_SEMANTICS')
+            globals().update(platform.configure(CConfig))
+
+            CreateFile = rffi.llexternal(
+                'CreateFileA',
+                [rwin32.LPCSTR, rwin32.DWORD, rwin32.DWORD,
+                 rwin32.LPSECURITY_ATTRIBUTES, rwin32.DWORD, rwin32.DWORD,
+                 rwin32.HANDLE],
+                rwin32.HANDLE,
+                calling_conv='win')
+
+            GetSystemTime = rffi.llexternal(
+                'GetSystemTime',
+                [lltype.Ptr(rwin32.SYSTEMTIME)],
+                lltype.Void,
+                calling_conv='win')
+
+            SystemTimeToFileTime = rffi.llexternal(
+                'SystemTimeToFileTime',
+                [lltype.Ptr(rwin32.SYSTEMTIME),
+                 lltype.Ptr(rwin32.FILETIME)],
+                rwin32.BOOL,
+                calling_conv='win')
+
+            SetFileTime = rffi.llexternal(
+                'SetFileTime',
+                [rwin32.HANDLE,
+                 lltype.Ptr(rwin32.FILETIME),
+                 lltype.Ptr(rwin32.FILETIME),
+                 lltype.Ptr(rwin32.FILETIME)],
+                rwin32.BOOL,
+                calling_conv = 'win')
+
+            def os_utime_llimpl(path, tp):
+                hFile = CreateFile(path, 
+                                   FILE_WRITE_ATTRIBUTES, 0, 
+                                   None, OPEN_EXISTING,
+                                   FILE_FLAG_BACKUP_SEMANTICS, 0)
+                if hFile == rwin32.INVALID_HANDLE_VALUE:
+                    raise rwin32.lastWindowsError()
+                ctime = lltype.nullptr(rwin32.FILETIME)
+                atime = lltype.malloc(rwin32.FILETIME, flavor='raw')
+                mtime = lltype.malloc(rwin32.FILETIME, flavor='raw')
+                try:
+                    if tp is None:
+                        now = lltype.malloc(lltype.Ptr(rwin32.SYSTEMTIME),
+                                            flavor='raw')
+                        try:
+                            GetSystemTime(now)
+                            if (not SystemTimeToFileTime(now, atime) or
+                                not SystemTimeToFileTime(now, mtime)):
+                                raise rwin32.lastWindowsError()
+                        finally:
+                            lltype.free(now, flavor='raw')
+                    else:
+                        actime, modtime = tp
+                        time_t_to_FILE_TIME(actime, atime)
+                        time_t_to_FILE_TIME(modtime, mtime)
+                    if not SetFileTime(hFile, ctime, atime, mtime):
+                        raise rwin32.lastWindowsError()
+                finally:
+                    rwin32.CloseHandle(hFile)
+                    lltype.free(atime, flavor='raw')
+                    lltype.free(mtime, flavor='raw')
         os_utime_llimpl._annspecialcase_ = 'specialize:argtype(1)'
 
         s_string = SomeString()

Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py
==============================================================================
--- pypy/trunk/pypy/rpython/module/ll_os_stat.py	(original)
+++ pypy/trunk/pypy/rpython/module/ll_os_stat.py	Tue Apr 21 03:30:53 2009
@@ -398,6 +398,11 @@
         time = (ft / 10000000) - secs_between_epochs
         return time, nsec
 
+    def time_t_to_FILE_TIME(time, filetime):
+        ft = lltype.r_longlong((time + secs_between_epochs) * 10000000)
+        filetime.c_dwHighDateTime = lltype.r_uint(ft >> 32)
+        filetime.c_dwLowDateTime = lltype.r_uint(ft & ((1 << 32) - 1))
+        
     def attribute_data_to_stat(info):
         st_mode = attributes_to_mode(info.c_dwFileAttributes)
         st_size = make_longlong(info.c_nFileSizeHigh, info.c_nFileSizeLow)

Modified: pypy/trunk/pypy/rpython/module/test/test_ll_os.py
==============================================================================
--- pypy/trunk/pypy/rpython/module/test/test_ll_os.py	(original)
+++ pypy/trunk/pypy/rpython/module/test/test_ll_os.py	Tue Apr 21 03:30:53 2009
@@ -35,6 +35,19 @@
     for value in times:
         assert isinstance(value, float)
 
+def test_utimes():
+    if os.name != 'nt':
+        py.test.skip('Windows specific feature')
+    # Windows support centiseconds
+    def f(fname, t1):
+        os.utime(fname, (t1, t1))
+
+    fname = udir.join('test_utimes.txt')
+    fname.ensure()
+    t1 = 1159195039.25
+    compile(f, (str, float))(str(fname), t1)
+    assert t1 == os.stat(str(fname)).st_mtime
+
 def test__getfullpathname():
     if os.name != 'nt':
         py.test.skip('nt specific function')



More information about the Pypy-commit mailing list