[pypy-commit] pypy py3.3: Implement 'x' flag on io.open() / io.FileIO.
mjacob
noreply at buildbot.pypy.org
Fri Feb 27 17:32:33 CET 2015
Author: Manuel Jacob <me at manueljacob.de>
Branch: py3.3
Changeset: r76173:7f15f2e2ab69
Date: 2015-02-27 16:15 +0100
http://bitbucket.org/pypy/pypy/changeset/7f15f2e2ab69/
Log: Implement 'x' flag on io.open() / io.FileIO.
diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py
--- a/pypy/module/_io/interp_fileio.py
+++ b/pypy/module/_io/interp_fileio.py
@@ -4,7 +4,7 @@
from pypy.interpreter.error import wrap_oserror, wrap_oserror2
from rpython.rlib.rarithmetic import r_longlong
from rpython.rlib.rstring import StringBuilder
-from os import O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC
+from os import O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC, O_EXCL
import sys, os, stat, errno
from pypy.module._io.interp_iobase import W_RawIOBase, convert_size
@@ -34,13 +34,14 @@
def _bad_mode(space):
raise OperationError(space.w_ValueError, space.wrap(
- "Must have exactly one of read/write/append mode"))
+ "Must have exactly one of read/write/create/append mode"))
def decode_mode(space, mode):
flags = 0
rwa = False
readable = False
writable = False
+ created = False
append = False
plus = False
@@ -56,6 +57,13 @@
rwa = True
writable = True
flags |= O_CREAT | O_TRUNC
+ elif s == 'x':
+ if rwa:
+ _bad_mode(space)
+ rwa = True
+ created = True
+ writable = True
+ flags |= O_EXCL | O_CREAT
elif s == 'a':
if rwa:
_bad_mode(space)
@@ -86,7 +94,7 @@
flags |= O_BINARY
- return readable, writable, append, flags
+ return readable, writable, created, append, flags
SMALLCHUNK = 8 * 1024
BIGCHUNK = 512 * 1024
@@ -121,6 +129,7 @@
self.fd = -1
self.readable = False
self.writable = False
+ self.created = False
self.appending = False
self.seekable = -1
self.closefd = True
@@ -147,7 +156,7 @@
raise OperationError(space.w_ValueError, space.wrap(
"negative file descriptor"))
- self.readable, self.writable, self.appending, flags = decode_mode(space, mode)
+ self.readable, self.writable, self.created, self.appending, flags = decode_mode(space, mode)
fd_is_own = False
try:
@@ -204,6 +213,11 @@
raise
def _mode(self):
+ if self.created:
+ if self.readable:
+ return 'xb+'
+ else:
+ return 'xb'
if self.appending:
if self.readable:
return 'ab+'
diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py
--- a/pypy/module/_io/interp_io.py
+++ b/pypy/module/_io/interp_io.py
@@ -30,7 +30,7 @@
space.isinstance_w(w_file, space.w_int)):
raise oefmt(space.w_TypeError, "invalid file: %R", w_file)
- reading = writing = appending = updating = text = binary = universal = False
+ reading = writing = creating = appending = updating = text = binary = universal = False
uniq_mode = {}
for flag in mode:
@@ -42,6 +42,8 @@
reading = True
elif flag == "w":
writing = True
+ elif flag == "x":
+ creating = True
elif flag == "a":
appending = True
elif flag == "+":
@@ -61,6 +63,8 @@
rawmode += "r"
if writing:
rawmode += "w"
+ if creating:
+ rawmode += "x"
if appending:
rawmode += "a"
if updating:
@@ -74,9 +78,9 @@
raise OperationError(space.w_ValueError,
space.wrap("can't have text and binary mode at once")
)
- if reading + writing + appending > 1:
+ if reading + writing + creating + appending > 1:
raise OperationError(space.w_ValueError,
- space.wrap("must have exactly one of read/write/append mode")
+ space.wrap("must have exactly one of read/write/create/append mode")
)
if binary and encoding is not None:
raise OperationError(space.w_ValueError,
@@ -123,7 +127,7 @@
if updating:
buffer_cls = W_BufferedRandom
- elif writing or appending:
+ elif writing or creating or appending:
buffer_cls = W_BufferedWriter
elif reading:
buffer_cls = W_BufferedReader
diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py
--- a/pypy/module/_io/test/test_fileio.py
+++ b/pypy/module/_io/test/test_fileio.py
@@ -222,6 +222,17 @@
if os.path.exists(self.tmpfile):
os.unlink(self.tmpfile)
+ def test_open_exclusive(self):
+ # XXX: should raise FileExistsError
+ FileExistsError = OSError
+
+ import _io
+ filename = self.tmpfile + '_x'
+ raises(ValueError, _io.FileIO, filename, 'xw')
+ with _io.FileIO(filename, 'x') as f:
+ assert f.mode == 'xb'
+ raises(FileExistsError, _io.FileIO, filename, 'x')
+
def test_flush_at_exit():
from pypy import conftest
diff --git a/pypy/module/_io/test/test_io.py b/pypy/module/_io/test/test_io.py
--- a/pypy/module/_io/test/test_io.py
+++ b/pypy/module/_io/test/test_io.py
@@ -439,3 +439,14 @@
f.seek(1, 0)
f.read(buffer_size * 2)
assert f.tell() == 1 + buffer_size * 2
+
+ def test_open_exclusive(self):
+ # XXX: should raise FileExistsError
+ FileExistsError = OSError
+
+ import _io
+ filename = self.tmpfile + '_x'
+ raises(ValueError, _io.open, filename, 'xw')
+ with _io.open(filename, 'x') as f:
+ assert f.mode == 'x'
+ raises(FileExistsError, _io.open, filename, 'x')
More information about the pypy-commit
mailing list