Issue #12760: Add a create mode to open(). Patch by David Townshend.
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index 3829e0b..57cd9aa 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -46,6 +46,7 @@
typedef struct {
PyObject_HEAD
int fd;
+ unsigned int created : 1;
unsigned int readable : 1;
unsigned int writable : 1;
signed int seekable : 2; /* -1 means unknown */
@@ -152,6 +153,7 @@
self = (fileio *) type->tp_alloc(type, 0);
if (self != NULL) {
self->fd = -1;
+ self->created = 0;
self->readable = 0;
self->writable = 0;
self->seekable = -1;
@@ -290,15 +292,23 @@
s = mode;
while (*s) {
switch (*s++) {
- case 'r':
+ case 'x':
if (rwa) {
bad_mode:
PyErr_SetString(PyExc_ValueError,
- "Must have exactly one of read/write/append "
+ "Must have exactly one of create/read/write/append "
"mode and at most one plus");
goto error;
}
rwa = 1;
+ self->created = 1;
+ self->writable = 1;
+ flags |= O_EXCL | O_CREAT;
+ break;
+ case 'r':
+ if (rwa)
+ goto bad_mode;
+ rwa = 1;
self->readable = 1;
break;
case 'w':
@@ -988,6 +998,12 @@
static char *
mode_string(fileio *self)
{
+ if (self->created) {
+ if (self->readable)
+ return "xb+";
+ else
+ return "xb";
+ }
if (self->readable) {
if (self->writable)
return "rb+";
@@ -1049,15 +1065,17 @@
PyDoc_STRVAR(fileio_doc,
"file(name: str[, mode: str][, opener: None]) -> file IO object\n"
"\n"
-"Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n"
-"writing or appending. The file will be created if it doesn't exist\n"
-"when opened for writing or appending; it will be truncated when\n"
-"opened for writing. Add a '+' to the mode to allow simultaneous\n"
-"reading and writing. A custom opener can be used by passing a\n"
-"callable as *opener*. The underlying file descriptor for the file\n"
+"Open a file. The mode can be 'r', 'w', 'x' or 'a' for reading (default),\n"
+"writing, creating or appending. The file will be created if it doesn't\n"
+"exist when opened for writing or appending; it will be truncated when\n"
+"opened for writing. A `FileExistsError` will be raised if it already\n"
+"exists when opened for creating. Opening a file for creating implies\n"
+"writing so this mode behaves in a similar way to 'w'.Add a '+' to the mode\n"
+"to allow simultaneous reading and writing. A custom opener can be used by\n"
+"passing a callable as *opener*. The underlying file descriptor for the file\n"
"object is then obtained by calling opener with (*name*, *flags*).\n"
-"*opener* must return an open file descriptor (passing os.open as\n"
-"*opener* results in functionality similar to passing None).");
+"*opener* must return an open file descriptor (passing os.open as *opener*\n"
+"results in functionality similar to passing None).");
PyDoc_STRVAR(read_doc,
"read(size: int) -> bytes. read at most size bytes, returned as bytes.\n"