[pypy-svn] r64629 - in pypy/branch/unicode_filename/pypy: interpreter module/posix rlib rpython/lltypesystem rpython/module

afa at codespeak.net afa at codespeak.net
Fri Apr 24 12:05:28 CEST 2009


Author: afa
Date: Fri Apr 24 12:05:27 2009
New Revision: 64629

Modified:
   pypy/branch/unicode_filename/pypy/interpreter/error.py
   pypy/branch/unicode_filename/pypy/module/posix/interp_posix.py
   pypy/branch/unicode_filename/pypy/rlib/rwin32.py
   pypy/branch/unicode_filename/pypy/rpython/lltypesystem/rffi.py
   pypy/branch/unicode_filename/pypy/rpython/module/ll_os.py
Log:
adapt os.utime and nt._getfullpathname
+ some refactoring


Modified: pypy/branch/unicode_filename/pypy/interpreter/error.py
==============================================================================
--- pypy/branch/unicode_filename/pypy/interpreter/error.py	(original)
+++ pypy/branch/unicode_filename/pypy/interpreter/error.py	Fri Apr 24 12:05:27 2009
@@ -4,6 +4,8 @@
 AUTO_DEBUG = os.getenv('PYPY_DEBUG')
 RECORD_INTERPLEVEL_TRACEBACK = True
 
+_WIN32 = sys.platform == 'win32'
+
 
 class OperationError(Exception):
     """Interpreter-level exception that signals an exception that should be
@@ -262,16 +264,21 @@
     # 31: ANSI color code "red"
     ansi_print(text, esc="31", file=file, newline=newline)
 
-def wrap_oserror(space, e, exception_name='w_OSError'): 
-    assert isinstance(e, OSError) 
-    errno = e.errno
-    try:
-        msg = os.strerror(errno)
-    except ValueError:
-        msg = 'error %d' % errno
-    exc = getattr(space, exception_name)
+def wrap_oserror(space, e, exception_name='w_OSError'):
+    assert isinstance(e, OSError)
+    if _WIN32 and isinstance(e, WindowsError):
+        error = e.winerror
+        msg = e.strerror
+        exc = space.w_WindowsError
+    else:
+        error = e.errno
+        try:
+            msg = os.strerror(error)
+        except ValueError:
+            msg = 'error %d' % error
+        exc = getattr(space, exception_name)
     w_error = space.call_function(exc,
-                                  space.wrap(errno),
+                                  space.wrap(error),
                                   space.wrap(msg))
     return OperationError(exc, w_error)
 wrap_oserror._annspecialcase_ = 'specialize:arg(2)'

Modified: pypy/branch/unicode_filename/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/unicode_filename/pypy/module/posix/interp_posix.py	(original)
+++ pypy/branch/unicode_filename/pypy/module/posix/interp_posix.py	Fri Apr 24 12:05:27 2009
@@ -16,10 +16,9 @@
     """Open a file (for low level IO).
 Return a file descriptor (a small integer)."""
     try: 
-        fd = wrapper(os.open)(space, w_path, (flag, mode))
+        return unicodepath_wrapper(os.open)(space, w_path, (flag, mode))
     except OSError, e: 
         raise wrap_oserror(space, e) 
-    return space.wrap(fd)
 open.unwrap_spec = [ObjSpace, W_Root, int, int]
 
 def lseek(space, fd, pos, how):
@@ -146,15 +145,24 @@
 fstat.unwrap_spec = [ObjSpace, int]
 
 if WIDE_FILENAMES:
-    def wrapper(fn):
-        impl = extregistry.lookup(fn).lltypeimpl
+    def unicodepath_wrapper(fn, wrap=None):
+        extfunc = extregistry.lookup(fn)
+        impl = extfunc.lltypeimpl
+
+        def w(space, result):
+            if wrap is None:
+                return space.wrap(result)
+            else:
+                return wrap(space, result)
+
         def f(space, w_path, args):
             if space.is_true(space.isinstance(w_path, space.w_unicode)):
-                return impl(space.unicode_w(w_path), *args)
+                return w(space, impl(space.unicode_w(w_path), *args))
             else:
-                return impl(space.str_w(w_path), *args)
+                return w(space, impl(space.str_w(w_path), *args))
+
         return f
-    def wrapper2(fn):
+    def unicodepath_wrapper2(fn):
         impl = extregistry.lookup(fn).lltypeimpl
 
         from pypy.objspace.std.unicodetype import decode_object
@@ -177,16 +185,22 @@
             return impl(space.str_w(w_path1), space.str_w(w_path2), *args)
         return f
 else:
-    def wrapper(fn):
+    def unicodepath_wrapper(fn, wrap=None):
+        def w(space, result):
+            if wrap is None:
+                return space.wrap(result)
+            else:
+                return wrap(space, result)
+
         def f(space, w_path, args):
-            return fn(space.str_w(w_path), *args)
+            return w(space, fn(space.str_w(w_path), *args))
         return f
-    def wrapper2(fn):
+    def unicodepath_wrapper2(fn):
         def f(space, w_path1, w_path2, args):
             return fn(space.str_w(w_path1), space.str_w(w_path2), *args)
         return f
-wrapper._annspecialcase_ = 'specialize:memo'
-wrapper2._annspecialcase_ = 'specialize:memo'
+unicodepath_wrapper._annspecialcase_ = 'specialize:memo'
+unicodepath_wrapper2._annspecialcase_ = 'specialize:memo'
 
 def stat(space, w_path):
     """Perform a stat system call on the given path.  Return an object
@@ -204,21 +218,19 @@
 """
 
     try:
-        st = wrapper(os.stat)(space, w_path, ())
+        return unicodepath_wrapper(os.stat, wrap=build_stat_result)(
+            space, w_path, ())
     except OSError, e: 
         raise wrap_oserror(space, e) 
-    else: 
-        return build_stat_result(space, st)
 stat.unwrap_spec = [ObjSpace, W_Root]
 
 def lstat(space, w_path):
     "Like stat(path), but do no follow symbolic links."
     try:
-        st = wrapper(os.lstat)(space, w_path, ())
+        return unicodepath_wrapper(os.lstat, wrap=build_stat_result)(
+            space, w_path, ())
     except OSError, e:
         raise wrap_oserror(space, e)
-    else:
-        return build_stat_result(space, st)
 lstat.unwrap_spec = [ObjSpace, W_Root]
 
 class StatState(object):
@@ -271,11 +283,9 @@
     existence, or the inclusive-OR of R_OK, W_OK, and X_OK.
     """
     try:
-        ok = wrapper(os.access)(space, w_path, (mode,))
+        return unicodepath_wrapper(os.access)(space, w_path, (mode,))
     except OSError, e: 
         raise wrap_oserror(space, e) 
-    else:
-        return space.wrap(ok)
 access.unwrap_spec = [ObjSpace, W_Root, int]
 
 
@@ -310,7 +320,7 @@
 def unlink(space, w_path):
     """Remove a file (same as remove(path))."""
     try:
-        wrapper(os.unlink)(space, w_path, ())
+        return unicodepath_wrapper(os.unlink)(space, w_path, ())
     except OSError, e: 
         raise wrap_oserror(space, e) 
 unlink.unwrap_spec = [ObjSpace, W_Root]
@@ -318,21 +328,19 @@
 def remove(space, w_path):
     """Remove a file (same as unlink(path))."""
     try:
-        wrapper(os.unlink)(space, w_path, ())
+        return unicodepath_wrapper(os.unlink)(space, w_path, ())
     except OSError, e: 
         raise wrap_oserror(space, e) 
 remove.unwrap_spec = [ObjSpace, W_Root]
 
-def _getfullpathname(space, path):
+def _getfullpathname(space, w_path):
     """helper for ntpath.abspath """
     posix = __import__(os.name) # nt specific
     try:
-        fullpath = posix._getfullpathname(path)
+        return unicodepath_wrapper(posix._getfullpathname)(space, w_path, ())
     except OSError, e:
         raise wrap_oserror(space, e) 
-    else: 
-        return space.wrap(fullpath)
-_getfullpathname.unwrap_spec = [ObjSpace, str]
+_getfullpathname.unwrap_spec = [ObjSpace, W_Root]
 
 def getcwd(space):
     """Return the current working directory."""
@@ -357,7 +365,7 @@
 def chdir(space, w_path):
     """Change the current working directory to the specified path."""
     try:
-        wrapper(os.chdir)(space, w_path, ())
+        return unicodepath_wrapper(os.chdir)(space, w_path, ())
     except OSError, e: 
         raise wrap_oserror(space, e) 
 chdir.unwrap_spec = [ObjSpace, W_Root]
@@ -365,7 +373,7 @@
 def mkdir(space, w_path, mode=0777):
     """Create a directory."""
     try:
-        wrapper(os.mkdir)(space, w_path, (mode,))
+        return unicodepath_wrapper(os.mkdir)(space, w_path, (mode,))
     except OSError, e: 
         raise wrap_oserror(space, e) 
 mkdir.unwrap_spec = [ObjSpace, W_Root, int]
@@ -373,7 +381,7 @@
 def rmdir(space, w_path):
     """Remove a directory."""
     try:
-        wrapper(os.rmdir)(space, w_path, ())
+        return unicodepath_wrapper(os.rmdir)(space, w_path, ())
     except OSError, e: 
         raise wrap_oserror(space, e) 
 rmdir.unwrap_spec = [ObjSpace, W_Root]
@@ -465,7 +473,7 @@
 def chmod(space, w_path, mode):
     "Change the access permissions of a file."
     try: 
-        wrapper(os.chmod)(space, w_path, (mode,))
+        return unicodepath_wrapper(os.chmod)(space, w_path, (mode,))
     except OSError, e: 
         raise wrap_oserror(space, e) 
 chmod.unwrap_spec = [ObjSpace, W_Root, int]
@@ -473,8 +481,8 @@
 def rename(space, w_old, w_new):
     "Rename a file or directory."
     try:
-        wrapper2(os.rename)(space, w_old, w_new, ())
-    except OSError, e: 
+        unicodepath_wrapper2(os.rename)(space, w_old, w_new, ())
+    except OSError, e:
         raise wrap_oserror(space, e) 
 rename.unwrap_spec = [ObjSpace, W_Root, W_Root]
 
@@ -592,7 +600,7 @@
         raise wrap_oserror(space, e)
 execve.unwrap_spec = [ObjSpace, str, W_Root, W_Root]
 
-def utime(space, path, w_tuple):
+def utime(space, w_path, w_tuple):
     """ utime(path, (atime, mtime))
 utime(path, None)
 
@@ -601,8 +609,7 @@
     """
     if space.is_w(w_tuple, space.w_None):
         try:
-            os.utime(path, None)
-            return
+            return unicodepath_wrapper(os.utime)(space, w_path, (None,))
         except OSError, e:
             raise wrap_oserror(space, e)
     try:
@@ -612,14 +619,14 @@
             raise OperationError(space.w_TypeError, space.wrap(msg))
         actime = space.float_w(args_w[0])
         modtime = space.float_w(args_w[1])
-        os.utime(path, (actime, modtime))
+        return unicodepath_wrapper(os.utime)(space, w_path, ((actime, modtime),))
     except OSError, e:
         raise wrap_oserror(space, e)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
         raise OperationError(space.w_TypeError, space.wrap(msg))
-utime.unwrap_spec = [ObjSpace, str, W_Root]
+utime.unwrap_spec = [ObjSpace, W_Root, W_Root]
 
 def setsid(space):
     """setsid() -> pid

Modified: pypy/branch/unicode_filename/pypy/rlib/rwin32.py
==============================================================================
--- pypy/branch/unicode_filename/pypy/rlib/rwin32.py	(original)
+++ pypy/branch/unicode_filename/pypy/rlib/rwin32.py	Fri Apr 24 12:05:27 2009
@@ -34,6 +34,8 @@
         LPCVOID = rffi_platform.SimpleType("LPCVOID", rffi.VOIDP)
         LPSTR = rffi_platform.SimpleType("LPSTR", rffi.CCHARP)
         LPCSTR = rffi_platform.SimpleType("LPCSTR", rffi.CCHARP)
+        LPWSTR = rffi_platform.SimpleType("LPWSTR", rffi.CWCHARP)
+        LPCWSTR = rffi_platform.SimpleType("LPCWSTR", rffi.CWCHARP)
         LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP)
         SIZE_T = rffi_platform.SimpleType("SIZE_T", rffi.SIZE_T)
 
@@ -52,7 +54,9 @@
         DEFAULT_LANGUAGE = rffi_platform.ConstantInteger(
             "MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)")
 
-        for name in """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM
+        for name in """
+              FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM
+              MAX_PATH
               """.split():
             locals()[name] = rffi_platform.ConstantInteger(name)
 
@@ -109,7 +113,7 @@
         LocalFree(buf[0])
         return result
 
-    def lastWindowsError():
+    def lastWindowsError(context=None):
         code = GetLastError()
         message = FormatError(code)
         return WindowsError(code, message)

Modified: pypy/branch/unicode_filename/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/branch/unicode_filename/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/branch/unicode_filename/pypy/rpython/lltypesystem/rffi.py	Fri Apr 24 12:05:27 2009
@@ -691,6 +691,9 @@
 # char**
 CCHARPP = lltype.Ptr(lltype.Array(CCHARP, hints={'nolength': True}))
 
+# wchar_t**
+CWCHARPP = lltype.Ptr(lltype.Array(CWCHARP, hints={'nolength': True}))
+
 def liststr2charpp(l):
     """ list[str] -> char**, NULL terminated
     """

Modified: pypy/branch/unicode_filename/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/unicode_filename/pypy/rpython/module/ll_os.py	(original)
+++ pypy/branch/unicode_filename/pypy/rpython/module/ll_os.py	Fri Apr 24 12:05:27 2009
@@ -36,10 +36,18 @@
     _WIN32 = False
 
 if _WIN32:
+    from pypy.rlib import rwin32
+
     underscore_on_windows = '_'
+
+    def llos_exception(context):
+        return rwin32.lastWindowsError(context)
 else:
     underscore_on_windows = ''
 
+    def llos_exception(context):
+        return OSError(rposix.get_errno(), context + " failed")
+
 includes = []
 if not _WIN32:
     # XXX many of these includes are not portable at all
@@ -289,9 +297,6 @@
             HAVE_UTIMES = platform.Has('utimes')
         config = platform.configure(CConfig)
 
-        # XXX note that on Windows, calls to os.utime() are ignored on
-        # directories.  Remove that hack over there once it's fixed here!
-
         if config['HAVE_UTIMES']:
             class CConfig:
                 _compilation_info_ = ExternalCompilationInfo(
@@ -341,7 +346,6 @@
                 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:
@@ -357,7 +361,7 @@
                     'FILE_FLAG_BACKUP_SEMANTICS')
             globals().update(platform.configure(CConfig))
 
-            CreateFile = rffi.llexternal(
+            CreateFileA = rffi.llexternal(
                 'CreateFileA',
                 [rwin32.LPCSTR, rwin32.DWORD, rwin32.DWORD,
                  rwin32.LPSECURITY_ATTRIBUTES, rwin32.DWORD, rwin32.DWORD,
@@ -365,6 +369,14 @@
                 rwin32.HANDLE,
                 calling_conv='win')
 
+            CreateFileW = rffi.llexternal(
+                'CreateFileW',
+                [rwin32.LPCWSTR, 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)],
@@ -388,6 +400,10 @@
                 calling_conv = 'win')
 
             def os_utime_llimpl(path, tp):
+                if isinstance(path, str):
+                    CreateFile = CreateFileA
+                else:
+                    CreateFile = CreateFileW
                 hFile = CreateFile(path, 
                                    FILE_WRITE_ATTRIBUTES, 0, 
                                    None, OPEN_EXISTING,
@@ -417,7 +433,7 @@
                     rwin32.CloseHandle(hFile)
                     lltype.free(atime, flavor='raw')
                     lltype.free(mtime, flavor='raw')
-        os_utime_llimpl._annspecialcase_ = 'specialize:argtype(1)'
+        os_utime_llimpl._annspecialcase_ = 'specialize:argtype(0,1)'
 
         s_string = SomeString()
         s_tuple_of_2_floats = SomeTuple([SomeFloat(), SomeFloat()])
@@ -890,51 +906,40 @@
 
     @registering_if(posix, '_getfullpathname')
     def register_posix__getfullpathname(self):
-        # this nt function is not exposed via os, but needed
-        # to get a correct implementation of os.abspath
-        # XXX why do we ignore WINAPI conventions everywhere?
-        class CConfig:
-            _compilation_info_ = ExternalCompilationInfo(
-                includes = ['Windows.h']
-            )
-            MAX_PATH = platform.ConstantInteger('MAX_PATH')
-            DWORD    = platform.SimpleType("DWORD", rffi.ULONG)
-            LPCTSTR  = platform.SimpleType("LPCTSTR", rffi.CCHARP)
-            LPTSTR   = platform.SimpleType("LPTSTR", rffi.CCHARP)
-            LPTSTRP  = platform.SimpleType("LPTSTR*", rffi.CCHARPP)
-
-        config = platform.configure(CConfig)
-        MAX_PATH = config['MAX_PATH']
-        DWORD    = config['DWORD']
-        LPCTSTR  = config['LPCTSTR']
-        LPTSTR   = config['LPTSTR']
-        LPTSTRP  = config['LPTSTRP']
-        # XXX unicode?
-        GetFullPathName = self.llexternal('GetFullPathNameA',
-                         [LPCTSTR, DWORD, LPTSTR, LPTSTRP], DWORD)
-        GetLastError = self.llexternal('GetLastError', [], DWORD)
-        ##DWORD WINAPI GetFullPathName(
-        ##  __in          LPCTSTR lpFileName,
-        ##  __in          DWORD nBufferLength,
-        ##  __out         LPTSTR lpBuffer,
-        ##  __out         LPTSTR* lpFilePart
-        ##);
+        GetFullPathNameA = self.llexternal(
+            'GetFullPathNameA',
+            [rffi.CCHARP, rwin32.DWORD, rffi.CCHARP, rffi.CCHARPP],
+            rwin32.DWORD)
+        GetFullPathNameW = self.llexternal(
+            'GetFullPathNameW',
+            [rffi.CWCHARP, rwin32.DWORD, rffi.CWCHARP, rffi.CWCHARPP],
+            rwin32.DWORD)
 
         def _getfullpathname_llimpl(lpFileName):
-            nBufferLength = MAX_PATH + 1
+            if isinstance(lpFileName, str):
+                LPTSTR = rffi.CCHARP
+                LPTSTRP = rffi.CCHARPP
+                GetFullPathName = GetFullPathNameA
+                charp2str = rffi.charp2str
+            else:
+                LPTSTR = rffi.CWCHARP
+                LPTSTRP = rffi.CWCHARPP
+                GetFullPathName = GetFullPathNameW
+                charp2str = rffi.wcharp2unicode
+            nBufferLength = rwin32.MAX_PATH + 1
             lpBuffer = lltype.malloc(LPTSTR.TO, nBufferLength, flavor='raw')
             try:
                 res = GetFullPathName(
-                    lpFileName, rffi.cast(DWORD, nBufferLength),
+                    lpFileName, rffi.cast(rwin32.DWORD, nBufferLength),
                     lpBuffer, lltype.nullptr(LPTSTRP.TO))
                 if res == 0:
-                    error = GetLastError()
-                    raise OSError(error, "_getfullpathname failed")
+                    raise rwin32.lastWindowsError("_getfullpathname")
                 # XXX ntpath expects WindowsError :-(
-                result = rffi.charp2str(lpBuffer)
+                result = charp2str(lpBuffer)
                 return result
             finally:
                 lltype.free(lpBuffer, flavor='raw')
+        _getfullpathname_llimpl._annspecialcase_ = 'specialize:argtype(0)'
 
         return extdef([str],  # a single argument which is a str
                       str,    # returns a string
@@ -946,9 +951,11 @@
         if unicodepath:
             tp = unicode
             TP = rffi.CWCHARP
+            charp2str = rffi.charp2str
         else:
             tp = str
             TP = rffi.CCHARP
+            charp2str = rffi.wcharp2unicode
         os_getcwd = self.llexternal(underscore_on_windows + 'getcwd',
                                     [TP, rffi.SIZE_T],
                                     TP)
@@ -968,10 +975,7 @@
                 bufsize *= 4
                 if bufsize > 1024*1024:  # xxx hard-coded upper limit
                     raise OSError(error, "getcwd result too large")
-            if tp is str:
-                result = rffi.charp2str(res)
-            else:
-                result = rffi.wcharp2unicode(res)
+            result = charp2str(res)
             lltype.free(buf, flavor='raw')
             return result
 
@@ -1374,7 +1378,8 @@
 
     @registering(os.rename)
     def register_os_rename(self):
-        os_rename = self.llexternal(underscore_on_windows+'rename', [rffi.CCHARP, rffi.CCHARP],
+        # On windows the functions are: rename and _wrename
+        os_rename = self.llexternal('rename', [rffi.CCHARP, rffi.CCHARP],
                                     rffi.INT)
         os_wrename = self.llexternal(underscore_on_windows+'wrename', [rffi.CWCHARP, rffi.CWCHARP],
                                     rffi.INT)
@@ -1385,7 +1390,7 @@
             else:
                 res = rffi.cast(lltype.Signed, os_wrename(oldpath, newpath))
             if res < 0:
-                raise OSError(rposix.get_errno(), "os_rename failed")
+                raise llos_exception("os_rename")
         rename_llimpl._annspecialcase_ = 'specialize:argtype(0)'
 
         return extdef([str, str], s_None, llimpl=rename_llimpl,



More information about the Pypy-commit mailing list