Author: Philip Jenvey <pjen...@underboss.org> Branch: py3k Changeset: r73960:906383ab46d1 Date: 2014-10-14 12:51 -0700 http://bitbucket.org/pypy/pypy/changeset/906383ab46d1/
Log: move the py3 specific _getfileinformation/_getfinalpathname out of rpython diff --git a/pypy/module/posix/interp_nt.py b/pypy/module/posix/interp_nt.py new file mode 100644 --- /dev/null +++ b/pypy/module/posix/interp_nt.py @@ -0,0 +1,130 @@ +from rpython.rlib import rwin32 +from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.module.ll_win32file import make_win32_traits +from rpython.rtyper.module.support import UnicodeTraits +from rpython.translator.tool.cbuild import ExternalCompilationInfo + + +# XXX: pypy_GetFinalPathNameByHandle is needed to call the dynamically +# found GetFinalPathNameByHandle function with a non-standard calling +# convention. currently FuncType pointer calls w/ non-standard calling +# conventions don't work after translation +separate_module_source = """\ +DWORD +pypy_GetFinalPathNameByHandle(FARPROC address, HANDLE hFile, + LPTSTR lpszFilePath, DWORD cchFilePath, + DWORD dwFlags) { + DWORD (WINAPI *func)(HANDLE, LPTSTR, DWORD, DWORD); + *(FARPROC*)&func = address; + return func(hFile, lpszFilePath, cchFilePath, dwFlags); +} +""" +eci = ExternalCompilationInfo( + includes=['windows.h'], + separate_module_sources=[separate_module_source], + export_symbols=['pypy_GetFinalPathNameByHandle'] + ) +pypy_GetFinalPathNameByHandle = rffi.llexternal( + 'pypy_GetFinalPathNameByHandle', + [rffi.VOIDP, rwin32.HANDLE, rffi.CWCHARP, rwin32.DWORD, rwin32.DWORD], + rwin32.DWORD, compilation_info=eci) + + +# plain NotImplementedError is invalid RPython +class LLNotImplemented(NotImplementedError): + + def __init__(self, msg): + self.msg = msg + + +def make_traits(traits): + win32traits = make_win32_traits(traits) + + class NTTraits(win32traits): + + GetFinalPathNameByHandle_HANDLE = lltype.nullptr(rffi.VOIDP.TO) + + def check_GetFinalPathNameByHandle(self): + if (self.GetFinalPathNameByHandle_HANDLE != + lltype.nullptr(rffi.VOIDP.TO)): + return True + + from rpython.rlib.rdynload import GetModuleHandle, dlsym + hKernel32 = GetModuleHandle("KERNEL32") + try: + func = dlsym(hKernel32, 'GetFinalPathNameByHandleW') + except KeyError: + return False + + self.GetFinalPathNameByHandle_HANDLE = func + return True + + def GetFinalPathNameByHandle(self, *args): + assert (self.GetFinalPathNameByHandle_HANDLE != + lltype.nullptr(rffi.VOIDP.TO)) + return pypy_GetFinalPathNameByHandle( + self.GetFinalPathNameByHandle_HANDLE, *args) + + return NTTraits() + + +def make__getfileinformation_impl(traits): + win32traits = make_traits(traits) + + def _getfileinformation_llimpl(fd): + hFile = rwin32.get_osfhandle(fd) + with lltype.scoped_alloc( + win32traits.BY_HANDLE_FILE_INFORMATION) as info: + if win32traits.GetFileInformationByHandle(hFile, info) == 0: + raise rwin32.lastWindowsError("_getfileinformation") + return (rffi.cast(lltype.Signed, info.c_dwVolumeSerialNumber), + rffi.cast(lltype.Signed, info.c_nFileIndexHigh), + rffi.cast(lltype.Signed, info.c_nFileIndexLow)) + + return _getfileinformation_llimpl + + +def make__getfinalpathname_impl(traits): + assert traits.str is unicode, 'Currently only handles unicode paths' + win32traits = make_traits(traits) + + def _getfinalpathname_llimpl(path): + if not win32traits.check_GetFinalPathNameByHandle(): + raise LLNotImplemented("GetFinalPathNameByHandle not available on " + "this platform") + + hFile = win32traits.CreateFile(path, 0, 0, None, + win32traits.OPEN_EXISTING, + win32traits.FILE_FLAG_BACKUP_SEMANTICS, + rwin32.NULL_HANDLE) + if hFile == rwin32.INVALID_HANDLE_VALUE: + raise rwin32.lastWindowsError("CreateFile") + + VOLUME_NAME_DOS = rffi.cast(rwin32.DWORD, win32traits.VOLUME_NAME_DOS) + try: + usize = win32traits.GetFinalPathNameByHandle( + hFile, + lltype.nullptr(traits.CCHARP.TO), + rffi.cast(rwin32.DWORD, 0), + VOLUME_NAME_DOS) + if usize == 0: + raise rwin32.lastWindowsError("GetFinalPathNameByHandle") + + size = rffi.cast(lltype.Signed, usize) + with rffi.scoped_alloc_unicodebuffer(size + 1) as buf: + result = win32traits.GetFinalPathNameByHandle( + hFile, + buf.raw, + usize, + VOLUME_NAME_DOS) + if result == 0: + raise rwin32.lastWindowsError("GetFinalPathNameByHandle") + return buf.str(rffi.cast(lltype.Signed, result)) + finally: + rwin32.CloseHandle(hFile) + + return _getfinalpathname_llimpl + + +_getfileinformation = make__getfileinformation_impl(UnicodeTraits()) +_getfinalpathname = make__getfinalpathname_impl(UnicodeTraits()) diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -5,7 +5,8 @@ from rpython.rlib.objectmodel import specialize from rpython.rlib.rarithmetic import r_longlong from rpython.rlib.unroll import unrolling_iterable -from rpython.rtyper.module import ll_os, ll_os_stat +from rpython.rtyper.module import ll_os_stat +from rpython.rtyper.module.ll_os import RegisterOs from pypy.interpreter.gateway import unwrap_spec, WrappedDefault from pypy.interpreter.error import OperationError, wrap_oserror, wrap_oserror2 @@ -1204,7 +1205,7 @@ raise wrap_oserror(space, e) def declare_new_w_star(name): - if name in ll_os.RegisterOs.w_star_returning_int: + if name in RegisterOs.w_star_returning_int: @unwrap_spec(status=c_int) def WSTAR(space, status): return space.wrap(getattr(os, name)(status)) @@ -1216,7 +1217,7 @@ WSTAR.func_name = name return WSTAR -for name in ll_os.RegisterOs.w_star: +for name in RegisterOs.w_star: if hasattr(os, name): func = declare_new_w_star(name) globals()[name] = func @@ -1384,10 +1385,12 @@ return space.w_None if _WIN32: + from pypy.module.posix import interp_nt as nt + @unwrap_spec(fd=c_int) def _getfileinformation(space, fd): try: - info = ll_os._getfileinformation(fd) + info = nt._getfileinformation(fd) except OSError as e: raise wrap_oserror(space, e) return space.newtuple([space.wrap(info[0]), @@ -1397,8 +1400,8 @@ def _getfinalpathname(space, w_path): path = space.unicode_w(w_path) try: - result = ll_os._getfinalpathname(path) - except ll_os.LLNotImplemented as e: + result = nt._getfinalpathname(path) + except nt.LLNotImplemented as e: raise OperationError(space.w_NotImplementedError, space.wrap(e.msg)) except OSError as e: diff --git a/pypy/module/posix/test/test_nt.py b/pypy/module/posix/test/test_nt.py new file mode 100644 --- /dev/null +++ b/pypy/module/posix/test/test_nt.py @@ -0,0 +1,27 @@ +import os +import sys + +import py + +if not sys.platform.startswith('win'): + py.test.skip("requires Windows") + +from pypy.module.posix import interp_nt as nt + + +def test__getfileinformation(): + with open(__file__) as fp: + stat = os.fstat(fp.fileno()) + info = nt._getfileinformation(fp.fileno()) + serial, high, low = info + assert type(serial) in (int, long) + assert (high << 32) + low == stat.st_ino + + +def test__getfinalpathname(): + path = __file__.decode('mbcs') + try: + result = nt._getfinalpathname(path) + except nt.LLNotImplemented: + py.test.skip("_getfinalpathname not supported on this platform") + assert os.path.exists(result) diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py --- a/rpython/rtyper/module/ll_os.py +++ b/rpython/rtyper/module/ll_os.py @@ -105,12 +105,6 @@ _CYGWIN = sys.platform == 'cygwin' -# plain NotImplementedError is invalid RPython -class LLNotImplemented(NotImplementedError): - - def __init__(self, msg): - self.msg = msg - class CConfig: """ Definitions for platform integration. @@ -1969,12 +1963,10 @@ return OsEnvironController() # ____________________________________________________________ -# Support for the WindowsError exception and misc functions +# Support for the WindowsError exception if sys.platform == 'win32': from rpython.rlib import rwin32 - from rpython.rtyper.module.ll_win32file import ( - make__getfileinformation_impl, make__getfinalpathname_impl) class RegisterFormatError(BaseLazyRegistering): def __init__(self): @@ -1985,6 +1977,3 @@ return extdef([lltype.Signed], str, "rwin32_FormatError", llimpl=rwin32.llimpl_FormatError) - - _getfileinformation = make__getfileinformation_impl(UnicodeTraits()) - _getfinalpathname = make__getfinalpathname_impl(UnicodeTraits()) diff --git a/rpython/rtyper/module/ll_win32file.py b/rpython/rtyper/module/ll_win32file.py --- a/rpython/rtyper/module/ll_win32file.py +++ b/rpython/rtyper/module/ll_win32file.py @@ -10,17 +10,6 @@ from rpython.tool.sourcetools import func_renamer from rpython.rlib.objectmodel import specialize -separate_module_source = """\ -DWORD -pypy_GetFinalPathNameByHandle(FARPROC address, HANDLE hFile, - LPTSTR lpszFilePath, DWORD cchFilePath, - DWORD dwFlags) { - DWORD (WINAPI *func)(HANDLE, LPTSTR, DWORD, DWORD); - *(FARPROC*)&func = address; - return func(hFile, lpszFilePath, cchFilePath, dwFlags); -} -""" - def make_win32_traits(traits): from rpython.rlib import rwin32 @@ -32,8 +21,6 @@ class CConfig: _compilation_info_ = ExternalCompilationInfo( includes = ['windows.h', 'winbase.h', 'sys/stat.h'], - separate_module_sources=[separate_module_source], - export_symbols=['pypy_GetFinalPathNameByHandle'] ) WIN32_FIND_DATA = platform.Struct( 'struct _WIN32_FIND_DATA' + suffix, @@ -205,34 +192,7 @@ [traits.CCHARP, traits.CCHARP], rwin32.BOOL) - GetFinalPathNameByHandle_HANDLE = lltype.nullptr(rffi.VOIDP.TO) - pypy_GetFinalPathNameByHandle = staticmethod(rffi.llexternal( - 'pypy_GetFinalPathNameByHandle', - [rffi.VOIDP, rwin32.HANDLE, rffi.CWCHARP, rwin32.DWORD, rwin32.DWORD], - rwin32.DWORD, compilation_info=CConfig._compilation_info_)) - - def check_GetFinalPathNameByHandle(self): - if (self.GetFinalPathNameByHandle_HANDLE != - lltype.nullptr(rffi.VOIDP.TO)): - return True - - from rpython.rlib.rdynload import GetModuleHandle, dlsym - hKernel32 = GetModuleHandle("KERNEL32") - try: - func = dlsym(hKernel32, 'GetFinalPathNameByHandle' + suffix) - except KeyError: - return False - - self.GetFinalPathNameByHandle_HANDLE = func - return True - - def GetFinalPathNameByHandle(self, *args): - assert (self.GetFinalPathNameByHandle_HANDLE != - lltype.nullptr(rffi.VOIDP.TO)) - return self.pypy_GetFinalPathNameByHandle( - self.GetFinalPathNameByHandle_HANDLE, *args) - - return Win32Traits() + return Win32Traits #_______________________________________________________________ # listdir @@ -451,68 +411,3 @@ lltype.free(mtime, flavor='raw') return os_utime_llimpl - -#_______________________________________________________________ -# _getfileinformation (py3) - -def make__getfileinformation_impl(traits): - from rpython.rlib import rwin32 - win32traits = make_win32_traits(traits) - - def _getfileinformation_llimpl(fd): - hFile = rwin32.get_osfhandle(fd) - with lltype.scoped_alloc( - win32traits.BY_HANDLE_FILE_INFORMATION) as info: - if win32traits.GetFileInformationByHandle(hFile, info) == 0: - raise rwin32.lastWindowsError("_getfileinformation") - return (rffi.cast(lltype.Signed, info.c_dwVolumeSerialNumber), - rffi.cast(lltype.Signed, info.c_nFileIndexHigh), - rffi.cast(lltype.Signed, info.c_nFileIndexLow)) - - return _getfileinformation_llimpl - -#_______________________________________________________________ -# _getfinalpathname (py3) - -def make__getfinalpathname_impl(traits): - from rpython.rlib import rwin32 - from rpython.rtyper.module.ll_os import LLNotImplemented - assert traits.str is unicode, 'Currently only handles unicode paths' - win32traits = make_win32_traits(traits) - - def _getfinalpathname_llimpl(path): - if not win32traits.check_GetFinalPathNameByHandle(): - raise LLNotImplemented("GetFinalPathNameByHandle not available on " - "this platform") - - hFile = win32traits.CreateFile(path, 0, 0, None, - win32traits.OPEN_EXISTING, - win32traits.FILE_FLAG_BACKUP_SEMANTICS, - rwin32.NULL_HANDLE) - if hFile == rwin32.INVALID_HANDLE_VALUE: - raise rwin32.lastWindowsError("CreateFile") - - VOLUME_NAME_DOS = rffi.cast(rwin32.DWORD, win32traits.VOLUME_NAME_DOS) - try: - usize = win32traits.GetFinalPathNameByHandle( - hFile, - lltype.nullptr(traits.CCHARP.TO), - rffi.cast(rwin32.DWORD, 0), - VOLUME_NAME_DOS) - if usize == 0: - raise rwin32.lastWindowsError("GetFinalPathNameByHandle") - - size = rffi.cast(lltype.Signed, usize) - with rffi.scoped_alloc_unicodebuffer(size + 1) as buf: - result = win32traits.GetFinalPathNameByHandle( - hFile, - buf.raw, - usize, - VOLUME_NAME_DOS) - if result == 0: - raise rwin32.lastWindowsError("GetFinalPathNameByHandle") - return buf.str(rffi.cast(lltype.Signed, result)) - finally: - rwin32.CloseHandle(hFile) - - return _getfinalpathname_llimpl diff --git a/rpython/rtyper/module/test/test_ll_win32file.py b/rpython/rtyper/module/test/test_ll_win32file.py deleted file mode 100644 --- a/rpython/rtyper/module/test/test_ll_win32file.py +++ /dev/null @@ -1,26 +0,0 @@ -import os - -import py - -from rpython.rtyper.module import ll_os - -if not ll_os._WIN32: - py.test.skip("requires Windows") - - -def test__getfileinformation(): - with open(__file__) as fp: - stat = os.fstat(fp.fileno()) - info = ll_os._getfileinformation(fp.fileno()) - serial, high, low = info - assert type(serial) in (int, long) - assert (high << 32) + low == stat.st_ino - - -def test__getfinalpathname(): - path = __file__.decode('mbcs') - try: - result = ll_os._getfinalpathname(path) - except ll_os.LLNotImplemented: - py.test.skip("_getfinalpathname not supported on this platform") - assert os.path.exists(result) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit