[pypy-commit] pypy default: check file mode before read/write
bdkearns
noreply at buildbot.pypy.org
Fri Aug 29 19:31:39 CEST 2014
Author: Brian Kearns <bdkearns at 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):
More information about the pypy-commit
mailing list