Author: Amaury Forgeot d'Arc <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit