Klaus Demo bjoern / eb0e34e
Fix #130 -- filewrapper must work with any .read()able object Jonas Haag 2 years ago
5 changed file(s) with 44 addition(s) and 21 deletion(s). Raw diff Collapse all Expand all
00 #include "filewrapper.h"
11 #include "py2py3.h"
22
3 #define FW_self ((FileWrapper*)self)
4
35 int FileWrapper_GetFd(PyObject *self)
46 {
5 return ((FileWrapper*)self)->fd;
7 return FW_self->fd;
68 }
79
810 void FileWrapper_Done(PyObject *self)
911 {
10 PyFile_DecUseCount((PyFileObject*)((FileWrapper*)self)->file);
12 if (FW_self->fd != -1) {
13 PyFile_DecUseCount((PyFileObject*)FW_self->file);
14 }
1115 }
1216
1317 static PyObject*
1418 FileWrapper_New(PyTypeObject* cls, PyObject* args, PyObject* kwargs)
1519 {
1620 PyObject* file;
17 int fd;
18 unsigned int ignored_blocksize;
21 PyObject* blocksize = NULL;
1922
20 if(!PyArg_ParseTuple(args, "O|I:FileWrapper", &file, &ignored_blocksize))
23 if(!PyArg_ParseTuple(args, "O|O:FileWrapper", &file, &blocksize))
2124 return NULL;
2225
23 fd = PyObject_AsFileDescriptor(file);
26 Py_INCREF(file);
27 Py_XINCREF(blocksize);
28
29 int fd = PyObject_AsFileDescriptor(file);
2430 if (fd == -1) {
25 return NULL;
31 PyErr_Clear();
32 } else {
33 PyFile_IncUseCount((PyFileObject*)file);
2634 }
27
28 Py_INCREF(file);
29 PyFile_IncUseCount((PyFileObject*)file);
3035
3136 FileWrapper* wrapper = PyObject_NEW(FileWrapper, cls);
3237 wrapper->file = file;
38 wrapper->blocksize = blocksize;
3339 wrapper->fd = fd;
3440
3541 return (PyObject*)wrapper;
3642 }
3743
3844 static PyObject*
39 FileWrapper_GetAttrO(PyObject* self, PyObject* name)
45 FileWrapper_Iter(PyObject* self)
4046 {
41 return PyObject_GetAttr(((FileWrapper*)self)->file, name);
47 Py_INCREF(self);
48 return self;
4249 }
4350
4451 static PyObject*
45 FileWrapper_Iter(PyObject* self)
52 FileWrapper_IterNext(PyObject* self)
4653 {
47 return PyObject_GetIter(((FileWrapper*)self)->file);
54 PyObject* data = PyObject_CallMethodObjArgs(FW_self->file, _read, FW_self->blocksize, NULL);
55 if (data == NULL) {
56 return NULL;
57 } else if (PyObject_IsTrue(data)) {
58 return data;
59 } else {
60 PyErr_SetNone(PyExc_IndexError);
61 return NULL;
62 }
4863 }
4964
5065 void FileWrapper_dealloc(PyObject* self)
5166 {
52 Py_DECREF(((FileWrapper*)self)->file);
67 Py_DECREF(FW_self->file);
68 Py_XDECREF(FW_self->blocksize);
5369 PyObject_FREE(self);
5470 }
5571
6581 {
6682 FileWrapper_Type.tp_new = FileWrapper_New;
6783 FileWrapper_Type.tp_iter = FileWrapper_Iter;
68 FileWrapper_Type.tp_getattro = FileWrapper_GetAttrO;
84 FileWrapper_Type.tp_iternext = FileWrapper_IterNext;
6985 FileWrapper_Type.tp_flags |= Py_TPFLAGS_DEFAULT;
7086 }
66 typedef struct {
77 PyObject_HEAD
88 PyObject* file;
9 PyObject *blocksize;
910 int fd;
1011 } FileWrapper;
1112
246246 GIL_LOCK(0);
247247
248248 write_state write_state;
249 if(request->iterable && FileWrapper_CheckExact(request->iterable)) {
249 if(request->iterable && FileWrapper_CheckExact(request->iterable) && FileWrapper_GetFd(request->iterable) != -1) {
250250 write_state = on_write_sendfile(mainloop, request);
251251 } else {
252252 write_state = on_write_chunk(mainloop, request);
8181 Py_DECREF(retval);
8282 first_chunk = NULL;
8383 }
84 } else if(FileWrapper_CheckExact(retval)) {
84 } else if(FileWrapper_CheckExact(retval) && FileWrapper_GetFd(retval) != -1) {
8585 request->iterable = retval;
8686 request->iterator = NULL;
8787 first_chunk = NULL;
22 import bjoern
33
44 W = {
5 'callable-iterator': lambda f, e: iter(lambda: f.read(64*1024), ''),
6 'xreadlines': lambda f, e: f,
5 'callable-iterator': lambda f, _: iter(lambda: f.read(64*1024), b''),
6 'xreadlines': lambda f, _: f,
77 'filewrapper': lambda f, env: env['wsgi.file_wrapper'](f),
8 'filewrapper2': lambda f, env: env['wsgi.file_wrapper'](f, 1)
8 'filewrapper2': lambda f, env: env['wsgi.file_wrapper'](f, 1),
9 'pseudo-file': lambda f, env: env['wsgi.file_wrapper'](PseudoFile())
910 }
1011
1112 F = len(sys.argv) > 1 and sys.argv[1] or 'README.rst'
1213 W = len(sys.argv) > 2 and W[sys.argv[2]] or W['filewrapper']
14
15
16 class PseudoFile:
17 def read(self, *ignored):
18 return b'ab'
1319
1420 def app(env, start_response):
1521 f = open(F, 'rb')