| OLD | NEW |
| 1 /* Author: Daniel Stutzbach */ | 1 /* Author: Daniel Stutzbach */ |
| 2 | 2 |
| 3 #define PY_SSIZE_T_CLEAN | 3 #define PY_SSIZE_T_CLEAN |
| 4 #include "Python.h" | 4 #include "Python.h" |
| 5 #include "structmember.h" | 5 #include "structmember.h" |
| 6 #ifdef HAVE_SYS_TYPES_H | 6 #ifdef HAVE_SYS_TYPES_H |
| 7 #include <sys/types.h> | 7 #include <sys/types.h> |
| 8 #endif | 8 #endif |
| 9 #ifdef HAVE_SYS_STAT_H | 9 #ifdef HAVE_SYS_STAT_H |
| 10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 } | 205 } |
| 206 #endif | 206 #endif |
| 207 return 0; | 207 return 0; |
| 208 } | 208 } |
| 209 | 209 |
| 210 | 210 |
| 211 static int | 211 static int |
| 212 fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) | 212 fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) |
| 213 { | 213 { |
| 214 fileio *self = (fileio *) oself; | 214 fileio *self = (fileio *) oself; |
| 215 static char *kwlist[] = {"file", "mode", "closefd", NULL}; | 215 static char *kwlist[] = {"file", "mode", "closefd", "opener", NULL}; |
| 216 const char *name = NULL; | 216 const char *name = NULL; |
| 217 PyObject *nameobj, *stringobj = NULL; | 217 PyObject *nameobj, *stringobj = NULL, *opener = Py_None; |
| 218 char *mode = "r"; | 218 char *mode = "r"; |
| 219 char *s; | 219 char *s; |
| 220 #ifdef MS_WINDOWS | 220 #ifdef MS_WINDOWS |
| 221 Py_UNICODE *widename = NULL; | 221 Py_UNICODE *widename = NULL; |
| 222 #endif | 222 #endif |
| 223 int ret = 0; | 223 int ret = 0; |
| 224 int rwa = 0, plus = 0, append = 0; | 224 int rwa = 0, plus = 0, append = 0; |
| 225 int flags = 0; | 225 int flags = 0; |
| 226 int fd = -1; | 226 int fd = -1; |
| 227 int closefd = 1; | 227 int closefd = 1; |
| 228 | 228 |
| 229 assert(PyFileIO_Check(oself)); | 229 assert(PyFileIO_Check(oself)); |
| 230 if (self->fd >= 0) { | 230 if (self->fd >= 0) { |
| 231 /* Have to close the existing file first. */ | 231 /* Have to close the existing file first. */ |
| 232 if (internal_close(self) < 0) | 232 if (internal_close(self) < 0) |
| 233 return -1; | 233 return -1; |
| 234 } | 234 } |
| 235 | 235 |
| 236 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|si:fileio", | 236 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|siO:fileio", |
| 237 kwlist, &nameobj, &mode, &closefd)) | 237 kwlist, &nameobj, &mode, &closefd, |
| 238 &opener)) |
| 238 return -1; | 239 return -1; |
| 239 | 240 |
| 240 if (PyFloat_Check(nameobj)) { | 241 if (PyFloat_Check(nameobj)) { |
| 241 PyErr_SetString(PyExc_TypeError, | 242 PyErr_SetString(PyExc_TypeError, |
| 242 "integer argument expected, got float"); | 243 "integer argument expected, got float"); |
| 243 return -1; | 244 return -1; |
| 244 } | 245 } |
| 245 | 246 |
| 246 fd = PyLong_AsLong(nameobj); | 247 fd = PyLong_AsLong(nameobj); |
| 247 if (fd < 0) { | 248 if (fd < 0) { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 self->closefd = closefd; | 357 self->closefd = closefd; |
| 357 } | 358 } |
| 358 else { | 359 else { |
| 359 self->closefd = 1; | 360 self->closefd = 1; |
| 360 if (!closefd) { | 361 if (!closefd) { |
| 361 PyErr_SetString(PyExc_ValueError, | 362 PyErr_SetString(PyExc_ValueError, |
| 362 "Cannot use closefd=False with file name"); | 363 "Cannot use closefd=False with file name"); |
| 363 goto error; | 364 goto error; |
| 364 } | 365 } |
| 365 | 366 |
| 366 Py_BEGIN_ALLOW_THREADS | |
| 367 errno = 0; | 367 errno = 0; |
| 368 if (opener == Py_None) { |
| 369 Py_BEGIN_ALLOW_THREADS |
| 368 #ifdef MS_WINDOWS | 370 #ifdef MS_WINDOWS |
| 369 if (widename != NULL) | 371 if (widename != NULL) |
| 370 self->fd = _wopen(widename, flags, 0666); | 372 self->fd = _wopen(widename, flags, 0666); |
| 371 else | 373 else |
| 372 #endif | 374 #endif |
| 373 self->fd = open(name, flags, 0666); | 375 self->fd = open(name, flags, 0666); |
| 374 Py_END_ALLOW_THREADS | 376 Py_END_ALLOW_THREADS |
| 377 } else { |
| 378 PyObject *fdobj = PyObject_CallFunction( |
| 379 opener, "Oi", nameobj, flags); |
| 380 if (fdobj == NULL) |
| 381 goto error; |
| 382 if (!PyLong_Check(fdobj)) { |
| 383 Py_DECREF(fdobj); |
| 384 PyErr_SetString(PyExc_TypeError, |
| 385 "expected integer from opener"); |
| 386 goto error; |
| 387 } |
| 388 |
| 389 self->fd = PyLong_AsLong(fdobj); |
| 390 Py_DECREF(fdobj); |
| 391 if (self->fd == -1) { |
| 392 goto error; |
| 393 } |
| 394 } |
| 395 |
| 375 if (self->fd < 0) { | 396 if (self->fd < 0) { |
| 376 #ifdef MS_WINDOWS | 397 #ifdef MS_WINDOWS |
| 377 if (widename != NULL) | 398 if (widename != NULL) |
| 378 PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj); | 399 PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj); |
| 379 else | 400 else |
| 380 #endif | 401 #endif |
| 381 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); | 402 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); |
| 382 goto error; | 403 goto error; |
| 383 } | 404 } |
| 384 if (dircheck(self, name) < 0) | 405 if (dircheck(self, name) < 0) |
| (...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 static PyObject * | 1031 static PyObject * |
| 1011 fileio_getstate(fileio *self) | 1032 fileio_getstate(fileio *self) |
| 1012 { | 1033 { |
| 1013 PyErr_Format(PyExc_TypeError, | 1034 PyErr_Format(PyExc_TypeError, |
| 1014 "cannot serialize '%s' object", Py_TYPE(self)->tp_name); | 1035 "cannot serialize '%s' object", Py_TYPE(self)->tp_name); |
| 1015 return NULL; | 1036 return NULL; |
| 1016 } | 1037 } |
| 1017 | 1038 |
| 1018 | 1039 |
| 1019 PyDoc_STRVAR(fileio_doc, | 1040 PyDoc_STRVAR(fileio_doc, |
| 1020 "file(name: str[, mode: str]) -> file IO object\n" | 1041 "file(name: str[, mode: str][, opener: None]) -> file IO object\n" |
| 1021 "\n" | 1042 "\n" |
| 1022 "Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n" | 1043 "Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n" |
| 1023 "writing or appending. The file will be created if it doesn't exist\n" | 1044 "writing or appending. The file will be created if it doesn't exist\n" |
| 1024 "when opened for writing or appending; it will be truncated when\n" | 1045 "when opened for writing or appending; it will be truncated when\n" |
| 1025 "opened for writing. Add a '+' to the mode to allow simultaneous\n" | 1046 "opened for writing. Add a '+' to the mode to allow simultaneous\n" |
| 1026 "reading and writing."); | 1047 "reading and writing. A custom opener can be used by passing a\n" |
| 1048 "callable as *opener*. The underlying file descriptor for the file\n" |
| 1049 "object is then obtained by calling opener with (*name*, *flags*).\n" |
| 1050 "*opener* must return an open file descriptor (passing os.open as\n" |
| 1051 "*opener* results in functionality similar to passing None)."); |
| 1027 | 1052 |
| 1028 PyDoc_STRVAR(read_doc, | 1053 PyDoc_STRVAR(read_doc, |
| 1029 "read(size: int) -> bytes. read at most size bytes, returned as bytes.\n" | 1054 "read(size: int) -> bytes. read at most size bytes, returned as bytes.\n" |
| 1030 "\n" | 1055 "\n" |
| 1031 "Only makes one system call, so less data may be returned than requested\n" | 1056 "Only makes one system call, so less data may be returned than requested\n" |
| 1032 "In non-blocking mode, returns None if no data is available.\n" | 1057 "In non-blocking mode, returns None if no data is available.\n" |
| 1033 "On end-of-file, returns ''."); | 1058 "On end-of-file, returns ''."); |
| 1034 | 1059 |
| 1035 PyDoc_STRVAR(readall_doc, | 1060 PyDoc_STRVAR(readall_doc, |
| 1036 "readall() -> bytes. read all data from the file, returned as bytes.\n" | 1061 "readall() -> bytes. read all data from the file, returned as bytes.\n" |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1176 0, /* tp_base */ | 1201 0, /* tp_base */ |
| 1177 0, /* tp_dict */ | 1202 0, /* tp_dict */ |
| 1178 0, /* tp_descr_get */ | 1203 0, /* tp_descr_get */ |
| 1179 0, /* tp_descr_set */ | 1204 0, /* tp_descr_set */ |
| 1180 offsetof(fileio, dict), /* tp_dictoffset */ | 1205 offsetof(fileio, dict), /* tp_dictoffset */ |
| 1181 fileio_init, /* tp_init */ | 1206 fileio_init, /* tp_init */ |
| 1182 PyType_GenericAlloc, /* tp_alloc */ | 1207 PyType_GenericAlloc, /* tp_alloc */ |
| 1183 fileio_new, /* tp_new */ | 1208 fileio_new, /* tp_new */ |
| 1184 PyObject_GC_Del, /* tp_free */ | 1209 PyObject_GC_Del, /* tp_free */ |
| 1185 }; | 1210 }; |
| OLD | NEW |