[pypy-svn] r76181 - in pypy/branch/unicode_filename-2/pypy: module/posix rlib rlib/test rpython/module rpython/module/test

afa at codespeak.net afa at codespeak.net
Tue Jul 13 15:28:45 CEST 2010


Author: afa
Date: Tue Jul 13 15:28:42 2010
New Revision: 76181

Modified:
   pypy/branch/unicode_filename-2/pypy/module/posix/interp_posix.py
   pypy/branch/unicode_filename-2/pypy/rlib/rposix.py
   pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py
   pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py
   pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os_stat.py
   pypy/branch/unicode_filename-2/pypy/rpython/module/test/test_ll_os_stat.py
Log:
Add unicode support to os.stat() and os.lstat()


Modified: pypy/branch/unicode_filename-2/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/module/posix/interp_posix.py	(original)
+++ pypy/branch/unicode_filename-2/pypy/module/posix/interp_posix.py	Tue Jul 13 15:28:42 2010
@@ -183,7 +183,7 @@
         return build_stat_result(space, st)
 fstat.unwrap_spec = [ObjSpace, "c_int"]
 
-def stat(space, path):
+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
@@ -199,22 +199,22 @@
 """
 
     try:
-        st = os.stat(path)
+        st = dispatch_filename(rposix.stat)(space, w_path)
     except OSError, e: 
-        raise wrap_oserror(space, e, path)
+        raise wrap_oserror2(space, e, w_path)
     else: 
         return build_stat_result(space, st)
-stat.unwrap_spec = [ObjSpace, 'path']
+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 = dispatch_filename(rposix.lstat)(space, w_path)
     except OSError, e:
-        raise wrap_oserror(space, e, path)
+        raise wrap_oserror2(space, e, w_path)
     else:
         return build_stat_result(space, st)
-lstat.unwrap_spec = [ObjSpace, 'path']
+lstat.unwrap_spec = [ObjSpace, W_Root]
 
 class StatState(object):
     def __init__(self, space):

Modified: pypy/branch/unicode_filename-2/pypy/rlib/rposix.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rlib/rposix.py	(original)
+++ pypy/branch/unicode_filename-2/pypy/rlib/rposix.py	Tue Jul 13 15:28:42 2010
@@ -53,3 +53,17 @@
         return os.open(path, flags, mode)
     else:
         return os.open(path.encode(), flags, mode)
+
+ at specialize.argtype(0)
+def stat(path):
+    if isinstance(path, str):
+        return os.stat(path)
+    else:
+        return os.stat(path.encode())
+
+ at specialize.argtype(0)
+def lstat(path):
+    if isinstance(path, str):
+        return os.lstat(path)
+    else:
+        return os.lstat(path.encode())

Modified: pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py	(original)
+++ pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py	Tue Jul 13 15:28:42 2010
@@ -7,13 +7,12 @@
     return ''.join(s.chars)
 
 class TestPosixUnicode:
-    def test_access(self):
-        ufilename = (unicode(udir.join('test_open')) +
+    def setup_class(cls):
+        cls.ufilename = (unicode(udir.join('test_open')) +
                      u'\u65e5\u672c.txt') # "Japan"
-        f = file(ufilename, 'w')
+        f = file(cls.ufilename, 'w')
         f.write("test")
         f.close()
-        filename = str(udir.join('test_open'))
 
         class UnicodeWithEncoding:
             def __init__(self, unistr):
@@ -27,11 +26,12 @@
             def gettext(self):
                 return self.unistr
 
-        path = UnicodeWithEncoding(ufilename)
+        cls.path = UnicodeWithEncoding(cls.ufilename)
 
+    def test_access(self):
         def f():
             try:
-                fd = rposix.open(path, os.O_RDONLY, 0777)
+                fd = rposix.open(self.path, os.O_RDONLY, 0777)
                 try:
                     text = os.read(fd, 50)
                     return text
@@ -41,3 +41,9 @@
                 return ''
 
         assert ll_to_string(interpret(f, [])) == "test"
+
+    def test_stat(self):
+        def f():
+            return rposix.stat(self.path).st_mtime
+
+        assert interpret(f, []) == os.stat(self.ufilename).st_mtime

Modified: pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py	(original)
+++ pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py	Tue Jul 13 15:28:42 2010
@@ -1485,17 +1485,27 @@
     @registering(os.fstat)
     def register_os_fstat(self):
         from pypy.rpython.module import ll_os_stat
-        ll_os_stat.register_stat_variant('fstat')
+        return ll_os_stat.register_stat_variant('fstat')
 
     @registering(os.stat)
     def register_os_stat(self):
         from pypy.rpython.module import ll_os_stat
-        ll_os_stat.register_stat_variant('stat')
+        return ll_os_stat.register_stat_variant('stat')
 
     @registering(os.lstat)
     def register_os_lstat(self):
         from pypy.rpython.module import ll_os_stat
-        ll_os_stat.register_stat_variant('lstat')
+        return ll_os_stat.register_stat_variant('lstat')
+
+    @registering_unicode_version(os.stat, 1, [0], sys.platform=='win32')
+    def register_os_stat_unicode(self):
+        from pypy.rpython.module import ll_os_stat
+        return ll_os_stat.register_stat_variant_unicode('stat')
+
+    @registering_unicode_version(os.lstat, 1, [0], sys.platform=='win32')
+    def register_os_lstat_unicode(self):
+        from pypy.rpython.module import ll_os_stat
+        return ll_os_stat.register_stat_variant_unicode('lstat')
 
     # ------------------------------- os.W* ---------------------------------
 

Modified: pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os_stat.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os_stat.py	(original)
+++ pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os_stat.py	Tue Jul 13 15:28:42 2010
@@ -7,11 +7,12 @@
 from pypy.tool.pairtype import pairtype
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rpython import extregistry
-from pypy.rpython.extfunc import register_external
+from pypy.rpython.extfunc import register_external, extdef
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.tool import rffi_platform as platform
 from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE
 from pypy.rlib import rposix
+from pypy.rlib.objectmodel import specialize
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.annlowlevel import hlstr
 
@@ -271,8 +272,8 @@
                                        [ARG1, STAT_STRUCT], rffi.INT,
                                        compilation_info=compilation_info)
 
-        register_external(
-            getattr(os, name), [s_arg], s_StatResult,
+        return extdef(
+            [s_arg], s_StatResult,
             "ll_os.ll_os_%s" % (name,),
             llimpl=func_with_new_name(posix_stat_llimpl,
                                       'os_%s_llimpl' % (name,)),
@@ -281,13 +282,24 @@
             )
     else:
         # See Win32 implementation below
-        register_external(
-            getattr(os, name), [s_arg], s_StatResult,
+        return extdef(
+            [s_arg], s_StatResult,
             "ll_os.ll_os_%s" % (name,),
             llimpl=func_with_new_name(globals()['win32_%s_llimpl' % (name,)],
                                       'os_%s_llimpl' % (name,)),
             )
 
+def register_stat_variant_unicode(name):
+    assert name in ('stat', 'lstat')
+
+    # See Win32 implementation below
+    return extdef(
+        [unicode], s_StatResult,
+        "ll_os.ll_os_%s" % (name,),
+        llimpl=func_with_new_name(globals()['win32_wstat_llimpl'],
+                                  'os_wstat_llimpl')
+        )
+
 # ____________________________________________________________
 if sys.platform == 'win32':
     # The CRT of Windows has a number of flaws wrt. its stat() implementation:
@@ -344,7 +356,7 @@
              ('ftLastAccessTime', rwin32.FILETIME),
              ('ftLastWriteTime', rwin32.FILETIME)])
 
-        WIN32_FIND_DATA = platform.Struct(
+        WIN32_FIND_DATAA = platform.Struct(
             'WIN32_FIND_DATAA',
             # Only interesting fields
             [('dwFileAttributes', rwin32.DWORD),
@@ -353,17 +365,33 @@
              ('ftCreationTime', rwin32.FILETIME),
              ('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
 
-    GetFileAttributesEx = rffi.llexternal(
+    GetFileAttributesExA = rffi.llexternal(
         'GetFileAttributesExA',
         [rffi.CCHARP, GET_FILEEX_INFO_LEVELS,
          lltype.Ptr(WIN32_FILE_ATTRIBUTE_DATA)],
         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)],
@@ -376,9 +404,15 @@
         rwin32.DWORD,
         calling_conv='win')
 
-    FindFirstFile = rffi.llexternal(
+    FindFirstFileA = rffi.llexternal(
         'FindFirstFileA',
-        [rffi.CCHARP, lltype.Ptr(WIN32_FIND_DATA)],
+        [rffi.CCHARP, lltype.Ptr(WIN32_FIND_DATAA)],
+        rwin32.HANDLE,
+        calling_conv='win')
+
+    FindFirstFileW = rffi.llexternal(
+        'FindFirstFileW',
+        [rffi.CWCHARP, lltype.Ptr(WIN32_FIND_DATAW)],
         rwin32.HANDLE,
         calling_conv='win')
 
@@ -455,25 +489,37 @@
 
         return make_stat_result(result)
 
+    @specialize.ll()
+    def findfirstfile(l_path):
+        if lltype.typeOf(l_path) == rffi.CWCHARP:
+            filedata = lltype.malloc(WIN32_FIND_DATAW, flavor='raw')
+            return FindFirstFileW(l_path, filedata), filedata
+        else:
+            filedata = lltype.malloc(WIN32_FIND_DATAA, flavor='raw')
+            return FindFirstFileA(l_path, filedata), filedata
+
+    @specialize.ll()
     def attributes_from_dir(l_path, data):
-        filedata = lltype.malloc(WIN32_FIND_DATA, flavor='raw')
-        hFindFile = FindFirstFile(l_path, filedata)
-        if hFindFile == rwin32.INVALID_HANDLE_VALUE:
-            return 0
-        FindClose(hFindFile)
-        data.c_dwFileAttributes = filedata.c_dwFileAttributes
-        rffi.structcopy(data.c_ftCreationTime, filedata.c_ftCreationTime)
-        rffi.structcopy(data.c_ftLastAccessTime, filedata.c_ftLastAccessTime)
-        rffi.structcopy(data.c_ftLastWriteTime, filedata.c_ftLastWriteTime)
-        data.c_nFileSizeHigh    = filedata.c_nFileSizeHigh
-        data.c_nFileSizeLow     = filedata.c_nFileSizeLow
-        return 1
+        hFindFile, filedata = findfirstfile(l_path)
+        try:
+            if hFindFile == rwin32.INVALID_HANDLE_VALUE:
+                return 0
+            FindClose(hFindFile)
+            data.c_dwFileAttributes = filedata.c_dwFileAttributes
+            rffi.structcopy(data.c_ftCreationTime, filedata.c_ftCreationTime)
+            rffi.structcopy(data.c_ftLastAccessTime, filedata.c_ftLastAccessTime)
+            rffi.structcopy(data.c_ftLastWriteTime, filedata.c_ftLastWriteTime)
+            data.c_nFileSizeHigh    = filedata.c_nFileSizeHigh
+            data.c_nFileSizeLow     = filedata.c_nFileSizeLow
+            return 1
+        finally:
+            lltype.free(filedata, flavor='raw')
 
     def win32_stat_llimpl(path):
         data = lltype.malloc(WIN32_FILE_ATTRIBUTE_DATA, flavor='raw')
         try:
             l_path = rffi.str2charp(path)
-            res = GetFileAttributesEx(l_path, GetFileExInfoStandard, data)
+            res = GetFileAttributesExA(l_path, GetFileExInfoStandard, data)
             errcode = rwin32.GetLastError()
             if res == 0:
                 if errcode == ERROR_SHARING_VIOLATION:
@@ -487,6 +533,23 @@
             lltype.free(data, flavor='raw')
     win32_lstat_llimpl = win32_stat_llimpl
 
+    def win32_wstat_llimpl(path):
+        data = lltype.malloc(WIN32_FILE_ATTRIBUTE_DATA, flavor='raw')
+        try:
+            l_path = rffi.unicode2wcharp(path)
+            res = GetFileAttributesExW(l_path, GetFileExInfoStandard, data)
+            errcode = rwin32.GetLastError()
+            if res == 0:
+                if errcode == ERROR_SHARING_VIOLATION:
+                    res = attributes_from_dir(l_path, data)
+                    errcode = rwin32.GetLastError()
+            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')
+
     def win32_fstat_llimpl(fd):
         handle = rwin32._get_osfhandle(fd)
 

Modified: pypy/branch/unicode_filename-2/pypy/rpython/module/test/test_ll_os_stat.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rpython/module/test/test_ll_os_stat.py	(original)
+++ pypy/branch/unicode_filename-2/pypy/rpython/module/test/test_ll_os_stat.py	Tue Jul 13 15:28:42 2010
@@ -9,8 +9,11 @@
 
     def test_stat(self):
         stat = ll_os_stat.win32_stat_llimpl
+        wstat = ll_os_stat.win32_wstat_llimpl
         def check(f):
-            assert stat(f).st_mtime == os.stat(f).st_mtime
+            expected = os.stat(f).st_mtime
+            assert stat(f).st_mtime == expected
+            assert wstat(unicode(f)).st_mtime == expected
 
         check('c:/')
         check('c:/temp')



More information about the Pypy-commit mailing list