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