Author: Brian Kearns <[email protected]>
Branch:
Changeset: r73436:d00e4c12507a
Date: 2014-09-10 21:11 -0400
http://bitbucket.org/pypy/pypy/changeset/d00e4c12507a/
Log: test/fix fdopen buffering
diff --git a/rpython/rlib/rfile.py b/rpython/rlib/rfile.py
--- a/rpython/rlib/rfile.py
+++ b/rpython/rlib/rfile.py
@@ -153,18 +153,12 @@
finally:
lltype.free(ll_name, flavor='raw')
_dircheck(ll_file)
- if buffering >= 0:
- buf = lltype.nullptr(rffi.CCHARP.TO)
- if buffering == 0:
- c_setvbuf(ll_file, buf, _IONBF, 0)
- elif buffering == 1:
- c_setvbuf(ll_file, buf, _IOLBF, BUFSIZ)
- else:
- c_setvbuf(ll_file, buf, _IOFBF, buffering)
- return RFile(ll_file, mode)
+ f = RFile(ll_file, mode)
+ f._setbufsize(buffering)
+ return f
-def create_fdopen_rfile(fd, mode="r"):
+def create_fdopen_rfile(fd, mode="r", buffering=-1):
newmode = _sanitize_mode(mode)
fd = rffi.cast(rffi.INT, fd)
rposix.validate_fd(fd)
@@ -177,7 +171,9 @@
finally:
lltype.free(ll_mode, flavor='raw')
_dircheck(ll_file)
- return RFile(ll_file, mode)
+ f = RFile(ll_file, mode)
+ f._setbufsize(buffering)
+ return f
def create_temp_rfile():
@@ -213,6 +209,7 @@
class RFile(object):
+ _setbuf = lltype.nullptr(rffi.CCHARP.TO)
_univ_newline = False
_newlinetypes = NEWLINE_UNKNOWN
_skipnextlf = False
@@ -223,6 +220,23 @@
self._univ_newline = 'U' in mode
self._close2 = close2
+ def _setbufsize(self, bufsize):
+ if bufsize >= 0:
+ if bufsize == 0:
+ mode = _IONBF
+ elif bufsize == 1:
+ mode = _IOLBF
+ bufsize = BUFSIZ
+ else:
+ mode = _IOFBF
+ if self._setbuf:
+ lltype.free(self._setbuf, flavor='raw')
+ if mode == _IONBF:
+ self._setbuf = lltype.nullptr(rffi.CCHARP.TO)
+ else:
+ self._setbuf = lltype.malloc(rffi.CCHARP.TO, bufsize,
flavor='raw')
+ c_setvbuf(self._ll_file, self._setbuf, mode, bufsize)
+
def __del__(self):
"""Closes the described file when the object's last reference
goes away. Unlike an explicit call to close(), this is meant
@@ -233,6 +247,8 @@
do_close = self._close2[1]
if do_close:
do_close(ll_file) # return value ignored
+ if self._setbuf:
+ lltype.free(self._setbuf, flavor='raw')
def _cleanup_(self):
self._ll_file = lltype.nullptr(FILEP.TO)
@@ -251,11 +267,16 @@
# double close is allowed
self._ll_file = lltype.nullptr(FILEP.TO)
do_close = self._close2[0]
- if do_close:
- res = do_close(ll_file)
- if res == -1:
- errno = rposix.get_errno()
- raise IOError(errno, os.strerror(errno))
+ try:
+ if do_close:
+ res = do_close(ll_file)
+ if res == -1:
+ errno = rposix.get_errno()
+ raise IOError(errno, os.strerror(errno))
+ finally:
+ if self._setbuf:
+ lltype.free(self._setbuf, flavor='raw')
+ self._setbuf = lltype.nullptr(rffi.CCHARP.TO)
return res
def _check_closed(self):
diff --git a/rpython/rlib/test/test_rfile.py b/rpython/rlib/test/test_rfile.py
--- a/rpython/rlib/test/test_rfile.py
+++ b/rpython/rlib/test/test_rfile.py
@@ -104,15 +104,53 @@
f()
self.interpret(f, [])
+ @py.test.mark.skipif("sys.platform == 'win32'")
+ # http://msdn.microsoft.com/en-us/library/86cebhfs.aspx
+ def test_fdopen_buffering_line(self):
+ fname = str(self.tmpdir.join('file_1a'))
+
+ def f():
+ g = open(fname, 'w')
+ f = os.fdopen(os.dup(g.fileno()), 'w', 1)
+ g.close()
+ f.write('dupa\ndupb')
+ f2 = open(fname, 'r')
+ assert f2.read() == 'dupa\n'
+ f.close()
+ assert f2.read() == 'dupb'
+ f2.close()
+
+ f()
+ self.interpret(f, [])
+
def test_open_buffering_full(self):
fname = str(self.tmpdir.join('file_1b'))
def f():
f = open(fname, 'w', 128)
- f.write('dupa')
+ f.write('dupa\ndupb')
f2 = open(fname, 'r')
assert f2.read() == ''
- f.write('z' * 5000)
+ f.write('z' * 120)
+ assert f2.read() != ''
+ f.close()
+ assert f2.read() != ''
+ f2.close()
+
+ f()
+ self.interpret(f, [])
+
+ def test_fdopen_buffering_full(self):
+ fname = str(self.tmpdir.join('file_1b'))
+
+ def f():
+ g = open(fname, 'w')
+ f = os.fdopen(os.dup(g.fileno()), 'w', 128)
+ g.close()
+ f.write('dupa\ndupb')
+ f2 = open(fname, 'r')
+ assert f2.read() == ''
+ f.write('z' * 120)
assert f2.read() != ''
f.close()
assert f2.read() != ''
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit