[pypy-commit] pypy msvcrt-cffi: save this work for later. Idea needed: the subprocess module

arigo pypy.commits at gmail.com
Sun Jul 17 05:01:05 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: msvcrt-cffi
Changeset: r85731:2bd75abf0c25
Date: 2016-07-17 11:02 +0200
http://bitbucket.org/pypy/pypy/changeset/2bd75abf0c25/

Log:	save this work for later. Idea needed: the subprocess module needs
	msvcrt, but of course we need the subprocess module to run at least
	ffi.compile() inside _msvcrt_build.py

diff --git a/lib_pypy/_msvcrt_build.py b/lib_pypy/_msvcrt_build.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_msvcrt_build.py
@@ -0,0 +1,36 @@
+from cffi import FFI
+
+ffi = FFI()
+
+ffi.set_source("_msvcrt_cffi", """
+#include <io.h>
+#include <sys/locking.h>
+#include <conio.h>
+""")
+
+ffi.cdef("""
+int _open_osfhandle(intptr_t osfhandle, int flags);
+intptr_t _get_osfhandle(int fd);
+int _setmode(int fd, int mode);
+int _locking(int fd, int mode, long nbytes);
+
+#define LK_UNLCK ...
+#define LK_LOCK ...
+#define LK_NBLCK ...
+#define LK_RLCK ...
+#define LK_NBRLCK ...
+
+int _kbhit(void);
+char _getch(void);
+wchar_t _getwch(void);
+char _getche(void);
+wchar_t _getwche(void);
+void _putch(char);
+void _putwch(wchar_t);
+int _ungetch(char);
+
+#define EOF ...
+""")
+
+if __name__ == "__main__":
+    ffi.compile()
diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py
--- a/lib_pypy/msvcrt.py
+++ b/lib_pypy/msvcrt.py
@@ -7,26 +7,36 @@
 # XXX incomplete: implemented only functions needed by subprocess.py
 # PAC: 2010/08 added MS locking for Whoosh
 
-import ctypes
+# 07/2016: rewrote in CFFI
+
+import sys
+if sys.platform != 'win32':
+    raise ImportError("The 'msvcrt' module is only available on Windows")
+
+from _msvcrt_cffi import ffi, lib
 import errno
-from ctypes_support import standard_c_lib as _c
-from ctypes_support import get_errno
-
-try:
-    open_osfhandle = _c._open_osfhandle
-except AttributeError: # we are not on windows
-    raise ImportError
 
 try: from __pypy__ import builtinify, validate_fd
 except ImportError: builtinify = validate_fd = lambda f: f
 
 
-open_osfhandle.argtypes = [ctypes.c_int, ctypes.c_int]
-open_osfhandle.restype = ctypes.c_int
+def _ioerr():
+    e = ffi.errno
+    raise IOError(e, errno.errorcode[e])
 
-_get_osfhandle = _c._get_osfhandle
-_get_osfhandle.argtypes = [ctypes.c_int]
-_get_osfhandle.restype = ctypes.c_int
+
+ at builtinify
+def open_osfhandle(fd, flags):
+    """"open_osfhandle(handle, flags) -> file descriptor
+
+    Create a C runtime file descriptor from the file handle handle. The
+    flags parameter should be a bitwise OR of os.O_APPEND, os.O_RDONLY,
+    and os.O_TEXT. The returned file descriptor may be used as a parameter
+    to os.fdopen() to create a file object."""
+    fd = lib._open_osfhandle(fd, flags)
+    if fd == -1:
+        _ioerr()
+    return fd
 
 @builtinify
 def get_osfhandle(fd):
@@ -38,62 +48,61 @@
         validate_fd(fd)
     except OSError as e:
         raise IOError(*e.args)
-    return _get_osfhandle(fd)
+    result = lib._get_osfhandle(fd)
+    if result == -1:
+        _ioerr()
+    return result
 
-setmode = _c._setmode
-setmode.argtypes = [ctypes.c_int, ctypes.c_int]
-setmode.restype = ctypes.c_int
+ at builtinify
+def setmode(fd, flags):
+    """setmode(fd, mode) -> Previous mode
 
-LK_UNLCK, LK_LOCK, LK_NBLCK, LK_RLCK, LK_NBRLCK = range(5)
+    Set the line-end translation mode for the file descriptor fd. To set
+    it to text mode, flags should be os.O_TEXT; for binary, it should be
+    os.O_BINARY."""
+    flags = lib._setmode(fd, flags)
+    if flags == -1:
+        _ioerr()
+    return flags
 
-_locking = _c._locking
-_locking.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int]
-_locking.restype = ctypes.c_int
+LK_UNLCK = lib.LK_UNLCK
+LK_LOCK = lib.LK_LOCK
+LK_NBLCK = lib.LK_NBLCK
+LK_RLCK = lib.RLCK
+LK_NBRLCK = lib.LK_NBRLCK
 
 @builtinify
 def locking(fd, mode, nbytes):
-    '''lock or unlock a number of bytes in a file.'''
-    rv = _locking(fd, mode, nbytes)
+    """"locking(fd, mode, nbytes) -> None
+
+    Lock part of a file based on file descriptor fd from the C runtime.
+    Raises IOError on failure. The locked region of the file extends from
+    the current file position for nbytes bytes, and may continue beyond
+    the end of the file. mode must be one of the LK_* constants listed
+    below. Multiple regions in a file may be locked at the same time, but
+    may not overlap. Adjacent regions are not merged; they must be unlocked
+    individually."""
+    rv = lib._locking(fd, mode, nbytes)
     if rv != 0:
-        e = get_errno()
-        raise IOError(e, errno.errorcode[e])
+        _ioerr()
 
 # Console I/O routines
 
-kbhit = _c._kbhit
-kbhit.argtypes = []
-kbhit.restype = ctypes.c_int
+kbhit = lib._kbhit
+getch = lib._getch
+getwch = lib._getwch
+getche = lib._getche
+getwche = lib._getwche
+putch = lib._putch
+putwch = lib._putwch      # xxx CPython accepts a unicode str of length > 1 and
+                          # discards the other characters, but only in putwch()
 
-getch = _c._getch
-getch.argtypes = []
-getch.restype = ctypes.c_char
+ at builtinify
+def ungetch(ch):
+    if lib._ungetch(ch) == lib.EOF:
+        _ioerr()
 
-getwch = _c._getwch
-getwch.argtypes = []
-getwch.restype = ctypes.c_wchar
-
-getche = _c._getche
-getche.argtypes = []
-getche.restype = ctypes.c_char
-
-getwche = _c._getwche
-getwche.argtypes = []
-getwche.restype = ctypes.c_wchar
-
-putch = _c._putch
-putch.argtypes = [ctypes.c_char]
-putch.restype = None
-
-putwch = _c._putwch
-putwch.argtypes = [ctypes.c_wchar]
-putwch.restype = None
-
-ungetch = _c._ungetch
-ungetch.argtypes = [ctypes.c_char]
-ungetch.restype = None
-
-ungetwch = _c._ungetwch
-ungetwch.argtypes = [ctypes.c_wchar]
-ungetwch.restype = None
-
-del ctypes
+ at builtinify
+def ungetwch(ch):
+    if lib._ungetwch(ch) == lib.EOF:
+        _ioerr()
diff --git a/pypy/tool/build_cffi_imports.py b/pypy/tool/build_cffi_imports.py
--- a/pypy/tool/build_cffi_imports.py
+++ b/pypy/tool/build_cffi_imports.py
@@ -14,6 +14,7 @@
     "gdbm": "_gdbm_build.py"  if sys.platform != "win32" else None,
     "pwdgrp": "_pwdgrp_build.py" if sys.platform != "win32" else None,
     "resource": "_resource_build.py" if sys.platform != "win32" else None,
+    "msvcrt": "_msvcrt_build.py" if sys.platform == "win32" else None,
     "xx": None,    # for testing: 'None' should be completely ignored
     }
 


More information about the pypy-commit mailing list