[pypy-svn] r64565 - in pypy/branch/unicode_filename/pypy: module/posix rpython/lltypesystem rpython/module

afa at codespeak.net afa at codespeak.net
Wed Apr 22 02:05:23 CEST 2009


Author: afa
Date: Wed Apr 22 02:05:23 2009
New Revision: 64565

Modified:
   pypy/branch/unicode_filename/pypy/module/posix/interp_posix.py
   pypy/branch/unicode_filename/pypy/rpython/lltypesystem/rffi.py
   pypy/branch/unicode_filename/pypy/rpython/module/ll_os.py
   pypy/branch/unicode_filename/pypy/rpython/module/ll_os_stat.py
Log:
Start accepting both str and unicode for filenames.
This does not disturb the ll functions too much,

what I don't like is that functions like os.stat cannot have a _annspecialcase_ attribute;
the "wrapper" function has to fish the lltypeimpl function.


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	Wed Apr 22 02:05:23 2009
@@ -6,10 +6,11 @@
 from pypy.rpython.module.ll_os import RegisterOs
 from pypy.rpython.module import ll_os_stat
 from pypy.rpython.lltypesystem import lltype
+from pypy.rpython import extregistry
 
 import os, sys
 _WIN = sys.platform == 'win32'
-                          
+
 def open(space, fname, flag, mode=0777):
     """Open a file (for low level IO).
 Return a file descriptor (a small integer)."""
@@ -143,7 +144,23 @@
         return build_stat_result(space, st)
 fstat.unwrap_spec = [ObjSpace, int]
 
-def stat(space, path):
+if _WIN:
+    def wrapper(fn):
+        impl = extregistry.lookup(fn).lltypeimpl
+        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)
+            else:
+                return impl(space.str_w(w_path), *args)
+        return f
+else:
+    def wrapper(fn):
+        def f(space, w_path, args):
+            return fn(space.str_w(w_path), *args)
+        return f
+wrapper._annspecialcase_ = 'specialize:memo'
+
+def stat(space, w_path):
     """Perform a stat system call on the given path.  Return an object
 with (at least) the following attributes:
     st_mode
@@ -159,22 +176,22 @@
 """
 
     try:
-        st = os.stat(path)
+        st = wrapper(os.stat)(space, w_path, ())
     except OSError, e: 
         raise wrap_oserror(space, e) 
     else: 
         return build_stat_result(space, st)
-stat.unwrap_spec = [ObjSpace, str]
+stat.unwrap_spec = [ObjSpace, W_Root]
 
-def lstat(space, path):
+def lstat(space, w_path):
     "Like stat(path), but do no follow symbolic links."
     try:
-        st = os.lstat(path)
+        st = wrapper(os.lstat)(space, w_path, ())
     except OSError, e:
         raise wrap_oserror(space, e)
     else:
         return build_stat_result(space, st)
-lstat.unwrap_spec = [ObjSpace, str]
+lstat.unwrap_spec = [ObjSpace, W_Root]
 
 class StatState(object):
     def __init__(self, space):
@@ -299,21 +316,21 @@
         return space.wrap(cur)
 getcwd.unwrap_spec = [ObjSpace]
 
-def chdir(space, path):
+def chdir(space, w_path):
     """Change the current working directory to the specified path."""
     try:
-        os.chdir(path)
+        wrapper(os.chdir)(space, w_path, ())
     except OSError, e: 
         raise wrap_oserror(space, e) 
-chdir.unwrap_spec = [ObjSpace, str]
+chdir.unwrap_spec = [ObjSpace, W_Root]
 
-def mkdir(space, path, mode=0777):
+def mkdir(space, w_path, mode=0777):
     """Create a directory."""
     try:
-        os.mkdir(path, mode)
+        wrapper(os.mkdir)(space, w_path, (mode,))
     except OSError, e: 
         raise wrap_oserror(space, e) 
-mkdir.unwrap_spec = [ObjSpace, str, int]
+mkdir.unwrap_spec = [ObjSpace, W_Root, int]
 
 def rmdir(space, path):
     """Remove a directory."""

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	Wed Apr 22 02:05:23 2009
@@ -163,6 +163,17 @@
                     # XXX leaks if a str2charp() fails with MemoryError
                     # and was not the first in this function
                     freeme = arg
+
+            elif TARGET == CWCHARP:
+                if arg is None:
+                    arg = lltype.nullptr(CWCHARP.TO)   # None => (wchar_t*)NULL
+                    freeme = arg
+                elif isinstance(arg, unicode):
+                    arg = unicode2wcharp(arg)
+                    # XXX leaks if a str2charp() fails with MemoryError
+                    # and was not the first in this function
+                    freeme = arg
+
             elif _isfunctype(TARGET) and not _isllptr(arg):
                 # XXX pass additional arguments
                 if invoke_around_handlers:

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	Wed Apr 22 02:05:23 2009
@@ -1238,12 +1238,19 @@
 
     @registering(os.chdir)
     def register_os_chdir(self):
-        os_chdir = self.llexternal(underscore_on_windows+'chdir', [rffi.CCHARP], rffi.INT)
+        os_chdir = self.llexternal(underscore_on_windows+'chdir', 
+                                   [rffi.CCHARP], rffi.INT)
+        os_wchdir = self.llexternal(underscore_on_windows+'wchdir', 
+                                   [rffi.CWCHARP], rffi.INT)
 
         def chdir_llimpl(path):
-            res = rffi.cast(lltype.Signed, os_chdir(path))
+            if isinstance(path, str):
+                res = rffi.cast(lltype.Signed, os_chdir(path))
+            else:
+                res = rffi.cast(lltype.Signed, os_wchdir(path))
             if res < 0:
                 raise OSError(rposix.get_errno(), "os_chdir failed")
+        chdir_llimpl._annspecialcase_ = 'specialize:argtype(0)'
 
         return extdef([str], s_None, llimpl=chdir_llimpl,
                       export_name="ll_os.ll_os_chdir")
@@ -1256,16 +1263,23 @@
             ARG2 = [rffi.MODE_T]
         os_mkdir = self.llexternal(underscore_on_windows+'mkdir',
                                    [rffi.CCHARP]+ARG2, rffi.INT)
+        os_wmkdir = self.llexternal(underscore_on_windows+'wmkdir',
+                                   [rffi.CWCHARP]+ARG2, rffi.INT)
         IGNORE_MODE = len(ARG2) == 0
 
         def mkdir_llimpl(pathname, mode):
+            if isinstance(pathname, str):
+                mkdir = os_mkdir
+            else:
+                mkdir = os_wmkdir
             if IGNORE_MODE:
-                res = os_mkdir(pathname)
+                res = mkdir(pathname)
             else:
-                res = os_mkdir(pathname, mode)
+                res = mkdir(pathname, mode)
             res = rffi.cast(lltype.Signed, res)
             if res < 0:
                 raise OSError(rposix.get_errno(), "os_mkdir failed")
+        mkdir_llimpl._annspecialcase_ = 'specialize:argtype(0)'
 
         return extdef([str, int], s_None, llimpl=mkdir_llimpl,
                       export_name="ll_os.ll_os_mkdir")

Modified: pypy/branch/unicode_filename/pypy/rpython/module/ll_os_stat.py
==============================================================================
--- pypy/branch/unicode_filename/pypy/rpython/module/ll_os_stat.py	(original)
+++ pypy/branch/unicode_filename/pypy/rpython/module/ll_os_stat.py	Wed Apr 22 02:05:23 2009
@@ -345,6 +345,16 @@
              ('ftLastAccessTime', rwin32.FILETIME),
              ('ftLastWriteTime', rwin32.FILETIME)])
 
+        WIN32_FIND_DATAW = platform.Struct(
+            'WIN32_FIND_DATAW',
+            # Only interesting fields
+            [('dwFileAttributes', rwin32.DWORD),
+             ('nFileSizeHigh', rwin32.DWORD),
+             ('nFileSizeLow', rwin32.DWORD),
+             ('ftCreationTime', rwin32.FILETIME),
+             ('ftLastAccessTime', rwin32.FILETIME),
+             ('ftLastWriteTime', rwin32.FILETIME)])
+
     globals().update(platform.configure(CConfig))
     GET_FILEEX_INFO_LEVELS = rffi.ULONG # an enumeration
 
@@ -355,6 +365,13 @@
         rwin32.BOOL,
         calling_conv='win')
 
+    GetFileAttributesExW = rffi.llexternal(
+        'GetFileAttributesExW',
+        [rffi.CWCHARP, GET_FILEEX_INFO_LEVELS,
+         lltype.Ptr(WIN32_FILE_ATTRIBUTE_DATA)],
+        rwin32.BOOL,
+        calling_conv='win')
+
     GetFileInformationByHandle = rffi.llexternal(
         'GetFileInformationByHandle',
         [rwin32.HANDLE, lltype.Ptr(BY_HANDLE_FILE_INFORMATION)],
@@ -367,6 +384,12 @@
         rwin32.HANDLE,
         calling_conv='win')
 
+    FindFirstFileW = rffi.llexternal(
+        'FindFirstFileW',
+        [rffi.CWCHARP, lltype.Ptr(WIN32_FIND_DATAW)],
+        rwin32.HANDLE,
+        calling_conv='win')
+
     FindClose = rffi.llexternal(
         'FindClose',
         [rwin32.HANDLE],
@@ -440,9 +463,13 @@
 
         return make_stat_result(result)
 
-    def attributes_from_dir(l_path, data):
-        filedata = lltype.malloc(WIN32_FIND_DATA, flavor='raw')
-        hFindFile = FindFirstFile(l_path, filedata)
+    def attributes_from_dir(TP, l_path, data):
+        if TP is str:
+            filedata = lltype.malloc(WIN32_FIND_DATA, flavor='raw')
+            hFindFile = FindFirstFile(l_path, filedata)
+        else:
+            filedata = lltype.malloc(WIN32_FIND_DATAW, flavor='raw')
+            hFindFile = FindFirstFileW(l_path, filedata)
         if hFindFile == rwin32.INVALID_HANDLE_VALUE:
             return 0
         FindClose(hFindFile)
@@ -453,23 +480,37 @@
         data.c_nFileSizeHigh    = filedata.c_nFileSizeHigh
         data.c_nFileSizeLow     = filedata.c_nFileSizeLow
         return 1
+    attributes_from_dir._annspecialcase_ = 'specialize:arg(0)'
 
     def win32_stat_llimpl(path):
+        if isinstance(path, str):
+            TP = str
+        else:
+            TP = unicode
         data = lltype.malloc(WIN32_FILE_ATTRIBUTE_DATA, flavor='raw')
         try:
-            l_path = rffi.str2charp(path)
-            res = GetFileAttributesEx(l_path, GetFileExInfoStandard, data)
+            if TP is str:
+                l_path = rffi.str2charp(path)
+                fn = GetFileAttributesEx
+            else:
+                l_path = rffi.unicode2wcharp(path)
+                fn = GetFileAttributesExW
+            res = fn(l_path, GetFileExInfoStandard, data)
             errcode = rwin32.GetLastError()
             if res == 0:
                 if errcode == ERROR_SHARING_VIOLATION:
-                    res = attributes_from_dir(l_path, data)
+                    res = attributes_from_dir(TP, l_path, data)
                     errcode = rwin32.GetLastError()
-            rffi.free_charp(l_path)
+            if TP is str:
+                rffi.free_charp(l_path)
+            else:
+                rffi.free_wcharp(l_path)
             if res == 0:
                 raise WindowsError(errcode, "os_stat failed")
             return attribute_data_to_stat(data)
         finally:
             lltype.free(data, flavor='raw')
+    win32_stat_llimpl._annspecialcase_ = 'specialize:argtype(0)'
     win32_lstat_llimpl = win32_stat_llimpl
 
     def win32_fstat_llimpl(fd):



More information about the Pypy-commit mailing list