Remove an unnecessary check from test_decimal.
[python.git] / Modules / _fileio.c
blob2dc3d743b85f8279c525df2af15cebcc02d74d4e
1 /* Author: Daniel Stutzbach */
3 #define PY_SSIZE_T_CLEAN
4 #include "Python.h"
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <stddef.h> /* For offsetof */
11 * Known likely problems:
13 * - Files larger then 2**32-1
14 * - Files with unicode filenames
15 * - Passing numbers greater than 2**32-1 when an integer is expected
16 * - Making it work on Windows and other oddball platforms
18 * To Do:
20 * - autoconfify header file inclusion
23 #ifdef MS_WINDOWS
24 /* can simulate truncate with Win32 API functions; see file_truncate */
25 #define HAVE_FTRUNCATE
26 #define WIN32_LEAN_AND_MEAN
27 #include <windows.h>
28 #endif
30 typedef struct {
31 PyObject_HEAD
32 int fd;
33 unsigned readable : 1;
34 unsigned writable : 1;
35 int seekable : 2; /* -1 means unknown */
36 int closefd : 1;
37 PyObject *weakreflist;
38 } PyFileIOObject;
40 PyTypeObject PyFileIO_Type;
42 #define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
44 /* Returns 0 on success, errno (which is < 0) on failure. */
45 static int
46 internal_close(PyFileIOObject *self)
48 int save_errno = 0;
49 if (self->fd >= 0) {
50 int fd = self->fd;
51 self->fd = -1;
52 Py_BEGIN_ALLOW_THREADS
53 if (close(fd) < 0)
54 save_errno = errno;
55 Py_END_ALLOW_THREADS
57 return save_errno;
60 static PyObject *
61 fileio_close(PyFileIOObject *self)
63 if (!self->closefd) {
64 self->fd = -1;
65 Py_RETURN_NONE;
67 errno = internal_close(self);
68 if (errno < 0) {
69 PyErr_SetFromErrno(PyExc_IOError);
70 return NULL;
73 Py_RETURN_NONE;
76 static PyObject *
77 fileio_new(PyTypeObject *type, PyObject *args, PyObject *kews)
79 PyFileIOObject *self;
81 assert(type != NULL && type->tp_alloc != NULL);
83 self = (PyFileIOObject *) type->tp_alloc(type, 0);
84 if (self != NULL) {
85 self->fd = -1;
86 self->readable = 0;
87 self->writable = 0;
88 self->seekable = -1;
89 self->closefd = 1;
90 self->weakreflist = NULL;
93 return (PyObject *) self;
96 /* On Unix, open will succeed for directories.
97 In Python, there should be no file objects referring to
98 directories, so we need a check. */
100 static int
101 dircheck(PyFileIOObject* self, char *name)
103 #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
104 struct stat buf;
105 if (self->fd < 0)
106 return 0;
107 if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
108 char *msg = strerror(EISDIR);
109 PyObject *exc;
110 internal_close(self);
112 exc = PyObject_CallFunction(PyExc_IOError, "(iss)",
113 EISDIR, msg, name);
114 PyErr_SetObject(PyExc_IOError, exc);
115 Py_XDECREF(exc);
116 return -1;
118 #endif
119 return 0;
123 static int
124 fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
126 PyFileIOObject *self = (PyFileIOObject *) oself;
127 static char *kwlist[] = {"file", "mode", "closefd", NULL};
128 char *name = NULL;
129 char *mode = "r";
130 char *s;
131 #ifdef MS_WINDOWS
132 Py_UNICODE *widename = NULL;
133 #endif
134 int ret = 0;
135 int rwa = 0, plus = 0, append = 0;
136 int flags = 0;
137 int fd = -1;
138 int closefd = 1;
140 assert(PyFileIO_Check(oself));
141 if (self->fd >= 0) {
142 /* Have to close the existing file first. */
143 if (internal_close(self) < 0)
144 return -1;
147 if (PyArg_ParseTupleAndKeywords(args, kwds, "i|si:fileio",
148 kwlist, &fd, &mode, &closefd)) {
149 if (fd < 0) {
150 PyErr_SetString(PyExc_ValueError,
151 "Negative filedescriptor");
152 return -1;
155 else {
156 PyErr_Clear();
158 #ifdef Py_WIN_WIDE_FILENAMES
159 if (GetVersion() < 0x80000000) {
160 /* On NT, so wide API available */
161 PyObject *po;
162 if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:fileio",
163 kwlist, &po, &mode, &closefd)
165 widename = PyUnicode_AS_UNICODE(po);
166 } else {
167 /* Drop the argument parsing error as narrow
168 strings are also valid. */
169 PyErr_Clear();
172 if (widename == NULL)
173 #endif
175 if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:fileio",
176 kwlist,
177 Py_FileSystemDefaultEncoding,
178 &name, &mode, &closefd))
179 return -1;
183 s = mode;
184 while (*s) {
185 switch (*s++) {
186 case 'r':
187 if (rwa) {
188 bad_mode:
189 PyErr_SetString(PyExc_ValueError,
190 "Must have exactly one of read/write/append mode");
191 goto error;
193 rwa = 1;
194 self->readable = 1;
195 break;
196 case 'w':
197 if (rwa)
198 goto bad_mode;
199 rwa = 1;
200 self->writable = 1;
201 flags |= O_CREAT | O_TRUNC;
202 break;
203 case 'a':
204 if (rwa)
205 goto bad_mode;
206 rwa = 1;
207 self->writable = 1;
208 flags |= O_CREAT;
209 append = 1;
210 break;
211 case 'b':
212 break;
213 case '+':
214 if (plus)
215 goto bad_mode;
216 self->readable = self->writable = 1;
217 plus = 1;
218 break;
219 default:
220 PyErr_Format(PyExc_ValueError,
221 "invalid mode: %.200s", mode);
222 goto error;
226 if (!rwa)
227 goto bad_mode;
229 if (self->readable && self->writable)
230 flags |= O_RDWR;
231 else if (self->readable)
232 flags |= O_RDONLY;
233 else
234 flags |= O_WRONLY;
236 #ifdef O_BINARY
237 flags |= O_BINARY;
238 #endif
240 #ifdef O_APPEND
241 if (append)
242 flags |= O_APPEND;
243 #endif
245 if (fd >= 0) {
246 self->fd = fd;
247 self->closefd = closefd;
249 else {
250 self->closefd = 1;
251 if (!closefd) {
252 PyErr_SetString(PyExc_ValueError,
253 "Cannot use closefd=False with file name");
254 goto error;
257 Py_BEGIN_ALLOW_THREADS
258 errno = 0;
259 #ifdef MS_WINDOWS
260 if (widename != NULL)
261 self->fd = _wopen(widename, flags, 0666);
262 else
263 #endif
264 self->fd = open(name, flags, 0666);
265 Py_END_ALLOW_THREADS
266 if (self->fd < 0) {
267 #ifdef MS_WINDOWS
268 if (widename != NULL)
269 PyErr_SetFromErrnoWithUnicodeFilename(PyExc_IOError, widename);
270 else
271 #endif
272 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
273 goto error;
275 if(dircheck(self, name) < 0)
276 goto error;
279 goto done;
281 error:
282 ret = -1;
284 done:
285 PyMem_Free(name);
286 return ret;
289 static void
290 fileio_dealloc(PyFileIOObject *self)
292 if (self->weakreflist != NULL)
293 PyObject_ClearWeakRefs((PyObject *) self);
295 if (self->fd >= 0 && self->closefd) {
296 errno = internal_close(self);
297 if (errno < 0) {
298 PySys_WriteStderr("close failed: [Errno %d] %s\n",
299 errno, strerror(errno));
303 Py_TYPE(self)->tp_free((PyObject *)self);
306 static PyObject *
307 err_closed(void)
309 PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
310 return NULL;
313 static PyObject *
314 err_mode(char *action)
316 PyErr_Format(PyExc_ValueError, "File not open for %s", action);
317 return NULL;
320 static PyObject *
321 fileio_fileno(PyFileIOObject *self)
323 if (self->fd < 0)
324 return err_closed();
325 return PyInt_FromLong((long) self->fd);
328 static PyObject *
329 fileio_readable(PyFileIOObject *self)
331 if (self->fd < 0)
332 return err_closed();
333 return PyBool_FromLong((long) self->readable);
336 static PyObject *
337 fileio_writable(PyFileIOObject *self)
339 if (self->fd < 0)
340 return err_closed();
341 return PyBool_FromLong((long) self->writable);
344 static PyObject *
345 fileio_seekable(PyFileIOObject *self)
347 if (self->fd < 0)
348 return err_closed();
349 if (self->seekable < 0) {
350 int ret;
351 Py_BEGIN_ALLOW_THREADS
352 ret = lseek(self->fd, 0, SEEK_CUR);
353 Py_END_ALLOW_THREADS
354 if (ret < 0)
355 self->seekable = 0;
356 else
357 self->seekable = 1;
359 return PyBool_FromLong((long) self->seekable);
362 static PyObject *
363 fileio_readinto(PyFileIOObject *self, PyObject *args)
365 Py_buffer pbuf;
366 Py_ssize_t n;
368 if (self->fd < 0)
369 return err_closed();
370 if (!self->readable)
371 return err_mode("reading");
373 if (!PyArg_ParseTuple(args, "w*", &pbuf))
374 return NULL;
376 Py_BEGIN_ALLOW_THREADS
377 errno = 0;
378 n = read(self->fd, pbuf.buf, pbuf.len);
379 Py_END_ALLOW_THREADS
380 PyBuffer_Release(&pbuf);
381 if (n < 0) {
382 if (errno == EAGAIN)
383 Py_RETURN_NONE;
384 PyErr_SetFromErrno(PyExc_IOError);
385 return NULL;
388 return PyLong_FromSsize_t(n);
391 #define DEFAULT_BUFFER_SIZE (8*1024)
393 static PyObject *
394 fileio_readall(PyFileIOObject *self)
396 PyObject *result;
397 Py_ssize_t total = 0;
398 int n;
400 result = PyString_FromStringAndSize(NULL, DEFAULT_BUFFER_SIZE);
401 if (result == NULL)
402 return NULL;
404 while (1) {
405 Py_ssize_t newsize = total + DEFAULT_BUFFER_SIZE;
406 if (PyString_GET_SIZE(result) < newsize) {
407 if (_PyString_Resize(&result, newsize) < 0) {
408 if (total == 0) {
409 Py_DECREF(result);
410 return NULL;
412 PyErr_Clear();
413 break;
416 Py_BEGIN_ALLOW_THREADS
417 errno = 0;
418 n = read(self->fd,
419 PyString_AS_STRING(result) + total,
420 newsize - total);
421 Py_END_ALLOW_THREADS
422 if (n == 0)
423 break;
424 if (n < 0) {
425 if (total > 0)
426 break;
427 if (errno == EAGAIN) {
428 Py_DECREF(result);
429 Py_RETURN_NONE;
431 Py_DECREF(result);
432 PyErr_SetFromErrno(PyExc_IOError);
433 return NULL;
435 total += n;
438 if (PyString_GET_SIZE(result) > total) {
439 if (_PyString_Resize(&result, total) < 0) {
440 /* This should never happen, but just in case */
441 Py_DECREF(result);
442 return NULL;
445 return result;
448 static PyObject *
449 fileio_read(PyFileIOObject *self, PyObject *args)
451 char *ptr;
452 Py_ssize_t n;
453 Py_ssize_t size = -1;
454 PyObject *bytes;
456 if (self->fd < 0)
457 return err_closed();
458 if (!self->readable)
459 return err_mode("reading");
461 if (!PyArg_ParseTuple(args, "|n", &size))
462 return NULL;
464 if (size < 0) {
465 return fileio_readall(self);
468 bytes = PyString_FromStringAndSize(NULL, size);
469 if (bytes == NULL)
470 return NULL;
471 ptr = PyString_AS_STRING(bytes);
473 Py_BEGIN_ALLOW_THREADS
474 errno = 0;
475 n = read(self->fd, ptr, size);
476 Py_END_ALLOW_THREADS
478 if (n < 0) {
479 if (errno == EAGAIN)
480 Py_RETURN_NONE;
481 PyErr_SetFromErrno(PyExc_IOError);
482 return NULL;
485 if (n != size) {
486 if (_PyString_Resize(&bytes, n) < 0) {
487 Py_DECREF(bytes);
488 return NULL;
492 return (PyObject *) bytes;
495 static PyObject *
496 fileio_write(PyFileIOObject *self, PyObject *args)
498 Py_buffer pbuf;
499 Py_ssize_t n;
501 if (self->fd < 0)
502 return err_closed();
503 if (!self->writable)
504 return err_mode("writing");
506 if (!PyArg_ParseTuple(args, "s*", &pbuf))
507 return NULL;
509 Py_BEGIN_ALLOW_THREADS
510 errno = 0;
511 n = write(self->fd, pbuf.buf, pbuf.len);
512 Py_END_ALLOW_THREADS
514 PyBuffer_Release(&pbuf);
516 if (n < 0) {
517 if (errno == EAGAIN)
518 Py_RETURN_NONE;
519 PyErr_SetFromErrno(PyExc_IOError);
520 return NULL;
523 return PyLong_FromSsize_t(n);
526 /* XXX Windows support below is likely incomplete */
528 #if defined(MS_WIN64) || defined(MS_WINDOWS)
529 typedef PY_LONG_LONG Py_off_t;
530 #else
531 typedef off_t Py_off_t;
532 #endif
534 /* Cribbed from posix_lseek() */
535 static PyObject *
536 portable_lseek(int fd, PyObject *posobj, int whence)
538 Py_off_t pos, res;
540 #ifdef SEEK_SET
541 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
542 switch (whence) {
543 #if SEEK_SET != 0
544 case 0: whence = SEEK_SET; break;
545 #endif
546 #if SEEK_CUR != 1
547 case 1: whence = SEEK_CUR; break;
548 #endif
549 #if SEEL_END != 2
550 case 2: whence = SEEK_END; break;
551 #endif
553 #endif /* SEEK_SET */
555 if (posobj == NULL)
556 pos = 0;
557 else {
558 if(PyFloat_Check(posobj)) {
559 PyErr_SetString(PyExc_TypeError, "an integer is required");
560 return NULL;
562 #if defined(HAVE_LARGEFILE_SUPPORT)
563 pos = PyLong_AsLongLong(posobj);
564 #else
565 pos = PyLong_AsLong(posobj);
566 #endif
567 if (PyErr_Occurred())
568 return NULL;
571 Py_BEGIN_ALLOW_THREADS
572 #if defined(MS_WIN64) || defined(MS_WINDOWS)
573 res = _lseeki64(fd, pos, whence);
574 #else
575 res = lseek(fd, pos, whence);
576 #endif
577 Py_END_ALLOW_THREADS
578 if (res < 0)
579 return PyErr_SetFromErrno(PyExc_IOError);
581 #if defined(HAVE_LARGEFILE_SUPPORT)
582 return PyLong_FromLongLong(res);
583 #else
584 return PyLong_FromLong(res);
585 #endif
588 static PyObject *
589 fileio_seek(PyFileIOObject *self, PyObject *args)
591 PyObject *posobj;
592 int whence = 0;
594 if (self->fd < 0)
595 return err_closed();
597 if (!PyArg_ParseTuple(args, "O|i", &posobj, &whence))
598 return NULL;
600 return portable_lseek(self->fd, posobj, whence);
603 static PyObject *
604 fileio_tell(PyFileIOObject *self, PyObject *args)
606 if (self->fd < 0)
607 return err_closed();
609 return portable_lseek(self->fd, NULL, 1);
612 #ifdef HAVE_FTRUNCATE
613 static PyObject *
614 fileio_truncate(PyFileIOObject *self, PyObject *args)
616 PyObject *posobj = NULL;
617 Py_off_t pos;
618 int ret;
619 int fd;
621 fd = self->fd;
622 if (fd < 0)
623 return err_closed();
624 if (!self->writable)
625 return err_mode("writing");
627 if (!PyArg_ParseTuple(args, "|O", &posobj))
628 return NULL;
630 if (posobj == Py_None || posobj == NULL) {
631 /* Get the current position. */
632 posobj = portable_lseek(fd, NULL, 1);
633 if (posobj == NULL)
634 return NULL;
636 else {
637 /* Move to the position to be truncated. */
638 posobj = portable_lseek(fd, posobj, 0);
641 #if defined(HAVE_LARGEFILE_SUPPORT)
642 pos = PyLong_AsLongLong(posobj);
643 #else
644 pos = PyLong_AsLong(posobj);
645 #endif
646 if (PyErr_Occurred())
647 return NULL;
649 #ifdef MS_WINDOWS
650 /* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
651 so don't even try using it. */
653 HANDLE hFile;
655 /* Truncate. Note that this may grow the file! */
656 Py_BEGIN_ALLOW_THREADS
657 errno = 0;
658 hFile = (HANDLE)_get_osfhandle(fd);
659 ret = hFile == (HANDLE)-1;
660 if (ret == 0) {
661 ret = SetEndOfFile(hFile) == 0;
662 if (ret)
663 errno = EACCES;
665 Py_END_ALLOW_THREADS
667 #else
668 Py_BEGIN_ALLOW_THREADS
669 errno = 0;
670 ret = ftruncate(fd, pos);
671 Py_END_ALLOW_THREADS
672 #endif /* !MS_WINDOWS */
674 if (ret != 0) {
675 PyErr_SetFromErrno(PyExc_IOError);
676 return NULL;
679 return posobj;
681 #endif
683 static char *
684 mode_string(PyFileIOObject *self)
686 if (self->readable) {
687 if (self->writable)
688 return "rb+";
689 else
690 return "rb";
692 else
693 return "wb";
696 static PyObject *
697 fileio_repr(PyFileIOObject *self)
699 if (self->fd < 0)
700 return PyString_FromFormat("_fileio._FileIO(-1)");
702 return PyString_FromFormat("_fileio._FileIO(%d, '%s')",
703 self->fd, mode_string(self));
706 static PyObject *
707 fileio_isatty(PyFileIOObject *self)
709 long res;
711 if (self->fd < 0)
712 return err_closed();
713 Py_BEGIN_ALLOW_THREADS
714 res = isatty(self->fd);
715 Py_END_ALLOW_THREADS
716 return PyBool_FromLong(res);
720 PyDoc_STRVAR(fileio_doc,
721 "file(name: str[, mode: str]) -> file IO object\n"
722 "\n"
723 "Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n"
724 "writing or appending. The file will be created if it doesn't exist\n"
725 "when opened for writing or appending; it will be truncated when\n"
726 "opened for writing. Add a '+' to the mode to allow simultaneous\n"
727 "reading and writing.");
729 PyDoc_STRVAR(read_doc,
730 "read(size: int) -> bytes. read at most size bytes, returned as bytes.\n"
731 "\n"
732 "Only makes one system call, so less data may be returned than requested\n"
733 "In non-blocking mode, returns None if no data is available.\n"
734 "On end-of-file, returns ''.");
736 PyDoc_STRVAR(readall_doc,
737 "readall() -> bytes. read all data from the file, returned as bytes.\n"
738 "\n"
739 "In non-blocking mode, returns as much as is immediately available,\n"
740 "or None if no data is available. On end-of-file, returns ''.");
742 PyDoc_STRVAR(write_doc,
743 "write(b: bytes) -> int. Write bytes b to file, return number written.\n"
744 "\n"
745 "Only makes one system call, so not all of the data may be written.\n"
746 "The number of bytes actually written is returned.");
748 PyDoc_STRVAR(fileno_doc,
749 "fileno() -> int. \"file descriptor\".\n"
750 "\n"
751 "This is needed for lower-level file interfaces, such the fcntl module.");
753 PyDoc_STRVAR(seek_doc,
754 "seek(offset: int[, whence: int]) -> None. Move to new file position.\n"
755 "\n"
756 "Argument offset is a byte count. Optional argument whence defaults to\n"
757 "0 (offset from start of file, offset should be >= 0); other values are 1\n"
758 "(move relative to current position, positive or negative), and 2 (move\n"
759 "relative to end of file, usually negative, although many platforms allow\n"
760 "seeking beyond the end of a file)."
761 "\n"
762 "Note that not all file objects are seekable.");
764 #ifdef HAVE_FTRUNCATE
765 PyDoc_STRVAR(truncate_doc,
766 "truncate([size: int]) -> None. Truncate the file to at most size bytes.\n"
767 "\n"
768 "Size defaults to the current file position, as returned by tell()."
769 "The current file position is changed to the value of size.");
770 #endif
772 PyDoc_STRVAR(tell_doc,
773 "tell() -> int. Current file position");
775 PyDoc_STRVAR(readinto_doc,
776 "readinto() -> Undocumented. Don't use this; it may go away.");
778 PyDoc_STRVAR(close_doc,
779 "close() -> None. Close the file.\n"
780 "\n"
781 "A closed file cannot be used for further I/O operations. close() may be\n"
782 "called more than once without error. Changes the fileno to -1.");
784 PyDoc_STRVAR(isatty_doc,
785 "isatty() -> bool. True if the file is connected to a tty device.");
787 PyDoc_STRVAR(seekable_doc,
788 "seekable() -> bool. True if file supports random-access.");
790 PyDoc_STRVAR(readable_doc,
791 "readable() -> bool. True if file was opened in a read mode.");
793 PyDoc_STRVAR(writable_doc,
794 "writable() -> bool. True if file was opened in a write mode.");
796 static PyMethodDef fileio_methods[] = {
797 {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc},
798 {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc},
799 {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc},
800 {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc},
801 {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc},
802 {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc},
803 #ifdef HAVE_FTRUNCATE
804 {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc},
805 #endif
806 {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc},
807 {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc},
808 {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc},
809 {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc},
810 {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc},
811 {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc},
812 {NULL, NULL} /* sentinel */
815 /* 'closed' and 'mode' are attributes for backwards compatibility reasons. */
817 static PyObject *
818 get_closed(PyFileIOObject *self, void *closure)
820 return PyBool_FromLong((long)(self->fd < 0));
823 static PyObject *
824 get_closefd(PyFileIOObject *self, void *closure)
826 return PyBool_FromLong((long)(self->closefd));
829 static PyObject *
830 get_mode(PyFileIOObject *self, void *closure)
832 return PyString_FromString(mode_string(self));
835 static PyGetSetDef fileio_getsetlist[] = {
836 {"closed", (getter)get_closed, NULL, "True if the file is closed"},
837 {"closefd", (getter)get_closefd, NULL,
838 "True if the file descriptor will be closed"},
839 {"mode", (getter)get_mode, NULL, "String giving the file mode"},
840 {0},
843 PyTypeObject PyFileIO_Type = {
844 PyVarObject_HEAD_INIT(NULL, 0)
845 "_FileIO",
846 sizeof(PyFileIOObject),
848 (destructor)fileio_dealloc, /* tp_dealloc */
849 0, /* tp_print */
850 0, /* tp_getattr */
851 0, /* tp_setattr */
852 0, /* tp_compare */
853 (reprfunc)fileio_repr, /* tp_repr */
854 0, /* tp_as_number */
855 0, /* tp_as_sequence */
856 0, /* tp_as_mapping */
857 0, /* tp_hash */
858 0, /* tp_call */
859 0, /* tp_str */
860 PyObject_GenericGetAttr, /* tp_getattro */
861 0, /* tp_setattro */
862 0, /* tp_as_buffer */
863 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
864 fileio_doc, /* tp_doc */
865 0, /* tp_traverse */
866 0, /* tp_clear */
867 0, /* tp_richcompare */
868 offsetof(PyFileIOObject, weakreflist), /* tp_weaklistoffset */
869 0, /* tp_iter */
870 0, /* tp_iternext */
871 fileio_methods, /* tp_methods */
872 0, /* tp_members */
873 fileio_getsetlist, /* tp_getset */
874 0, /* tp_base */
875 0, /* tp_dict */
876 0, /* tp_descr_get */
877 0, /* tp_descr_set */
878 0, /* tp_dictoffset */
879 fileio_init, /* tp_init */
880 PyType_GenericAlloc, /* tp_alloc */
881 fileio_new, /* tp_new */
882 PyObject_Del, /* tp_free */
885 static PyMethodDef module_methods[] = {
886 {NULL, NULL}
889 PyMODINIT_FUNC
890 init_fileio(void)
892 PyObject *m; /* a module object */
894 m = Py_InitModule3("_fileio", module_methods,
895 "Fast implementation of io.FileIO.");
896 if (m == NULL)
897 return;
898 if (PyType_Ready(&PyFileIO_Type) < 0)
899 return;
900 Py_INCREF(&PyFileIO_Type);
901 PyModule_AddObject(m, "_FileIO", (PyObject *) &PyFileIO_Type);