Author: Brian Kearns <bdkea...@gmail.com> Branch: Changeset: r73182:7dd943c6998d Date: 2014-08-29 13:25 -0400 http://bitbucket.org/pypy/pypy/changeset/7dd943c6998d/
Log: check file mode before read/write diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py --- a/pypy/module/_file/interp_file.py +++ b/pypy/module/_file/interp_file.py @@ -30,6 +30,8 @@ w_name = None mode = "<uninitialized file>" binary = False + readable = False + writable = False softspace= 0 # Required according to file object docs encoding = None errors = None @@ -61,6 +63,12 @@ self.fd = fd self.mode = mode self.binary = "b" in mode + if 'r' in mode or 'U' in mode: + self.readable = True + if 'w' in mode or 'a' in mode: + self.writable = True + if '+' in mode: + self.readable = self.writable = True if w_name is not None: self.w_name = w_name self.stream = stream @@ -89,6 +97,16 @@ self.space.wrap("I/O operation on closed file") ) + def check_readable(self): + if not self.readable: + raise OperationError(self.space.w_IOError, self.space.wrap( + "File not open for reading")) + + def check_writable(self): + if not self.writable: + raise OperationError(self.space.w_IOError, self.space.wrap( + "File not open for writing")) + def getstream(self): """Return self.stream or raise an app-level ValueError if missing (i.e. if the file is closed).""" @@ -176,6 +194,7 @@ @unwrap_spec(n=int) def direct_read(self, n=-1): stream = self.getstream() + self.check_readable() if n < 0: return stream.readall() else: @@ -201,6 +220,7 @@ @unwrap_spec(size=int) def direct_readline(self, size=-1): stream = self.getstream() + self.check_readable() if size < 0: return stream.readline() else: @@ -227,6 +247,7 @@ @unwrap_spec(size=int) def direct_readlines(self, size=0): stream = self.getstream() + self.check_readable() # this is implemented as: .read().split('\n') # except that it keeps the \n in the resulting strings if size <= 0: @@ -260,6 +281,7 @@ def direct_truncate(self, w_size=None): # note: a wrapped size! stream = self.getstream() + self.check_writable() space = self.space if space.is_none(w_size): size = stream.tell() @@ -269,6 +291,7 @@ def direct_write(self, w_data): space = self.space + self.check_writable() if self.binary: data = space.getarg_w('s*', w_data).as_str() else: @@ -462,6 +485,7 @@ space = self.space self.check_closed() + self.check_writable() lines = space.fixedview(w_lines) for i, w_line in enumerate(lines): if not space.isinstance_w(w_line, space.w_str): diff --git a/pypy/module/_file/test/test_file_extra.py b/pypy/module/_file/test/test_file_extra.py --- a/pypy/module/_file/test/test_file_extra.py +++ b/pypy/module/_file/test/test_file_extra.py @@ -555,15 +555,7 @@ import errno, sys f = open(fn) exc = raises(IOError, f.truncate, 3) - # CPython explicitly checks the file mode - # PyPy relies on the libc to raise the error - if '__pypy__' not in sys.builtin_module_names: - assert str(exc.value) == "File not open for writing" - else: - if sys.platform == 'win32': - assert exc.value.errno == 5 # ERROR_ACCESS_DENIED - else: - assert exc.value.errno == errno.EINVAL + assert str(exc.value) == "File not open for writing" f.close() def test_readinto(self): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit