[pypy-svn] r31408 - in pypy/dist/pypy/module/mmap: . test

rhymes at codespeak.net rhymes at codespeak.net
Sat Aug 19 17:57:51 CEST 2006


Author: rhymes
Date: Sat Aug 19 17:57:49 2006
New Revision: 31408

Modified:
   pypy/dist/pypy/module/mmap/__init__.py
   pypy/dist/pypy/module/mmap/interp_mmap.py
   pypy/dist/pypy/module/mmap/test/test_mmap.py
Log:
mmap start working on Windows. PAGESIZE, other attributes, the instantiation of mmap object, close() and read_byte() all work.

Modified: pypy/dist/pypy/module/mmap/__init__.py
==============================================================================
--- pypy/dist/pypy/module/mmap/__init__.py	(original)
+++ pypy/dist/pypy/module/mmap/__init__.py	Sat Aug 19 17:57:49 2006
@@ -15,12 +15,14 @@
     
     def buildloaders(cls):
         from pypy.module.mmap import interp_mmap
+        import os
 
         Module.interpleveldefs["PAGESIZE"] = 'space.wrap(%r)' %\
             interp_mmap._get_page_size()
-            
-        for constant, value in interp_mmap.constants.iteritems():
-            Module.interpleveldefs[constant] = "space.wrap(%r)" % value
+         
+        if os.name == "posix":
+            for constant, value in interp_mmap.constants.iteritems():
+                Module.interpleveldefs[constant] = "space.wrap(%r)" % value
         
         super(Module, cls).buildloaders()
     buildloaders = classmethod(buildloaders)

Modified: pypy/dist/pypy/module/mmap/interp_mmap.py
==============================================================================
--- pypy/dist/pypy/module/mmap/interp_mmap.py	(original)
+++ pypy/dist/pypy/module/mmap/interp_mmap.py	Sat Aug 19 17:57:49 2006
@@ -18,23 +18,33 @@
 _64BIT = "64bit" in platform.architecture()[0]
 
 class CConfig:
-    _header_ = """
-    #include <sys/types.h>
-    #include <sys/mman.h>
-    """
+    _header_ = "#include <sys/types.h>"
     size_t = ctypes_platform.SimpleType("size_t", c_long)
     off_t = ctypes_platform.SimpleType("off_t", c_long)
 
-# constants, look in sys/mman.h and platform docs for the meaning
-# some constants are linux only so they will be correctly exposed outside 
-# depending on the OS
 constants = {}
-constant_names = ['MAP_SHARED', 'MAP_PRIVATE', 'MAP_ANON', 'MAP_ANONYMOUS',
-    'PROT_READ', 'PROT_WRITE', 'PROT_EXEC', 'MAP_DENYWRITE', 'MAP_EXECUTABLE',
-    'MS_SYNC']
-for name in constant_names:
-    setattr(CConfig, name, ctypes_platform.DefinedConstantInteger(name))
-
+if _POSIX:
+    CConfig._header_ = """
+    %s
+    #include <sys/mman.h>""" % CConfig._header_
+    # constants, look in sys/mman.h and platform docs for the meaning
+    # some constants are linux only so they will be correctly exposed outside 
+    # depending on the OS
+    constant_names = ['MAP_SHARED', 'MAP_PRIVATE', 'MAP_ANON', 'MAP_ANONYMOUS',
+                      'PROT_READ', 'PROT_WRITE', 'PROT_EXEC', 'MAP_DENYWRITE', 'MAP_EXECUTABLE',
+                      'MS_SYNC']
+    for name in constant_names:
+        setattr(CConfig, name, ctypes_platform.DefinedConstantInteger(name))
+elif _MS_WINDOWS:
+    CConfig._header_ = """
+    %s
+    #include <windows.h>""" % CConfig._header_
+    constant_names = ['PAGE_READONLY', 'PAGE_READWRITE', 'PAGE_WRITECOPY',
+                      'FILE_MAP_READ', 'FILE_MAP_WRITE', 'FILE_MAP_COPY',
+                      'DUPLICATE_SAME_ACCESS']
+    for name in constant_names:
+        setattr(CConfig, name, ctypes_platform.ConstantInteger(name))
+    
 class cConfig:
     pass
 
@@ -46,12 +56,14 @@
     if value is not None:
         constants[name] = value
 
-# MAP_ANONYMOUS is not always present but it's always available at CPython level
-if cConfig.MAP_ANONYMOUS is None:
-    cConfig.MAP_ANONYMOUS = cConfig.MAP_ANON
-    constants["MAP_ANONYMOUS"] = cConfig.MAP_ANON
+if _POSIX:
+    # MAP_ANONYMOUS is not always present but it's always available at CPython level
+    if cConfig.MAP_ANONYMOUS is None:
+        cConfig.MAP_ANONYMOUS = cConfig.MAP_ANON
+        constants["MAP_ANONYMOUS"] = cConfig.MAP_ANON
 
 locals().update(constants)
+    
 
 _ACCESS_DEFAULT, ACCESS_READ, ACCESS_WRITE, ACCESS_COPY = range(4)
 
@@ -61,123 +73,135 @@
 libc.strerror.argtypes = [c_int]
 libc.memcpy.argtypes = [POINTER(c_char), c_char_p, c_int]
 libc.memcpy.restype = c_void_p
-libc.mmap.argtypes = [c_void_p, size_t, c_int, c_int, c_int, off_t]
-libc.mmap.restype = c_void_p
-libc.close.argtypes = [c_int]
-libc.close.restype = c_int
-libc.munmap.argtypes = [c_void_p, size_t]
-libc.munmap.restype = c_int
-libc.msync.argtypes = [c_char_p, size_t, c_int]
-libc.msync.restype = c_int
-
-## LINUX msync syscall helper stuff
-# you don't have addressof() in rctypes so I looked up the implementation
-# of addressof in ctypes source and come up with this.
-pythonapi.PyLong_FromVoidPtr.argtypes = [c_char_p]
-pythonapi.PyLong_FromVoidPtr.restype = c_int
-# we also need to alias msync to take a c_void_p instead of c_char_p
-linux_msync = libc["msync"]
-linux_msync.argtypes = [c_void_p, size_t, c_int]
-linux_msync.restype = c_int
-
-libc.memmove.argtypes = [c_char_p, c_char_p, size_t]
-libc.memmove.restype = c_void_p
-has_mremap = False
-if hasattr(libc, "mremap"):
-    libc.mremap.argtypes = [POINTER(c_char), size_t, size_t, c_ulong]
-    libc.mremap.restype = c_void_p
-    has_mremap = True
-libc.ftruncate.argtypes = [c_int, off_t]
-libc.ftruncate.restype = c_int
 
 if _POSIX:
+    libc.mmap.argtypes = [c_void_p, size_t, c_int, c_int, c_int, off_t]
+    libc.mmap.restype = c_void_p
+    libc.close.argtypes = [c_int]
+    libc.close.restype = c_int
+    libc.munmap.argtypes = [c_void_p, size_t]
+    libc.munmap.restype = c_int
+    libc.msync.argtypes = [c_char_p, size_t, c_int]
+    libc.msync.restype = c_int
+
+    ## LINUX msync syscall helper stuff
+    # you don't have addressof() in rctypes so I looked up the implementation
+    # of addressof in ctypes source and come up with this.
+    pythonapi.PyLong_FromVoidPtr.argtypes = [c_char_p]
+    pythonapi.PyLong_FromVoidPtr.restype = c_int
+    # we also need to alias msync to take a c_void_p instead of c_char_p
+    linux_msync = libc["msync"]
+    linux_msync.argtypes = [c_void_p, size_t, c_int]
+    linux_msync.restype = c_int
+    
+    libc.memmove.argtypes = [c_char_p, c_char_p, size_t]
+    libc.memmove.restype = c_void_p
+    has_mremap = False
+    if hasattr(libc, "mremap"):
+        libc.mremap.argtypes = [POINTER(c_char), size_t, size_t, c_ulong]
+        libc.mremap.restype = c_void_p
+        has_mremap = True
+    libc.ftruncate.argtypes = [c_int, off_t]
+    libc.ftruncate.restype = c_int
+
     def _get_page_size():
         return libc.getpagesize()
 
     def _get_error_msg():
         errno = geterrno()
         return libc.strerror(errno)   
-# elif _MS_WINDOWS:
-#     from ctypes import wintypes
-#     _LPVOID = c_void_p
-#     _LPCVOID = _LPVOID
-#     _DWORD_PTR = wintypes.DWORD
-#     _INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value
-# 
-#     _PAGE_READONLY = 0x02
-#     _PAGE_READWRITE = 0x04
-#     _PAGE_WRITECOPY = 0x08
-# 
-#     _FILE_MAP_READ = 0x0004
-#     _FILE_MAP_WRITE = 0x0002
-#     _FILE_MAP_COPY = 0x0001
-# 
-# 
-#     class _STRUCT(Structure):
-#         _fields_ = [("wProcessorArchitecture", wintypes.WORD),
-#                     ("wReserved", wintypes.WORD)]
-# 
-#     class _UNION(Union):
-#         _fields_ = [("dwOemId", wintypes.DWORD),
-#                     ("struct", _STRUCT)]
-# 
-#     class _SYSTEM_INFO(Structure):
-#         _fields_ = [("union", _UNION),
-#                     ("dwPageSize", wintypes.DWORD),
-#                     ("lpMinimumApplicationAddress", _LPVOID),
-#                     ("lpMaximumApplicationAddress", _LPVOID),
-#                     ("dwActiveProcessorMask", _DWORD_PTR),
-#                     ("dwNumberOfProcessors", wintypes.DWORD),
-#                     ("dwProcessorType", wintypes.DWORD),
-#                     ("dwAllocationGranularity", wintypes.DWORD),
-#                     ("wProcessorLevel", wintypes.WORD),
-#                     ("wProcessorRevision", wintypes.WORD)]
-# 
-#     def _get_page_size():
-#         si = _SYSTEM_INFO()
-#         windll.kernel32.GetSystemInfo.argtypes = [POINTER(_SYSTEM_INFO)]
-#         windll.kernel32.GetSystemInfo(byref(si))
-#         return int(si.dwPageSize)
-#     
-#     def _get_file_size(handle):
-#         windll.kernel32.GetFileSize.restype = wintypes.DWORD
-#         low = wintypes.DWORD()
-#         high = wintypes.DWORD()
-#         low = wintypes.DWORD(windll.kernel32.GetFileSize(handle, byref(high)))
-#         # low might just happen to have the value INVALID_FILE_SIZE
-#         # so we need to check the last error also
-#         INVALID_FILE_SIZE = wintypes.DWORD(0xFFFFFFFF).value
-#         NO_ERROR = 0
-#         dwErr = GetLastError()
-#         if low.value == INVALID_FILE_SIZE and dwErr != NO_ERROR:
-#             raise WinError(dwErr)
-#         return low, high
-# 
-#     def _get_error_msg():
-#         cdll.msvcrt.strerror.restype = c_char_p
-#         msg = cdll.msvcrt.strerror(GetLastError())
-#         return msg
-# 
-#     windll.kernel32.CloseHandle.argtypes = [wintypes.HANDLE]
-#     windll.kernel32.CloseHandle.restype = wintypes.BOOL
+elif _MS_WINDOWS:
+    from ctypes import wintypes
+    
+    WORD = wintypes.WORD
+    DWORD = wintypes.DWORD
+    BOOL = wintypes.BOOL
+    LPVOID = c_void_p
+    LPCVOID = LPVOID
+    DWORD_PTR = DWORD
+    HANDLE = wintypes.HANDLE
+    INVALID_HANDLE_VALUE = HANDLE(-1).value
+    
+    class SYSINFO_STRUCT(Structure):
+        _fields_ = [("wProcessorArchitecture", WORD),
+                    ("wReserved", WORD)]
+
+    class SYSINFO_UNION(Union):
+        _fields_ = [("dwOemId", DWORD),
+                    ("struct", SYSINFO_STRUCT)]
+
+    class SYSTEM_INFO(Structure):
+        _fields_ = [("union", SYSINFO_UNION),
+                    ("dwPageSize", DWORD),
+                    ("lpMinimumApplicationAddress", LPVOID),
+                    ("lpMaximumApplicationAddress", LPVOID),
+                    ("dwActiveProcessorMask", DWORD_PTR),
+                    ("dwNumberOfProcessors", DWORD),
+                    ("dwProcessorType", DWORD),
+                    ("dwAllocationGranularity", DWORD),
+                    ("wProcessorLevel", WORD),
+                    ("wProcessorRevision", WORD)]
+    
+    windll.kernel32.GetSystemInfo.argtypes = [POINTER(SYSTEM_INFO)]
+    windll.kernel32.GetFileSize.restype = DWORD
+    GetCurrentProcess = windll.kernel32.GetCurrentProcess
+    GetCurrentProcess.restype = HANDLE
+    DuplicateHandle = windll.kernel32.DuplicateHandle
+    DuplicateHandle.argtypes = [HANDLE, HANDLE, HANDLE, POINTER(HANDLE), DWORD,
+                                BOOL, DWORD]
+    DuplicateHandle.restype = BOOL
+    CreateFileMapping = windll.kernel32.CreateFileMappingA
+    CreateFileMapping.argtypes = [HANDLE, c_void_p, DWORD, DWORD, DWORD,
+                                  c_char_p]
+    CreateFileMapping.restype = HANDLE
+    MapViewOfFile = windll.kernel32.MapViewOfFile
+    MapViewOfFile.argtypes = [HANDLE, DWORD,  DWORD, DWORD, DWORD]
+    MapViewOfFile.restype = c_void_p
+    CloseHandle = windll.kernel32.CloseHandle
+    CloseHandle.argtypes = [HANDLE]
+    CloseHandle.restype = BOOL
+    UnmapViewOfFile = windll.kernel32.UnmapViewOfFile
+    UnmapViewOfFile.argtypes = [LPCVOID]
+    UnmapViewOfFile.restype = BOOL
+    
+    def _get_page_size():
+        si = SYSTEM_INFO()
+        windll.kernel32.GetSystemInfo(byref(si))
+        return int(si.dwPageSize)
+    
+    def _get_file_size(space, handle):
+        low = DWORD()
+        high = DWORD()
+        low = DWORD(windll.kernel32.GetFileSize(handle, byref(high)))
+        # low might just happen to have the value INVALID_FILE_SIZE
+        # so we need to check the last error also
+        INVALID_FILE_SIZE = DWORD(0xFFFFFFFF).value
+        NO_ERROR = 0
+        dwErr = GetLastError()
+        if low.value == INVALID_FILE_SIZE and dwErr != NO_ERROR:
+            raise OperationError(space.wrap(WinError), space.wrap(dwErr))
+        return low, high
+
+    def _get_error_msg():
+        errno = GetLastError()
+        return libc.strerror(GetLastError())
 
 PAGESIZE = _get_page_size()
 
 class _mmap(Wrappable):
     def __init__(self, space):
         self.space = space
-        #self._data = 
         self._size = 0
         self._pos = 0
         self._access = _ACCESS_DEFAULT
-        self._closed = False
 
-        # if _MS_WINDOWS:
-        #     self._map_handle = wintypes.HANDLE()
-        #     self._file_handle = wintypes.HANDLE()
-        #     self._tagname = None
-        if _POSIX:
+        if _MS_WINDOWS:
+            self._map_handle = wintypes.HANDLE()
+            self._file_handle = wintypes.HANDLE()
+            self._tagname = ""
+        elif _POSIX:
             self._fd = 0
+            self._closed = False
     
     def _to_str(self):
         str = "".join([self._data[i] for i in range(self._size)])
@@ -185,12 +209,13 @@
     _to_str.unwrap_spec = ['self']
     
     def _check_valid(self):
-        # if _MS_WINDOWS:
-        #     if self._map_handle.value == _INVALID_HANDLE_VALUE:
-        #         raise ValueError, "map closed or invalid"
-        if _POSIX:
-            if self._closed:
-                raise OperationError(self.space.w_ValueError, 
+        if _MS_WINDOWS:
+            to_close = self._map_handle.value == INVALID_HANDLE_VALUE
+        elif _POSIX:
+            to_close = self._closed
+
+        if to_close:
+            raise OperationError(self.space.w_ValueError, 
                     self.space.wrap("map closed or invalid"))
     _check_valid.unwrap_spec = ['self']
     
@@ -208,17 +233,17 @@
     _check_resizeable.unwrap_spec = ['self']
     
     def close(self):
-        # if _MS_WINDOWS:
-        #     if self._data:
-        #         self._unmapview()
-        #         self._data = None
-        #     if self._map_handle.value != _INVALID_HANDLE_VALUE:
-        #         windll.kernel32.CloseHandle(self._map_handle)
-        #         self._map_handle.value = _INVALID_HANDLE_VALUE
-        #     if self._file_handle.value != _INVALID_HANDLE_VALUE:
-        #         windll.kernel32.CloseHandle(self._file_handle)
-        #         self._file_handle.value = _INVALID_HANDLE_VALUE
-        if _POSIX:
+        if _MS_WINDOWS:
+            if self._data:
+                self._unmapview()
+                self._data = None
+            if self._map_handle.value != INVALID_HANDLE_VALUE:
+                CloseHandle(self._map_handle)
+                self._map_handle.value = INVALID_HANDLE_VALUE
+            if self._file_handle.value != INVALID_HANDLE_VALUE:
+                CloseHandle(self._file_handle)
+                self._file_handle.value = INVALID_HANDLE_VALUE
+        elif _POSIX:
             self._closed = True
             libc.close(self._fd)
             self._fd = -1
@@ -226,6 +251,10 @@
                 libc.munmap(self._data, self._size)
     close.unwrap_spec = ['self']
     
+    def _unmapview(self):
+        self._data = cast(self._data, c_void_p)
+        UnmapViewOfFile(self._data)
+    
     def read_byte(self):
         self._check_valid()
 
@@ -610,8 +639,7 @@
     __delitem__ = interp2app(_mmap.__delitem__,
         unwrap_spec=_mmap.__delitem__.unwrap_spec),
     __add__ = interp2app(_mmap.__add__, unwrap_spec=_mmap.__add__.unwrap_spec),
-    __mul__ = interp2app(_mmap.__mul__, unwrap_spec=_mmap.__mul__.unwrap_spec),
-    
+    __mul__ = interp2app(_mmap.__mul__, unwrap_spec=_mmap.__mul__.unwrap_spec),   
 )
 
 def _check_map_size(space, size):
@@ -694,147 +722,102 @@
 
         return space.wrap(m)
     mmap.unwrap_spec = [ObjSpace, int, int, int, int, int]
-# elif _MS_WINDOWS:
-#     def mmap(fileno, length, *args, **kwargs):
-#         size_hi = wintypes.DWORD() # upper 32 bits of m._size
-#         size_lo = wintypes.DWORD() # lower 32 bits of m._size
-#         tagname = ""
-#         dwErr = wintypes.DWORD(0)
-#         fh = wintypes.HANDLE(0)
-#         access = _ACCESS_DEFAULT
-#         flProtect = wintypes.DWORD()
-#         dwDesiredAccess = wintypes.DWORD()
-#         keywords = ["tagname", "access"]
-#         _check_args(fileno, length, 4, keywords, args, kwargs)
-# 
-#         try:
-#             tagname = args[0]
-#         except IndexError:
-#             try:
-#                 tagname = kwargs[keywords[0]]
-#             except KeyError:
-#                 pass
-#         if not _is_str(tagname) or tagname:
-#                 raise TypeError, "tagname must be string or None"
-# 
-#         try:
-#             access = args[1]
-#         except IndexError:
-#             try:
-#                 access = kwargs[keywords[1]]
-#             except KeyError:
-#                 pass
-#         if not _is_int(access):
-#             raise TypeError, "an integer is required"
-# 
-#         if access == ACCESS_READ:
-#             flProtect = wintypes.DWORD(_PAGE_READONLY)
-#             dwDesiredAccess = wintypes.DWORD(_FILE_MAP_READ)
-#         elif access == _ACCESS_DEFAULT or access == ACCESS_WRITE:
-#             flProtect = wintypes.DWORD(_PAGE_READWRITE)
-#             dwDesiredAccess = wintypes.DWORD(_FILE_MAP_WRITE)
-#         elif access == ACCESS_COPY:
-#             flProtect = wintypes.DWORD(_PAGE_WRITECOPY)
-#             dwDesiredAccess = wintypes.DWORD(_FILE_MAP_COPY)
-#         else:
-#             raise ValueError, "mmap invalid access parameter."
-# 
-#         # check size boundaries
-#         _check_map_size(length)
-#         map_size = length
-# 
-#         # assume -1 and 0 both mean invalid filedescriptor
-#         # to 'anonymously' map memory.
-#         if fileno != -1 and fileno != 0:
-#             fh = cdll.msvcr71._get_osfhandle(fileno)
-#             if fh == -1:
-#                 raise error, _get_error_msg()
-#             # Win9x appears to need us seeked to zero
-#             SEEK_SET = 0
-#             cdll.msvcrt._lseek(fileno, 0, SEEK_SET)
-# 
-#         m = _mmap()
-#         m._file_handle = wintypes.HANDLE(_INVALID_HANDLE_VALUE)
-#         m._map_handle = wintypes.HANDLE(_INVALID_HANDLE_VALUE)
-# 
-#         if fh:
-#             # it is necessary to duplicate the handle, so the
-#             # Python code can close it on us
-#             DUPLICATE_SAME_ACCESS = 0x00000002
-#             GetCurrentProcess = windll.kernel32.GetCurrentProcess
-#             GetCurrentProcess.restype = wintypes.HANDLE
-#             DuplicateHandle = windll.kernel32.DuplicateHandle
-#             DuplicateHandle.argtypes = [wintypes.HANDLE,
-#                                         wintypes.HANDLE,
-#                                         wintypes.HANDLE,
-#                                         POINTER(wintypes.HANDLE),
-#                                         wintypes.DWORD,
-#                                         wintypes.BOOL,
-#                                         wintypes.DWORD]
-#             DuplicateHandle.restype = wintypes.BOOL
-# 
-#             res = DuplicateHandle(GetCurrentProcess(), # source process handle
-#                                   fh, # handle to be duplicated
-#                                   GetCurrentProcess(), # target process handle
-#                                   byref(m._file_handle), # result
-#                                   0, # access - ignored due to options value
-#                                   wintypes.BOOL(False), # inherited by child procs?
-#                                   DUPLICATE_SAME_ACCESS) # options
-#             if not res:
-#                 raise WinError()
-# 
-#             if not map_size:
-#                 low, high = _get_file_size(fh)
-#                 if _64BIT:
-#                     m._size = (c_long(low.value).value << 32) + 1
-#                 else:
-#                     if high:
-#                         # file is too large to map completely
-#                         m._size = -1L
-#                     else:
-#                         m._size = low.value
-#             else:
-#                 m._size = map_size
-#         else:
-#             m._size = map_size
-# 
-#         # set the tag name
-#         if tagname:
-#            m._tagname = tagname
-# 
-#         m._access = access
-# 
-#         # DWORD is a 4-byte int. If int > 4-byte it must be divided
-#         if _64BIT:
-#             size_hi = wintypes.DWORD(m._size >> 32)
-#             size_lo = wintypes.DWORD(m._size & 0xFFFFFFFF)
-#         else:
-#             size_hi = wintypes.DWORD(0)
-#             size_lo = wintypes.DWORD(m._size)
-# 
-#         CreateFileMapping = windll.kernel32.CreateFileMappingA
-#         CreateFileMapping.argtypes = [wintypes.HANDLE, c_void_p, wintypes.DWORD,
-#                                       wintypes.DWORD, wintypes.DWORD, c_char_p]
-#         CreateFileMapping.restype = wintypes.HANDLE
-# 
-#         m._map_handle = wintypes.HANDLE(CreateFileMapping(m._file_handle, None, flProtect,
-#                                          size_hi, size_lo, m._tagname))
-# 
-#         if m._map_handle:
-#             MapViewOfFile = windll.kernel32.MapViewOfFile
-#             MapViewOfFile.argtypes = [wintypes.HANDLE, wintypes.DWORD,
-#                                       wintypes.DWORD, wintypes.DWORD,
-#                                       wintypes.DWORD]
-#             MapViewOfFile.restype = c_void_p
-#             m._data = MapViewOfFile(m._map_handle, dwDesiredAccess,
-#                                     0, 0, 0)
-#             if m._data:
-#                 m._data = cast(m._data, POINTER(c_char))
-#                 return m
-#             else:
-#                 dwErr = GetLastError()
-#         else:
-#             dwErr = GetLastError()
-# 
-#         raise WinError(dwErr)
+elif _MS_WINDOWS:
+    def mmap(space, fileno, length, tagname="", access=_ACCESS_DEFAULT):
+        # check size boundaries
+        _check_map_size(space, length)
+        map_size = length
+        
+        WORD = wintypes.WORD
+        DWORD = wintypes.DWORD
+        HANDLE = wintypes.HANDLE
+        
+        flProtect = WORD()
+        dwDesiredAccess = WORD()
+        fh = HANDLE(0)
+        
+        if access == ACCESS_READ:
+            flProtect = DWORD(PAGE_READONLY)
+            dwDesiredAccess = DWORD(FILE_MAP_READ)
+        elif access == _ACCESS_DEFAULT or access == ACCESS_WRITE:
+            flProtect = DWORD(PAGE_READWRITE)
+            dwDesiredAccess = DWORD(FILE_MAP_WRITE)
+        elif access == ACCESS_COPY:
+            flProtect = DWORD(PAGE_WRITECOPY)
+            dwDesiredAccess = DWORD(FILE_MAP_COPY)
+        else:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("mmap invalid access parameter."))
+        
+        # assume -1 and 0 both mean invalid file descriptor
+        # to 'anonymously' map memory.
+        if fileno != -1 and fileno != 0:
+            fh = cdll.msvcr71._get_osfhandle(fileno)
+            if fh == -1:
+                raise OperationError(space.w_EnvironmentError,
+                                     space.wrap(_get_error_msg()))
+            # Win9x appears to need us seeked to zero
+            SEEK_SET = 0
+            libc._lseek(fileno, 0, SEEK_SET)
+        
+        m = _mmap(space)
+        m._file_handle = HANDLE(INVALID_HANDLE_VALUE)
+        m._map_handle = HANDLE(INVALID_HANDLE_VALUE)
+        
+        if fh:
+            res = BOOL()
+            # it is necessary to duplicate the handle, so the
+            # Python code can close it on us        
+            res = DuplicateHandle(GetCurrentProcess(), # source process handle
+                                  fh, # handle to be duplicated
+                                  GetCurrentProcess(), # target process handle
+                                  byref(m._file_handle), # result
+                                  0, # access - ignored due to options value
+                                  wintypes.BOOL(False), # inherited by child procs?
+                                  DUPLICATE_SAME_ACCESS) # options
+            if not res:
+                raise OperationError(space.wrap(WinError), space.wrap(""))
+        
+            if not map_size:
+                low, high = _get_file_size(fh)
+                if _64BIT:
+                    m._size = (c_long(low.value).value << 32) + 1
+                else:
+                    if high:
+                        # file is too large to map completely
+                        m._size = -1L
+                    else:
+                        m._size = low.value
+            else:
+                m._size = map_size
+        else:
+            m._size = map_size
+
+        if tagname:
+            m._tagname = tagname
+        m._access = access
+        
+        # DWORD is a 4-byte int. If int > 4-byte it must be divided
+        if _64BIT:
+            size_hi = DWORD(m._size >> 32)
+            size_lo = DWORD(m._size & 0xFFFFFFFF)
+        else:
+            size_hi = DWORD(0)
+            size_lo = DWORD(m._size)
+
+        m._map_handle = HANDLE(CreateFileMapping(m._file_handle, None, flProtect,
+                                                 size_hi, size_lo, m._tagname))
+
+        if m._map_handle:
+            m._data = MapViewOfFile(m._map_handle, dwDesiredAccess,
+                                    0, 0, 0)
+            if m._data:
+                m._data = cast(m._data, POINTER(c_char))
+                return m
+            else:
+                dwErr = GetLastError()
+        else:
+            dwErr = GetLastError()
 
+        raise OperationError(space.wrap(WinError), space.wrap(dwErr))
+    mmap.unwrap_spec = [ObjSpace, int, int, str, int]

Modified: pypy/dist/pypy/module/mmap/test/test_mmap.py
==============================================================================
--- pypy/dist/pypy/module/mmap/test/test_mmap.py	(original)
+++ pypy/dist/pypy/module/mmap/test/test_mmap.py	Sat Aug 19 17:57:49 2006
@@ -1,13 +1,13 @@
 from pypy.conftest import gettestobjspace
 import os
 
-if os.name == "nt":
-    from py.test import skip
-    skip("Windows is not supported")
-
 def teardown_module(mod):
-    if os.path.exists("foo"):
-        os.unlink("foo")
+    for p in "abcde":
+        if os.path.exists(p):
+            try:
+                os.unlink(p)
+            except OSError:
+                print "Cannot delete '%s'" % p
 
 class AppTestMMap:
     def setup_class(cls):
@@ -21,16 +21,18 @@
         
     def test_attributes(self):
         import mmap
+        import os
         assert isinstance(mmap.ACCESS_READ, int)
         assert isinstance(mmap.ACCESS_WRITE, int)
         assert isinstance(mmap.ACCESS_COPY, int)
-        assert isinstance(mmap.MAP_ANON, int)
-        assert isinstance(mmap.MAP_ANONYMOUS, int)
-        assert isinstance(mmap.MAP_PRIVATE, int)
-        assert isinstance(mmap.MAP_SHARED, int)
-        assert isinstance(mmap.PROT_EXEC, int)
-        assert isinstance(mmap.PROT_READ, int)
-        assert isinstance(mmap.PROT_WRITE, int)
+        if os.name == "posix":
+            assert isinstance(mmap.MAP_ANON, int)
+            assert isinstance(mmap.MAP_ANONYMOUS, int)
+            assert isinstance(mmap.MAP_PRIVATE, int)
+            assert isinstance(mmap.MAP_SHARED, int)
+            assert isinstance(mmap.PROT_EXEC, int)
+            assert isinstance(mmap.PROT_READ, int)
+            assert isinstance(mmap.PROT_WRITE, int)
         
         assert mmap.error is EnvironmentError
             
@@ -50,17 +52,19 @@
             raises(OverflowError, mmap, 0, sys.maxint)
             raises(ValueError, mmap, 0, 1, flags=2, access=3)
             raises(ValueError, mmap, 0, 1, access=123)
-        # elif _MS_WINDOWS:
-        #     py.test.raises(TypeError, mmap, 0, 1, 2, 3, 4)
-        #     py.test.raises(TypeError, mmap, 0, 1, tagname=123)
-        #     py.test.raises(TypeError, mmap, 0, 1, access="foo")
-        #     py.test.raises(ValueError, mmap, 0, 1, access=-1)
+        elif os.name == "nt":
+            raises(TypeError, mmap, 0, 1, 2, 3, 4)
+            raises(TypeError, mmap, 0, 1, tagname=123)
+            raises(TypeError, mmap, 0, 1, access="foo")
+            raises(ValueError, mmap, 0, 1, access=-1)
 
     def test_file_size(self):
-        # if _MS_WINDOWS:
-        #     py.test.skip("Only Unix checks file size")
+        import os
+        if os.name == "nt":
+            skip("Only Unix checks file size")
+
         from mmap import mmap
-        f = open("foo", "w+")
+        f = open("a", "w+")
         
         f.write("c")
         f.flush()
@@ -69,7 +73,7 @@
 
     def test_mmap_creation(self):
         from mmap import mmap
-        f = open("foo", "w+")
+        f = open("b", "w+")
         
         f.write("c")
         f.flush()
@@ -80,7 +84,7 @@
 
     def test_close(self):
         from mmap import mmap
-        f = open("foo", "w+")
+        f = open("c", "w+")
         
         f.write("c")
         f.flush()
@@ -90,7 +94,7 @@
 
     def test_read_byte(self):
         from mmap import mmap
-        f = open("foo", "w+")
+        f = open("d", "w+")
 
         f.write("c")
         f.flush()
@@ -103,7 +107,7 @@
     def test_readline(self):
         from mmap import mmap
         import os
-        f = open("foo", "w+")
+        f = open("e", "w+")
 
         f.write("foo\n")
         f.flush()



More information about the Pypy-commit mailing list