[pypy-svn] r78313 - in pypy/branch/fast-forward/pypy/module/_io: . test
afa at codespeak.net
afa at codespeak.net
Tue Oct 26 19:30:11 CEST 2010
Author: afa
Date: Tue Oct 26 19:30:09 2010
New Revision: 78313
Modified:
pypy/branch/fast-forward/pypy/module/_io/interp_bufferedio.py
pypy/branch/fast-forward/pypy/module/_io/test/test_bufferedio.py
Log:
Fix properties of incompletely initialized Buffered* objects.
This is especially important to avoid segfaults in __del__...
Modified: pypy/branch/fast-forward/pypy/module/_io/interp_bufferedio.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_io/interp_bufferedio.py (original)
+++ pypy/branch/fast-forward/pypy/module/_io/interp_bufferedio.py Tue Oct 26 19:30:09 2010
@@ -1,6 +1,6 @@
from __future__ import with_statement
from pypy.interpreter.typedef import (
- TypeDef, generic_new_descr)
+ TypeDef, GetSetProperty, generic_new_descr)
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.baseobjspace import ObjSpace, W_Root
from pypy.interpreter.error import OperationError, operationerrfmt
@@ -11,12 +11,15 @@
from pypy.module._io.interp_io import DEFAULT_BUFFER_SIZE, W_BlockingIOError
from pypy.module.thread.os_lock import Lock
+STATE_ZERO, STATE_OK, STATE_DETACHED = range(3)
+
class BlockingIOError(Exception):
pass
class W_BufferedIOBase(W_IOBase):
def __init__(self, space):
W_IOBase.__init__(self, space)
+ self.state = STATE_ZERO
self.buffer = lltype.nullptr(rffi.CCHARP.TO)
self.pos = 0 # Current logical position in the buffer
@@ -84,6 +87,18 @@
except OperationError:
pass
+ def _check_init(self, space):
+ if self.state == STATE_ZERO:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "I/O operation on uninitialized object"))
+ elif self.state == STATE_DETACHED:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "raw stream has been detached"))
+
+ def _check_closed(self, space, message=None):
+ self._check_init(space)
+ W_IOBase._check_closed(self, space, message)
+
def _raw_tell(self, space):
w_pos = space.call_method(self.raw, "tell")
pos = space.r_longlong_w(w_pos)
@@ -94,6 +109,10 @@
self.abs_pos = pos
return pos
+ def closed_get_w(space, self):
+ self._check_init(space)
+ return space.getattr(self.raw, space.wrap("closed"))
+
def _readahead(self):
if self.readable and self.read_end != -1:
return self.read_end - self.pos
@@ -155,6 +174,7 @@
@unwrap_spec('self', ObjSpace)
def close_w(self, space):
+ self._check_init(space)
with self.lock:
if self._closed(space):
return
@@ -164,6 +184,7 @@
@unwrap_spec('self', ObjSpace)
def flush_w(self, space):
+ self._check_init(space)
return space.call_method(self.raw, "flush")
def _writer_flush_unlocked(self, space, restore_pos=False):
@@ -223,7 +244,7 @@
l.append(self.buffer[i])
return self._write(space, ''.join(l))
-class W_BufferedReader(W_BufferedIOBase, BufferedMixin):
+class W_BufferedReader(BufferedMixin, W_BufferedIOBase):
def __init__(self, space):
W_BufferedIOBase.__init__(self, space)
self.ok = False
@@ -231,6 +252,7 @@
@unwrap_spec('self', ObjSpace, W_Root, int)
def descr_init(self, space, w_raw, buffer_size=DEFAULT_BUFFER_SIZE):
+ self.state = STATE_ZERO
raw = space.interp_w(W_IOBase, w_raw)
raw.check_readable_w(space)
@@ -240,6 +262,7 @@
self._init(space)
self._reader_reset_buf()
+ self.state = STATE_OK
@unwrap_spec('self', ObjSpace, W_Root)
def read_w(self, space, w_size=None):
@@ -397,11 +420,13 @@
seek = interp2app(W_BufferedReader.seek_w),
close = interp2app(W_BufferedReader.close_w),
flush = interp2app(W_BufferedReader.flush_w),
+ closed = GetSetProperty(W_BufferedReader.closed_get_w),
)
-class W_BufferedWriter(W_BufferedIOBase, BufferedMixin):
+class W_BufferedWriter(BufferedMixin, W_BufferedIOBase):
@unwrap_spec('self', ObjSpace, W_Root, int)
def descr_init(self, space, w_raw, buffer_size=DEFAULT_BUFFER_SIZE):
+ self.state = STATE_ZERO
raw = space.interp_w(W_IOBase, w_raw)
raw.check_writable_w(space)
@@ -411,6 +436,7 @@
self._init(space)
self._writer_reset_buf()
+ self.state = STATE_OK
def _adjust_position(self, new_pos):
self.pos = new_pos
@@ -545,6 +571,7 @@
# from the mixin class
seek = interp2app(W_BufferedWriter.seek_w),
close = interp2app(W_BufferedWriter.close_w),
+ closed = GetSetProperty(W_BufferedWriter.closed_get_w),
)
class W_BufferedRWPair(W_BufferedIOBase):
Modified: pypy/branch/fast-forward/pypy/module/_io/test/test_bufferedio.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_io/test/test_bufferedio.py (original)
+++ pypy/branch/fast-forward/pypy/module/_io/test/test_bufferedio.py Tue Oct 26 19:30:09 2010
@@ -1,4 +1,4 @@
-from pypy.conftest import gettestobjspace
+from pypy.conftest import gettestobjspace, option
from pypy.interpreter.gateway import interp2app
from pypy.tool.udir import udir
@@ -38,9 +38,12 @@
cls.space = gettestobjspace(usemodules=['_io'])
tmpfile = udir.join('tmpfile')
cls.w_tmpfile = cls.space.wrap(str(tmpfile))
- def readfile(space):
- return space.wrap(tmpfile.read())
- cls.w_readfile = cls.space.wrap(interp2app(readfile))
+ if option.runappdirect:
+ cls.w_readfile = tmpfile.read
+ else:
+ def readfile(space):
+ return space.wrap(tmpfile.read())
+ cls.w_readfile = cls.space.wrap(interp2app(readfile))
def test_write(self):
import _io
@@ -57,3 +60,12 @@
f.write("abcd" * 5000)
f.close()
assert self.readfile() == "abcd" * 5000
+
+ def test_incomplete(self):
+ import _io
+ raw = _io.FileIO(self.tmpfile)
+ b = _io.BufferedWriter.__new__(_io.BufferedWriter)
+ raises(IOError, b.__init__, raw) # because file is not writable
+ raises(ValueError, getattr, b, 'closed')
+ raises(ValueError, b.flush)
+ raises(ValueError, b.close)
More information about the Pypy-commit
mailing list