1. Pypy
  2. Untitled project
  3. pypy

Commits

Amaury Forgeot d'Arc  committed 614e99b

Move win32 functions to another file, share the str/unicode implementations.

  • Participants
  • Parent commits 23bc461
  • Branches unicode_filename-2

Comments (0)

Files changed (3)

File pypy/rpython/module/ll_os.py

View file
 
 class StringTraits:
     str = str
+    CHAR = rffi.CHAR
     CCHARP = rffi.CCHARP
 
     @staticmethod
 
 class UnicodeTraits:
     str = unicode
+    CHAR = rffi.WCHAR_T
     CCHARP = rffi.CWCHARP
 
     @staticmethod
     def register_os_listdir(self):
         # we need a different approach on Windows and on Posix
         if sys.platform.startswith('win'):
-            from pypy.rlib import rwin32
-            class CConfig:
-                _compilation_info_ = ExternalCompilationInfo(
-                    includes = ['windows.h']
-                )
-                WIN32_FIND_DATA = platform.Struct('struct _WIN32_FIND_DATAA',
-                    [('cFileName', lltype.FixedSizeArray(rffi.CHAR, 1))])
-                ERROR_FILE_NOT_FOUND = platform.ConstantInteger(
-                    'ERROR_FILE_NOT_FOUND')
-                ERROR_NO_MORE_FILES = platform.ConstantInteger(
-                    'ERROR_NO_MORE_FILES')
-
-            config = platform.configure(CConfig)
-            WIN32_FIND_DATA      = config['WIN32_FIND_DATA']
-            ERROR_FILE_NOT_FOUND = config['ERROR_FILE_NOT_FOUND']
-            ERROR_NO_MORE_FILES  = config['ERROR_NO_MORE_FILES']
-            LPWIN32_FIND_DATA    = lltype.Ptr(WIN32_FIND_DATA)
-
-            FindFirstFile = self.llexternal('FindFirstFileA',
-                                            [rwin32.LPCSTR, LPWIN32_FIND_DATA],
-                                            rwin32.HANDLE)
-            FindNextFile = self.llexternal('FindNextFileA',
-                                           [rwin32.HANDLE, LPWIN32_FIND_DATA],
-                                           rwin32.BOOL)
-            FindClose = self.llexternal('FindClose',
-                                        [rwin32.HANDLE],
-                                        rwin32.BOOL)
-
-            def os_listdir_llimpl(path):
-                if path and path[-1] not in ('/', '\\', ':'):
-                    path += '/'
-                path += '*.*'
-                filedata = lltype.malloc(WIN32_FIND_DATA, flavor='raw')
-                try:
-                    result = []
-                    hFindFile = FindFirstFile(path, filedata)
-                    if hFindFile == rwin32.INVALID_HANDLE_VALUE:
-                        error = rwin32.GetLastError()
-                        if error == ERROR_FILE_NOT_FOUND:
-                            return result
-                        else:
-                            raise WindowsError(error,  "FindFirstFile failed")
-                    while True:
-                        name = rffi.charp2str(rffi.cast(rffi.CCHARP,
-                                                        filedata.c_cFileName))
-                        if name != "." and name != "..":   # skip these
-                            result.append(name)
-                        if not FindNextFile(hFindFile, filedata):
-                            break
-                    # FindNextFile sets error to ERROR_NO_MORE_FILES if
-                    # it got to the end of the directory
-                    error = rwin32.GetLastError()
-                    FindClose(hFindFile)
-                    if error == ERROR_NO_MORE_FILES:
-                        return result
-                    else:
-                        raise WindowsError(error,  "FindNextFile failed")
-                finally:
-                    lltype.free(filedata, flavor='raw')
-
+            from pypy.rpython.module.win32file import make_listdir_impl
+            os_listdir_llimpl = make_listdir_impl(StringTraits())
         else:
             compilation_info = ExternalCompilationInfo(
                 includes = ['sys/types.h', 'dirent.h']
 
     @registering_unicode_version(os.listdir, [unicode], sys.platform=='win32')
     def register_os_listdir_unicode(self):
-        from pypy.rlib import rwin32
-        class CConfig:
-            _compilation_info_ = ExternalCompilationInfo(
-                includes = ['windows.h']
-            )
-            WIN32_FIND_DATA = platform.Struct('struct _WIN32_FIND_DATAW',
-                [('cFileName', lltype.FixedSizeArray(rwin32.WCHAR, 250))])
-            ERROR_FILE_NOT_FOUND = platform.ConstantInteger(
-                'ERROR_FILE_NOT_FOUND')
-            ERROR_NO_MORE_FILES = platform.ConstantInteger(
-                'ERROR_NO_MORE_FILES')
-
-        config = platform.configure(CConfig)
-        WIN32_FIND_DATA      = config['WIN32_FIND_DATA']
-        ERROR_FILE_NOT_FOUND = config['ERROR_FILE_NOT_FOUND']
-        ERROR_NO_MORE_FILES  = config['ERROR_NO_MORE_FILES']
-        LPWIN32_FIND_DATA    = lltype.Ptr(WIN32_FIND_DATA)
-
-        FindFirstFile = self.llexternal('FindFirstFileW',
-                                        [rwin32.LPCWSTR, LPWIN32_FIND_DATA],
-                                        rwin32.HANDLE)
-        FindNextFile = self.llexternal('FindNextFileW',
-                                       [rwin32.HANDLE, LPWIN32_FIND_DATA],
-                                       rwin32.BOOL)
-        FindClose = self.llexternal('FindClose',
-                                    [rwin32.HANDLE],
-                                    rwin32.BOOL)
-
-        def os_listdir_llimpl(path):
-            if path and path[-1] not in (u'/', u'\\', u':'):
-                path += u'/'
-            path += u'*.*'
-            filedata = lltype.malloc(WIN32_FIND_DATA, flavor='raw')
-            try:
-                result = []
-                hFindFile = FindFirstFile(path, filedata)
-                if hFindFile == rwin32.INVALID_HANDLE_VALUE:
-                    error = rwin32.GetLastError()
-                    if error == ERROR_FILE_NOT_FOUND:
-                        return result
-                    else:
-                        raise WindowsError(error,  "FindFirstFile failed")
-                while True:
-                    name = rffi.wcharp2unicode(rffi.cast(rffi.CWCHARP,
-                                                         filedata.c_cFileName))
-                    if name != u"." and name != u"..":   # skip these
-                        result.append(name)
-                    if not FindNextFile(hFindFile, filedata):
-                        break
-                # FindNextFile sets error to ERROR_NO_MORE_FILES if
-                # it got to the end of the directory
-                error = rwin32.GetLastError()
-                FindClose(hFindFile)
-                if error == ERROR_NO_MORE_FILES:
-                    return result
-                else:
-                    raise WindowsError(error,  "FindNextFile failed")
-            finally:
-                lltype.free(filedata, flavor='raw')
+        from pypy.rpython.module.win32file import make_listdir_impl
 
         return extdef([unicode],  # a single argument which is a unicode
                       [unicode],  # returns a list of unicodes
                       "ll_os.ll_os_wlistdir",
-                      llimpl=os_listdir_llimpl)
+                      llimpl=make_listdir_impl(UnicodeTraits()))
 
     @registering(os.pipe)
     def register_os_pipe(self):

File pypy/rpython/module/ll_os_stat.py

View file
 import os, sys
 from pypy.annotation import model as annmodel
 from pypy.tool.pairtype import pairtype
-from pypy.tool.sourcetools import func_with_new_name
+from pypy.tool.sourcetools import func_with_new_name, func_renamer
 from pypy.rpython import extregistry
 from pypy.rpython.extfunc import register_external, extdef
 from pypy.rpython.lltypesystem import rffi, lltype
 
     arg_is_path = (name != 'fstat')
 
+    @func_renamer('os_%s_llimpl' % (name,))
     def posix_stat_llimpl(arg):
         stresult = lltype.malloc(STAT_STRUCT.TO, flavor='raw')
         try:
         finally:
             lltype.free(stresult, flavor='raw')
 
+    @func_renamer('os_%s_fake' % (name,))
     def posix_fakeimpl(arg):
         if s_arg == str:
             arg = hlstr(arg)
                                        compilation_info=compilation_info)
 
         return extdef(
-            [s_arg], s_StatResult,
-            "ll_os.ll_os_%s" % (name,),
-            llimpl=func_with_new_name(posix_stat_llimpl,
-                                      'os_%s_llimpl' % (name,)),
-            llfakeimpl=func_with_new_name(posix_fakeimpl,
-                                          'os_%s_fake' % (name,)),
-            )
+            [s_arg], s_StatResult, "ll_os.ll_os_%s" % (name,),
+            llimpl=posix_stat_llimpl, llfakeimpl=posix_fakeimpl)
     else:
         # See Win32 implementation below
         return extdef(
-            [s_arg], s_StatResult,
-            "ll_os.ll_os_%s" % (name,),
+            [s_arg], s_StatResult, "ll_os.ll_os_%s" % (name,),
             llimpl=func_with_new_name(globals()['win32_%s_llimpl' % (name,)],
                                       'os_%s_llimpl' % (name,)),
             )
 # ____________________________________________________________
 if sys.platform == 'win32':
     # The CRT of Windows has a number of flaws wrt. its stat() implementation:
-    # - for when we implement subsecond resolution in RPython, time stamps
-    #   would be restricted to second resolution
+    # - time stamps are restricted to second resolution
     # - file modification times suffer from forth-and-back conversions between
     #   UTC and local time
     # Therefore, we implement our own stat, based on the Win32 API directly.

File pypy/rpython/module/ll_win32file.py

View file
+"""
+The Windows implementation of some posix modules,
+based on the Win32 API.
+"""
+
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.rpython.tool import rffi_platform as platform
+
+def make_win32_traits(traits):
+    from pypy.rlib import rwin32
+
+    if traits.str is unicode:
+        suffix = 'W'
+    else:
+        suffix = 'A'
+
+    class CConfig:
+        _compilation_info_ = ExternalCompilationInfo(
+            includes = ['windows.h']
+        )
+        WIN32_FIND_DATA = platform.Struct(
+            'struct _WIN32_FIND_DATA' + suffix,
+            # Only interesting fields
+            [('dwFileAttributes', rwin32.DWORD),
+             ('nFileSizeHigh', rwin32.DWORD),
+             ('nFileSizeLow', rwin32.DWORD),
+             ('ftCreationTime', rwin32.FILETIME),
+             ('ftLastAccessTime', rwin32.FILETIME),
+             ('ftLastWriteTime', rwin32.FILETIME),
+             ('cFileName', lltype.FixedSizeArray(traits.CHAR, 250))])
+        ERROR_FILE_NOT_FOUND = platform.ConstantInteger(
+            'ERROR_FILE_NOT_FOUND')
+        ERROR_NO_MORE_FILES = platform.ConstantInteger(
+            'ERROR_NO_MORE_FILES')
+
+    def external(*args, **kwargs):
+        kwargs['compilation_info'] = CConfig._compilation_info_
+        return rffi.llexternal(*args, **kwargs)
+
+    config = platform.configure(CConfig)
+
+    class Win32Traits:
+        WIN32_FIND_DATA      = config['WIN32_FIND_DATA']
+        ERROR_FILE_NOT_FOUND = config['ERROR_FILE_NOT_FOUND']
+        ERROR_NO_MORE_FILES  = config['ERROR_NO_MORE_FILES']
+        LPWIN32_FIND_DATA    = lltype.Ptr(WIN32_FIND_DATA)
+
+        FindFirstFile = external('FindFirstFile' + suffix,
+                                 [traits.CCHARP, LPWIN32_FIND_DATA],
+                                 rwin32.HANDLE)
+        FindNextFile = external('FindNextFile' + suffix,
+                                [rwin32.HANDLE, LPWIN32_FIND_DATA],
+                                rwin32.BOOL)
+        FindClose = external('FindClose',
+                             [rwin32.HANDLE],
+                             rwin32.BOOL)
+
+    return Win32Traits
+
+def make_listdir_impl(traits):
+    from pypy.rlib import rwin32
+    win32traits = make_win32_traits(traits)
+
+    if traits.str is unicode:
+        def make_listdir_mask(path):
+            if path and path[-1] not in (u'/', u'\\', u':'):
+                path += u'/'
+            return path + u'*.*'
+
+        def skip_listdir(path):
+            return name == u"." or name == u"..":
+    else:
+        def make_listdir_mask(path):
+            if path and path[-1] not in ('/', '\\', ':'):
+                path += '/'
+            return path + '*.*'
+
+        def skip_listdir(path):
+            return name == "." or name == "..":
+
+    def listdir_llimpl(path):
+        mask = make_listdir_mask(path)
+        filedata = lltype.malloc(win32traits.WIN32_FIND_DATA, flavor='raw')
+        try:
+            result = []
+            hFindFile = win32traits.FindFirstFile(mask, filedata)
+            if hFindFile == rwin32.INVALID_HANDLE_VALUE:
+                error = rwin32.GetLastError()
+                if error == win32traits.ERROR_FILE_NOT_FOUND:
+                    return result
+                else:
+                    raise WindowsError(error,  "FindFirstFile failed")
+            while True:
+                name = rffi.wcharp2unicode(rffi.cast(rffi.CWCHARP,
+                                                     filedata.c_cFileName))
+                if not skip_listdir(name):
+                    result.append(name)
+                if not win32traits.FindNextFile(hFindFile, filedata):
+                    break
+            # FindNextFile sets error to ERROR_NO_MORE_FILES if
+            # it got to the end of the directory
+            error = rwin32.GetLastError()
+            win32traits.FindClose(hFindFile)
+            if error == win32traits.ERROR_NO_MORE_FILES:
+                return result
+            else:
+                raise WindowsError(error,  "FindNextFile failed")
+        finally:
+            lltype.free(filedata, flavor='raw')
+
+    return listdir_llimpl