Author: Amaury Forgeot d'Arc <amaur...@gmail.com>
Branch: py3k
Changeset: r61501:a09cb059a3bb
Date: 2013-02-19 22:38 +0100
http://bitbucket.org/pypy/pypy/changeset/a09cb059a3bb/

Log:    Fix cffi support for FILE*

diff --git a/pypy/module/_cffi_backend/ctypeptr.py 
b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -2,6 +2,8 @@
 Pointers.
 """
 
+import os
+
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.error import wrap_oserror
 from rpython.rtyper.lltypesystem import lltype, rffi
@@ -247,11 +249,10 @@
         return W_CTypePtrBase.cast(self, w_ob)
 
     def prepare_file(self, w_ob):
-        from pypy.module._file.interp_file import W_File
-        from pypy.module._cffi_backend import ctypefunc
+        from pypy.module._io.interp_iobase import W_IOBase
         ob = self.space.interpclass_w(w_ob)
-        if isinstance(ob, W_File):
-            return prepare_file_argument(self.space, ob)
+        if isinstance(ob, W_IOBase):
+            return prepare_iofile_argument(self.space, w_ob)
         else:
             return lltype.nullptr(rffi.CCHARP.TO)
 
@@ -350,15 +351,21 @@
     def close(self):
         rffi_fclose(self.llf)
 
-def prepare_file_argument(space, fileobj):
-    fileobj.direct_flush()
+def prepare_iofile_argument(space, w_fileobj):
+    fileobj = space.interpclass_w(w_fileobj)
+    from pypy.module._io.interp_iobase import W_IOBase
+    assert isinstance(fileobj, W_IOBase)
+    space.call_method(w_fileobj, "flush")
     if fileobj.cffi_fileobj is None:
-        fd = fileobj.direct_fileno()
+        fd = space.int_w(space.call_method(w_fileobj, "fileno"))
         if fd < 0:
             raise OperationError(space.w_ValueError,
                                  space.wrap("file has no OS file descriptor"))
+        fd = os.dup(fd)
+        mode = space.str_w(space.getattr(w_fileobj, space.wrap("mode")))
         try:
-            fileobj.cffi_fileobj = CffiFileObj(fd, fileobj.mode)
+            fileobj.cffi_fileobj = CffiFileObj(fd, mode)
         except OSError, e:
             raise wrap_oserror(space, e)
     return fileobj.cffi_fileobj.llf
+
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -2480,13 +2480,13 @@
     assert len(p) == 4
     assert list(p) == [b"f", b"o", b"o", b"\x00"]
 
-# XXX hack
-if sys.version_info >= (3,):
-    try:
-        import posix, io
-        posix.fdopen = io.open
-    except ImportError:
-        pass   # win32
+import io
+fdopen_funcs = [io.open]
+try:
+    import posix
+    fdopen_funcs.append(posix.fdopen)
+except (ImportError, AttributeError):  # win32, or py3k
+    pass
 
 def test_FILE():
     if sys.platform == "win32":
@@ -2503,22 +2503,22 @@
     fputs = ll.load_function(BFunc, "fputs")
     fscanf = ll.load_function(BFunc2, "fscanf")
     #
-    import posix
-    fdr, fdw = posix.pipe()
-    fr1 = posix.fdopen(fdr, 'rb', 256)
-    fw1 = posix.fdopen(fdw, 'wb', 256)
-    #
-    fw1.write(b"X")
-    res = fputs(b"hello world\n", fw1)
-    assert res >= 0
-    fw1.flush()     # should not be needed
-    #
-    p = newp(new_array_type(BCharP, 100), None)
-    res = fscanf(fr1, b"%s\n", p)
-    assert res == 1
-    assert string(p) == b"Xhello"
-    fr1.close()
-    fw1.close()
+    for fdopen in fdopen_funcs:
+        fdr, fdw = posix.pipe()
+        fr1 = fdopen(fdr, 'rb', 256)
+        fw1 = fdopen(fdw, 'wb', 256)
+        #
+        fw1.write(b"X")
+        res = fputs(b"hello world\n", fw1)
+        assert res >= 0
+        fw1.flush()     # should not be needed
+        #
+        p = newp(new_array_type(BCharP, 100), None)
+        res = fscanf(fr1, b"%s\n", p)
+        assert res == 1
+        assert string(p) == b"Xhello"
+        fr1.close()
+        fw1.close()
 
 def test_FILE_only_for_FILE_arg():
     if sys.platform == "win32":
@@ -2533,15 +2533,15 @@
     ll = find_and_load_library('c')
     fputs = ll.load_function(BFunc, "fputs")
     #
-    import posix
-    fdr, fdw = posix.pipe()
-    fr1 = posix.fdopen(fdr, 'r')
-    fw1 = posix.fdopen(fdw, 'w')
-    #
-    e = py.test.raises(TypeError, fputs, b"hello world\n", fw1)
-    assert str(e.value).startswith(
-        "initializer for ctype 'struct NOT_FILE *' must "
-        "be a cdata pointer, not ")
+    for fdopen in fdopen_funcs:
+        fdr, fdw = posix.pipe()
+        fr1 = fdopen(fdr, 'r')
+        fw1 = fdopen(fdw, 'w')
+        #
+        e = py.test.raises(TypeError, fputs, b"hello world\n", fw1)
+        assert str(e.value).startswith(
+            "initializer for ctype 'struct NOT_FILE *' must "
+            "be a cdata pointer, not ")
 
 def test_FILE_object():
     if sys.platform == "win32":
@@ -2558,22 +2558,23 @@
     fputs = ll.load_function(BFunc, "fputs")
     fileno = ll.load_function(BFunc2, "fileno")
     #
-    import posix
-    fdr, fdw = posix.pipe()
-    fw1 = posix.fdopen(fdw, 'wb', 256)
-    #
-    fw1p = cast(BFILEP, fw1)
-    fw1.write(b"X")
-    fw1.flush()
-    res = fputs(b"hello\n", fw1p)
-    assert res >= 0
-    res = fileno(fw1p)
-    assert (res == fdw) == (sys.version_info < (3,))
-    fw1.close()
-    #
-    data = posix.read(fdr, 256)
-    assert data == b"Xhello\n"
-    posix.close(fdr)
+    for fdopen in fdopen_funcs:
+        fdr, fdw = posix.pipe()
+        fw1 = fdopen(fdw, 'wb', 256)
+        #
+        fw1p = cast(BFILEP, fw1)
+        fw1.write(b"X")
+        fw1.flush()
+        res = fputs(b"hello\n", fw1p)
+        assert res >= 0
+        res = fileno(fw1p)
+        if fdopen is not io.open and 'PY_DOT_PY' not in globals():
+            assert res == fdw
+        fw1.close()
+        #
+        data = posix.read(fdr, 256)
+        assert data == b"Xhello\n"
+        posix.close(fdr)
 
 def test_GetLastError():
     if sys.platform != "win32":
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -37,6 +37,8 @@
         raise unsupported(space, "File or stream is not seekable")
 
 class W_IOBase(Wrappable):
+    cffi_fileobj = None    # pypy/module/_cffi_backend
+
     def __init__(self, space):
         # XXX: IOBase thinks it has to maintain its own internal state in
         # `__IOBase_closed` and call flush() by itself, but it is redundant
@@ -106,6 +108,12 @@
     def close_w(self, space):
         if self._CLOSED():
             return
+
+        cffifo = self.cffi_fileobj
+        self.cffi_fileobj = None
+        if cffifo is not None:
+            cffifo.close()
+
         try:
             space.call_method(self, "flush")
         finally:
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to