ajp-wsgi
changeset 49:ffa257a88246
Minor code cleanup.
| author | Allan Saddi <allan@saddi.com> |
|---|---|
| date | Sun, 24 Dec 2006 17:25:00 +0000 |
| parents | c719a6d917c0 |
| children | ecb586935c77 6eb96bc18250 |
| files | ChangeLog Makefile.in ajp-glue.c input.c version.h wrapper.c wsgi-int.h wsgi.c wsgiinput.c wsgiwrapper.c |
| diffstat | 10 files changed, 651 insertions(+), 651 deletions(-) [+] |
line diff
1.1 --- a/ChangeLog Fri Dec 22 19:42:02 2006 +0000 1.2 +++ b/ChangeLog Sun Dec 24 17:25:00 2006 +0000 1.3 @@ -1,3 +1,7 @@ 1.4 +2006-12-24 Allan Saddi <allan@saddi.com> 1.5 + 1.6 + * Minor code cleanup. 1.7 + 1.8 2006-12-22 Allan Saddi <allan@saddi.com> 1.9 1.10 * Release version 0.5
2.1 --- a/Makefile.in Fri Dec 22 19:42:02 2006 +0000 2.2 +++ b/Makefile.in Sun Dec 24 17:25:00 2006 +0000 2.3 @@ -10,7 +10,8 @@ 2.4 SYSLIBS= @@SYSLIBS@@ 2.5 VERSION= @@VERSION@@ 2.6 2.7 -OBJS= main.o ajp.o wsgi.o input.o wrapper.o ajp-glue.o threadpool.o 2.8 +OBJS= main.o ajp.o wsgi.o wsgiinput.o wsgiwrapper.o ajp-glue.o \ 2.9 + threadpool.o 2.10 2.11 all: ajp-wsgi 2.12 2.13 @@ -23,9 +24,9 @@ 2.14 2.15 wsgi.o: wsgi.c wsgi-int.h wsgi.h 2.16 2.17 -input.o: input.c wsgi-int.h wsgi.h 2.18 +wsgiinput.o: wsgiinput.c wsgi-int.h wsgi.h 2.19 2.20 -wrapper.o: wrapper.c wsgi-int.h wsgi.h 2.21 +wsgiwrapper.o: wsgiwrapper.c wsgi-int.h wsgi.h 2.22 2.23 ajp-glue.o: ajp-glue.c ajp.h wsgi-int.h wsgi.h 2.24
3.1 --- a/ajp-glue.c Fri Dec 22 19:42:02 2006 +0000 3.2 +++ b/ajp-glue.c Sun Dec 24 17:25:00 2006 +0000 3.3 @@ -131,7 +131,7 @@ 3.4 goto bad; 3.5 3.6 /* wsgi.errors */ 3.7 - if (PyDict_SetItemString(environ, "wsgi.errors", self->pStderr)) 3.8 + if (PyDict_SetItemString(environ, "wsgi.errors", wsgiStderr)) 3.9 goto bad; 3.10 3.11 /* wsgi.multithread */ 3.12 @@ -156,9 +156,9 @@ 3.13 3.14 /* SCRIPT_NAME/PATH_INFO */ 3.15 pathInfo = req_uri ? req_uri : req->uri; 3.16 - if (self->scriptNameLen) { 3.17 - if (!strncmp(pathInfo, self->scriptName, self->scriptNameLen)) 3.18 - pathInfo = &pathInfo[self->scriptNameLen]; 3.19 + if (wsgiScriptNameLen) { 3.20 + if (!strncmp(pathInfo, wsgiScriptName, wsgiScriptNameLen)) 3.21 + pathInfo = &pathInfo[wsgiScriptNameLen]; 3.22 else 3.23 fprintf (stderr, "WARNING: SCRIPT_NAME does not match REQUEST_URI\n"); 3.24 } 3.25 @@ -166,7 +166,7 @@ 3.26 if (wsgiPutEnv(self, "PATH_INFO", pathInfo)) 3.27 goto bad; 3.28 3.29 - if (wsgiPutEnv(self, "SCRIPT_NAME", self->scriptName)) 3.30 + if (wsgiPutEnv(self, "SCRIPT_NAME", wsgiScriptName)) 3.31 goto bad; 3.32 3.33 /* Ensure QUERY_STRING is set */
4.1 --- a/input.c Fri Dec 22 19:42:02 2006 +0000 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,434 +0,0 @@ 4.4 -/*- 4.5 - * Copyright (c) 2006 Allan Saddi <allan@saddi.com> 4.6 - * All rights reserved. 4.7 - * 4.8 - * Redistribution and use in source and binary forms, with or without 4.9 - * modification, are permitted provided that the following conditions 4.10 - * are met: 4.11 - * 1. Redistributions of source code must retain the above copyright 4.12 - * notice, this list of conditions and the following disclaimer. 4.13 - * 2. Redistributions in binary form must reproduce the above copyright 4.14 - * notice, this list of conditions and the following disclaimer in the 4.15 - * documentation and/or other materials provided with the distribution. 4.16 - * 4.17 - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 4.18 - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4.19 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4.20 - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4.21 - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4.22 - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4.23 - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4.24 - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4.25 - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 4.26 - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 4.27 - * SUCH DAMAGE. 4.28 - * 4.29 - * $Id$ 4.30 - */ 4.31 - 4.32 -#include <Python.h> 4.33 - 4.34 -#include <assert.h> 4.35 - 4.36 -#include "wsgi-int.h" 4.37 - 4.38 -/* Add data as a new chunk at the tail of our chunk list */ 4.39 -int 4.40 -wsgiBodyHandler(void *ctxt, uint8_t *data, size_t len) 4.41 -{ 4.42 - InputStream *self = (InputStream *)((Request *)wsgiGetRequestData(ctxt))->input; 4.43 - struct InputStream_chunk *chunk; 4.44 - 4.45 - if (!len) return 0; 4.46 - 4.47 - if ((chunk = PyMem_Malloc(sizeof(*chunk) + len)) == NULL) 4.48 - return -1; 4.49 - 4.50 - chunk->next = NULL; 4.51 - chunk->size = len; 4.52 - memcpy(InputStream_chunk_DATA(chunk), data, len); 4.53 - 4.54 - if (self->chunks) { 4.55 - self->tail->next = chunk; 4.56 - self->tail = chunk; 4.57 - } 4.58 - else { 4.59 - self->chunks = self->tail = chunk; 4.60 - } 4.61 - 4.62 - self->avail += len; 4.63 - 4.64 - return 0; 4.65 -} 4.66 - 4.67 -/* Find occurrence of a character within our buffers */ 4.68 -static int 4.69 -InputStream_findChar(InputStream *self, int start, int c) 4.70 -{ 4.71 - struct InputStream_chunk *chunk = self->chunks; 4.72 - int index = 0; 4.73 - 4.74 - /* Find starting chunk */ 4.75 - while (chunk != NULL) { 4.76 - if (chunk->size > start) 4.77 - break; 4.78 - 4.79 - index += chunk->size; 4.80 - start -= chunk->size; 4.81 - chunk = chunk->next; 4.82 - } 4.83 - 4.84 - while (chunk != NULL) { 4.85 - char *data = InputStream_chunk_DATA(chunk); 4.86 - char *found = memchr(&data[start], c, chunk->size - start); 4.87 - if (found != NULL) { 4.88 - return index + (found - data); 4.89 - } 4.90 - else { 4.91 - index += chunk->size; 4.92 - chunk = chunk->next; 4.93 - start = 0; 4.94 - } 4.95 - } 4.96 - 4.97 - return -1; 4.98 -} 4.99 - 4.100 -/* Consume characters between self->pos and newPos, returning it as a 4.101 - new Python string. */ 4.102 -static PyObject * 4.103 -InputStream_consume(InputStream *self, int newPos) 4.104 -{ 4.105 - PyObject *result; 4.106 - int origSize = newPos - self->pos, size; 4.107 - char *data; 4.108 - struct InputStream_chunk *chunk = self->chunks, *next; 4.109 - int start = self->pos, index; 4.110 - 4.111 - assert(chunk != NULL); 4.112 - assert(self->pos <= chunk->size); 4.113 - 4.114 - if (!origSize) 4.115 - return PyString_FromString(""); 4.116 - 4.117 - result = PyString_FromStringAndSize(NULL, origSize); 4.118 - if (result == NULL) 4.119 - return NULL; 4.120 - 4.121 - data = PyString_AS_STRING(result); 4.122 - index = 0; 4.123 - 4.124 - /* Copy chunks into string */ 4.125 - while (self->pos < newPos) { 4.126 - char *cdata = InputStream_chunk_DATA(chunk); 4.127 - 4.128 - /* Constrain copy operations to chunk boundaries */ 4.129 - size = newPos - self->pos; 4.130 - if (size > (chunk->size - start)) 4.131 - size = chunk->size - start; 4.132 - 4.133 - memcpy(&data[index], &cdata[start], size); 4.134 - 4.135 - self->pos += size; 4.136 - index += size; 4.137 - 4.138 - /* Advance to next chunk */ 4.139 - chunk = chunk->next; 4.140 - start = 0; 4.141 - } 4.142 - 4.143 - assert(index == origSize); 4.144 - data[index] = '\0'; 4.145 - 4.146 - /* Free fully-consumed chunks */ 4.147 - chunk = self->chunks; 4.148 - while (self->pos > chunk->size) { 4.149 - next = chunk->next; 4.150 - self->pos -= chunk->size; 4.151 - self->size -= chunk->size; 4.152 - self->avail -= chunk->size; 4.153 - PyMem_Free(chunk); 4.154 - chunk = next; 4.155 - } 4.156 - self->chunks = chunk; 4.157 - 4.158 - assert(self->chunks != NULL); 4.159 - assert(self->pos >= 0); 4.160 - assert(self->size > 0); 4.161 - assert(self->avail > 0); 4.162 - 4.163 - return result; 4.164 -} 4.165 - 4.166 -static void 4.167 -InputStream_dealloc(InputStream *self) 4.168 -{ 4.169 - struct InputStream_chunk *chunk, *next; 4.170 - PyObject *tmp; 4.171 - 4.172 - chunk = self->chunks; 4.173 - while (chunk != NULL) { 4.174 - next = chunk->next; 4.175 - PyMem_Free(chunk); 4.176 - chunk = next; 4.177 - } 4.178 - self->chunks = NULL; 4.179 - 4.180 - tmp = (PyObject *)self->request; 4.181 - self->request = NULL; 4.182 - Py_XDECREF(tmp); 4.183 - 4.184 - self->ob_type->tp_free((PyObject *)self); 4.185 -} 4.186 - 4.187 -static PyObject * 4.188 -InputStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 4.189 -{ 4.190 - InputStream *self; 4.191 - 4.192 - self = (InputStream *)type->tp_alloc(type, 0); 4.193 - if (self != NULL) { 4.194 - self->request = NULL; 4.195 - self->pos = 0; 4.196 - self->size = 0; 4.197 - self->avail = 0; 4.198 - self->chunks = NULL; 4.199 - self->tail = NULL; 4.200 - } 4.201 - 4.202 - return (PyObject *)self; 4.203 -} 4.204 - 4.205 -/* InputStream constructor. Expects to be passed the parent Request and 4.206 - the received Content-Length. */ 4.207 -static int 4.208 -InputStream_init(InputStream *self, PyObject *args, PyObject *kwds) 4.209 -{ 4.210 - Request *request; 4.211 - int size; 4.212 - 4.213 - if (!PyArg_ParseTuple(args, "O!i", &Request_Type, &request, &size)) 4.214 - return -1; 4.215 - 4.216 - Py_INCREF(request); 4.217 - self->request = request; 4.218 - self->size = size; 4.219 - 4.220 - return 0; 4.221 -} 4.222 - 4.223 -/* read() implementation */ 4.224 -static PyObject * 4.225 -InputStream_read(InputStream *self, PyObject *args) 4.226 -{ 4.227 - int size = -1, newPos; 4.228 - 4.229 - if (!PyArg_ParseTuple(args, "|i:read", &size)) 4.230 - return NULL; 4.231 - 4.232 - if (self->pos == self->size) 4.233 - return PyString_FromString(""); 4.234 - 4.235 - for (;;) { 4.236 - if (size < 0 || (self->avail - self->pos) < size) { 4.237 - /* Not enough data available */ 4.238 - if (self->avail == self->size) { 4.239 - /* No more coming */ 4.240 - newPos = self->avail; 4.241 - break; 4.242 - } 4.243 - else { 4.244 - /* Ask for more data */ 4.245 - if (wsgiGetBody(self->request->context)) 4.246 - return NULL; 4.247 - continue; 4.248 - } 4.249 - } 4.250 - else { 4.251 - newPos = self->pos + size; 4.252 - break; 4.253 - } 4.254 - } 4.255 - 4.256 - return InputStream_consume(self, newPos); 4.257 -} 4.258 - 4.259 -/* readline() implementation. Supports "size" argument not required by 4.260 - WSGI spec (but now required by Python 2.5's cgi module) */ 4.261 -static PyObject * 4.262 -InputStream_readline(InputStream *self, PyObject *args) 4.263 -{ 4.264 - int size = -1, start, i, newPos; 4.265 - 4.266 - if (!PyArg_ParseTuple(args, "|i:readline", &size)) 4.267 - return NULL; 4.268 - 4.269 - if (self->pos == self->size) 4.270 - return PyString_FromString(""); 4.271 - 4.272 - start = self->pos; 4.273 - 4.274 - for (;;) { 4.275 - /* Find newline */ 4.276 - i = InputStream_findChar(self, start, '\n'); 4.277 - if (i < 0) { 4.278 - /* Not found? */ 4.279 - if (self->avail == self->size) { 4.280 - /* No more data coming */ 4.281 - newPos = self->avail; 4.282 - break; 4.283 - } 4.284 - else { 4.285 - if (size < 0 || (self->avail - self->pos) < size) { 4.286 - /* Wait for more to come */ 4.287 - start = self->avail; /* Search new chunk only */ 4.288 - if (wsgiGetBody(self->request->context)) 4.289 - return NULL; 4.290 - continue; 4.291 - } 4.292 - else { 4.293 - /* Already have at least size bytes available */ 4.294 - newPos = self->pos + size; 4.295 - break; 4.296 - } 4.297 - } 4.298 - } 4.299 - else { 4.300 - newPos = i + 1; 4.301 - 4.302 - /* Trim line, if necessary */ 4.303 - if (size >= 0 && (self->pos + size) < newPos) 4.304 - newPos = self->pos + size; 4.305 - break; 4.306 - } 4.307 - } 4.308 - 4.309 - return InputStream_consume(self, newPos); 4.310 -} 4.311 - 4.312 -/* readlines() implementation. Supports "hint" argument. */ 4.313 -static PyObject * 4.314 -InputStream_readlines(InputStream *self, PyObject *args) 4.315 -{ 4.316 - int hint = 0, total = 0; 4.317 - PyObject *lines = NULL, *args2 = NULL, *line; 4.318 - int len, ret; 4.319 - 4.320 - if (!PyArg_ParseTuple(args, "|i:readlines", &hint)) 4.321 - return NULL; 4.322 - 4.323 - if ((lines = PyList_New(0)) == NULL) 4.324 - return NULL; 4.325 - 4.326 - if ((args2 = PyTuple_New(0)) == NULL) 4.327 - goto bad; 4.328 - 4.329 - if ((line = InputStream_readline(self, args2)) == NULL) 4.330 - goto bad; 4.331 - 4.332 - while ((len = PyString_GET_SIZE(line)) > 0) { 4.333 - ret = PyList_Append(lines, line); 4.334 - Py_DECREF(line); 4.335 - if (ret) 4.336 - goto bad; 4.337 - total += len; 4.338 - if (hint > 0 && total >= hint) 4.339 - break; 4.340 - 4.341 - if ((line = InputStream_readline(self, args2)) == NULL) 4.342 - goto bad; 4.343 - } 4.344 - 4.345 - Py_DECREF(line); 4.346 - Py_DECREF(args2); 4.347 - 4.348 - return lines; 4.349 - 4.350 - bad: 4.351 - Py_XDECREF(args2); 4.352 - Py_XDECREF(lines); 4.353 - return NULL; 4.354 -} 4.355 - 4.356 -/* __iter__() implementation. Simply returns self. */ 4.357 -static PyObject * 4.358 -InputStream_iter(InputStream *self) 4.359 -{ 4.360 - Py_INCREF(self); 4.361 - return (PyObject *)self; 4.362 -} 4.363 - 4.364 -/* next() implementation for iteration protocol support */ 4.365 -static PyObject * 4.366 -InputStream_iternext(InputStream *self) 4.367 -{ 4.368 - PyObject *line, *args; 4.369 - 4.370 - if ((args = PyTuple_New(0)) == NULL) 4.371 - return NULL; 4.372 - 4.373 - line = InputStream_readline(self, args); 4.374 - Py_DECREF(args); 4.375 - if (line == NULL) 4.376 - return NULL; 4.377 - 4.378 - if (PyString_GET_SIZE(line) == 0) { 4.379 - Py_DECREF(line); 4.380 - PyErr_Clear(); 4.381 - return NULL; 4.382 - } 4.383 - 4.384 - return line; 4.385 -} 4.386 - 4.387 -static PyMethodDef InputStream_methods[] = { 4.388 - { "read", (PyCFunction)InputStream_read, METH_VARARGS, 4.389 - "Read from this input stream" }, 4.390 - { "readline", (PyCFunction)InputStream_readline, METH_VARARGS, 4.391 - "Read a line from this input stream" }, 4.392 - { "readlines", (PyCFunction)InputStream_readlines, METH_VARARGS, 4.393 - "Read lines from this input stream" }, 4.394 - { NULL } 4.395 -}; 4.396 - 4.397 -PyTypeObject InputStream_Type = { 4.398 - PyObject_HEAD_INIT(NULL) 4.399 - 0, /*ob_size*/ 4.400 - "_wsgisup.InputStream", /*tp_name*/ 4.401 - sizeof(InputStream), /*tp_basicsize*/ 4.402 - 0, /*tp_itemsize*/ 4.403 - (destructor)InputStream_dealloc, /*tp_dealloc*/ 4.404 - 0, /*tp_print*/ 4.405 - 0, /*tp_getattr*/ 4.406 - 0, /*tp_setattr*/ 4.407 - 0, /*tp_compare*/ 4.408 - 0, /*tp_repr*/ 4.409 - 0, /*tp_as_number*/ 4.410 - 0, /*tp_as_sequence*/ 4.411 - 0, /*tp_as_mapping*/ 4.412 - 0, /*tp_hash */ 4.413 - 0, /*tp_call*/ 4.414 - 0, /*tp_str*/ 4.415 - 0, /*tp_getattro*/ 4.416 - 0, /*tp_setattro*/ 4.417 - 0, /*tp_as_buffer*/ 4.418 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ 4.419 - "wsgi.input implementation", /* tp_doc */ 4.420 - 0, /* tp_traverse */ 4.421 - 0, /* tp_clear */ 4.422 - 0, /* tp_richcompare */ 4.423 - 0, /* tp_weaklistoffset */ 4.424 - (getiterfunc)InputStream_iter, /* tp_iter */ 4.425 - (iternextfunc)InputStream_iternext, /* tp_iternext */ 4.426 - InputStream_methods, /* tp_methods */ 4.427 - 0, /* tp_members */ 4.428 - 0, /* tp_getset */ 4.429 - 0, /* tp_base */ 4.430 - 0, /* tp_dict */ 4.431 - 0, /* tp_descr_get */ 4.432 - 0, /* tp_descr_set */ 4.433 - 0, /* tp_dictoffset */ 4.434 - (initproc)InputStream_init, /* tp_init */ 4.435 - 0, /* tp_alloc */ 4.436 - InputStream_new, /* tp_new */ 4.437 -};
5.1 --- a/version.h Fri Dec 22 19:42:02 2006 +0000 5.2 +++ b/version.h Sun Dec 24 17:25:00 2006 +0000 5.3 @@ -1,5 +1,5 @@ 5.4 #define VERSION_MAJOR 0 5.5 -#define VERSION_MINOR 5 5.6 +#define VERSION_MINOR 6 5.7 #define VERSION_PATCHLEVEL 0 5.8 -#define VERSION_STRING "0.5" 5.9 -#define VERSION_DATE "2006-Dec-22" 5.10 +#define VERSION_STRING "0.6" 5.11 +#define VERSION_DATE "2006-Dec-24"
6.1 --- a/wrapper.c Fri Dec 22 19:42:02 2006 +0000 6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 6.3 @@ -1,187 +0,0 @@ 6.4 -/*- 6.5 - * Copyright (c) 2006 Allan Saddi <allan@saddi.com> 6.6 - * All rights reserved. 6.7 - * 6.8 - * Redistribution and use in source and binary forms, with or without 6.9 - * modification, are permitted provided that the following conditions 6.10 - * are met: 6.11 - * 1. Redistributions of source code must retain the above copyright 6.12 - * notice, this list of conditions and the following disclaimer. 6.13 - * 2. Redistributions in binary form must reproduce the above copyright 6.14 - * notice, this list of conditions and the following disclaimer in the 6.15 - * documentation and/or other materials provided with the distribution. 6.16 - * 6.17 - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 6.18 - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6.19 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6.20 - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 6.21 - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 6.22 - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 6.23 - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 6.24 - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6.25 - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6.26 - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6.27 - * SUCH DAMAGE. 6.28 - * 6.29 - * $Id$ 6.30 - */ 6.31 - 6.32 -#include <Python.h> 6.33 - 6.34 -#include "wsgi-int.h" 6.35 - 6.36 -static void 6.37 -FileWrapper_dealloc(FileWrapper *self) 6.38 -{ 6.39 - PyObject *tmp; 6.40 - 6.41 - tmp = (PyObject *)self->filelike; 6.42 - self->filelike = NULL; 6.43 - Py_XDECREF(tmp); 6.44 - 6.45 - self->ob_type->tp_free((PyObject *)self); 6.46 -} 6.47 - 6.48 -static PyObject * 6.49 -FileWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 6.50 -{ 6.51 - FileWrapper *self; 6.52 - 6.53 - self = (FileWrapper *)type->tp_alloc(type, 0); 6.54 - if (self != NULL) { 6.55 - self->filelike = NULL; 6.56 - } 6.57 - 6.58 - return (PyObject *)self; 6.59 -} 6.60 - 6.61 -static int 6.62 -FileWrapper_init(FileWrapper *self, PyObject *args, PyObject *kwds) 6.63 -{ 6.64 - PyObject *filelike; 6.65 - int blocksize = 4096; 6.66 - 6.67 - if (!PyArg_ParseTuple(args, "O|i", &filelike, &blocksize)) 6.68 - return -1; 6.69 - 6.70 - Py_INCREF(filelike); 6.71 - self->filelike = filelike; 6.72 - self->blocksize = blocksize; 6.73 - 6.74 - return 0; 6.75 -} 6.76 - 6.77 -static PyObject * 6.78 -FileWrapper_iter(FileWrapper *self) 6.79 -{ 6.80 - Py_INCREF(self); 6.81 - return (PyObject *)self; 6.82 -} 6.83 - 6.84 -static PyObject * 6.85 -FileWrapper_iternext(FileWrapper *self) 6.86 -{ 6.87 - PyObject *pRead, *args, *data; 6.88 - int len; 6.89 - 6.90 - if ((pRead = PyObject_GetAttrString(self->filelike, "read")) == NULL) 6.91 - return NULL; 6.92 - 6.93 - if ((args = Py_BuildValue("(i)", self->blocksize)) == NULL) { 6.94 - Py_DECREF(pRead); 6.95 - return NULL; 6.96 - } 6.97 - 6.98 - data = PyObject_CallObject(pRead, args); 6.99 - Py_DECREF(args); 6.100 - Py_DECREF(pRead); 6.101 - if (data == NULL) 6.102 - return NULL; 6.103 - 6.104 - len = PyString_Size(data); 6.105 - if (PyErr_Occurred()) { 6.106 - Py_DECREF(data); 6.107 - return NULL; 6.108 - } 6.109 - 6.110 - if (len == 0) { 6.111 - Py_DECREF(data); 6.112 - PyErr_Clear(); 6.113 - return NULL; 6.114 - } 6.115 - 6.116 - return data; 6.117 -} 6.118 - 6.119 -static PyObject * 6.120 -FileWrapper_close(FileWrapper *self, PyObject *args) 6.121 -{ 6.122 - PyObject *pClose, *args2, *result; 6.123 - 6.124 - if (PyObject_HasAttrString(self->filelike, "close")) { 6.125 - if ((pClose = PyObject_GetAttrString(self->filelike, "close")) == NULL) 6.126 - return NULL; 6.127 - 6.128 - if ((args2 = PyTuple_New(0)) == NULL) { 6.129 - Py_DECREF(pClose); 6.130 - return NULL; 6.131 - } 6.132 - 6.133 - result = PyObject_CallObject(pClose, args2); 6.134 - Py_DECREF(args2); 6.135 - Py_DECREF(pClose); 6.136 - if (result == NULL) 6.137 - return NULL; 6.138 - } 6.139 - 6.140 - Py_INCREF(Py_None); 6.141 - return Py_None; 6.142 -} 6.143 - 6.144 -static PyMethodDef FileWrapper_methods[] = { 6.145 - { "close", (PyCFunction)FileWrapper_close, METH_VARARGS, 6.146 - "Calls the file-like object's close method" }, 6.147 - { NULL } 6.148 -}; 6.149 - 6.150 -PyTypeObject FileWrapper_Type = { 6.151 - PyObject_HEAD_INIT(NULL) 6.152 - 0, /*ob_size*/ 6.153 - "_wsgisup.FileWrapper", /*tp_name*/ 6.154 - sizeof(FileWrapper), /*tp_basicsize*/ 6.155 - 0, /*tp_itemsize*/ 6.156 - (destructor)FileWrapper_dealloc, /*tp_dealloc*/ 6.157 - 0, /*tp_print*/ 6.158 - 0, /*tp_getattr*/ 6.159 - 0, /*tp_setattr*/ 6.160 - 0, /*tp_compare*/ 6.161 - 0, /*tp_repr*/ 6.162 - 0, /*tp_as_number*/ 6.163 - 0, /*tp_as_sequence*/ 6.164 - 0, /*tp_as_mapping*/ 6.165 - 0, /*tp_hash */ 6.166 - 0, /*tp_call*/ 6.167 - 0, /*tp_str*/ 6.168 - 0, /*tp_getattro*/ 6.169 - 0, /*tp_setattro*/ 6.170 - 0, /*tp_as_buffer*/ 6.171 - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ 6.172 - "wsgi.file_wrapper implementation", /* tp_doc */ 6.173 - 0, /* tp_traverse */ 6.174 - 0, /* tp_clear */ 6.175 - 0, /* tp_richcompare */ 6.176 - 0, /* tp_weaklistoffset */ 6.177 - (getiterfunc)FileWrapper_iter, /* tp_iter */ 6.178 - (iternextfunc)FileWrapper_iternext, /* tp_iternext */ 6.179 - FileWrapper_methods, /* tp_methods */ 6.180 - 0, /* tp_members */ 6.181 - 0, /* tp_getset */ 6.182 - 0, /* tp_base */ 6.183 - 0, /* tp_dict */ 6.184 - 0, /* tp_descr_get */ 6.185 - 0, /* tp_descr_set */ 6.186 - 0, /* tp_dictoffset */ 6.187 - (initproc)FileWrapper_init, /* tp_init */ 6.188 - 0, /* tp_alloc */ 6.189 - FileWrapper_new, /* tp_new */ 6.190 -};
7.1 --- a/wsgi-int.h Fri Dec 22 19:42:02 2006 +0000 7.2 +++ b/wsgi-int.h Sun Dec 24 17:25:00 2006 +0000 7.3 @@ -45,11 +45,6 @@ 7.4 PyObject *headers; 7.5 PyObject *result; 7.6 int headers_sent; 7.7 - 7.8 - /* Convenience */ 7.9 - PyObject *pStderr; /* owned by module */ 7.10 - const char *scriptName; 7.11 - int scriptNameLen; 7.12 } Request; 7.13 7.14 struct InputStream_chunk { 7.15 @@ -104,4 +99,9 @@ 7.16 int wsgiPutEnv(Request *req, const char *key, const char *value); 7.17 const char *wsgiUnquote(const char *s); 7.18 7.19 +/* Externs available to glue */ 7.20 +extern PyObject *wsgiStderr; 7.21 +extern const char *wsgiScriptName; 7.22 +extern int wsgiScriptNameLen; 7.23 + 7.24 #endif /* APS_WSGI_INT_H */
8.1 --- a/wsgi.c Fri Dec 22 19:42:02 2006 +0000 8.2 +++ b/wsgi.c Sun Dec 24 17:25:00 2006 +0000 8.3 @@ -33,10 +33,10 @@ 8.4 8.5 #include "wsgi-int.h" 8.6 8.7 -static const char *scriptName = ""; 8.8 -static int scriptNameLen = 0; 8.9 +PyObject *wsgiStderr; 8.10 +const char *wsgiScriptName = ""; 8.11 +int wsgiScriptNameLen = 0; 8.12 8.13 -static PyObject *pStderr; 8.14 static PyObject *pApp; 8.15 static PyThreadState *_main; 8.16 8.17 @@ -167,11 +167,6 @@ 8.18 self->headers = NULL; 8.19 self->result = NULL; 8.20 self->headers_sent = 0; 8.21 - 8.22 - /* So we don't have to extern these... */ 8.23 - self->pStderr = pStderr; 8.24 - self->scriptName = scriptName; 8.25 - self->scriptNameLen = scriptNameLen; 8.26 } 8.27 8.28 return (PyObject *)self; 8.29 @@ -599,19 +594,19 @@ 8.30 { 8.31 PyEval_RestoreThread(_main); 8.32 Py_DECREF(pApp); 8.33 - Py_DECREF(pStderr); 8.34 + Py_DECREF(wsgiStderr); 8.35 Py_Finalize(); 8.36 } 8.37 8.38 int 8.39 -wsgiInit(const char *moduleName, const char *appName, const char *_scriptName, 8.40 +wsgiInit(const char *moduleName, const char *appName, const char *scriptName, 8.41 const char *progName) 8.42 { 8.43 PyObject *pName, *pModule; 8.44 char *argv[1]; 8.45 8.46 - scriptName = _scriptName; 8.47 - scriptNameLen = strlen(_scriptName); 8.48 + wsgiScriptName = scriptName; 8.49 + wsgiScriptNameLen = strlen(scriptName); 8.50 8.51 PyEval_InitThreads(); 8.52 Py_Initialize(); 8.53 @@ -629,9 +624,9 @@ 8.54 if (pModule == NULL) 8.55 goto err; 8.56 8.57 - pStderr = PyObject_GetAttrString(pModule, "stderr"); 8.58 + wsgiStderr = PyObject_GetAttrString(pModule, "stderr"); 8.59 Py_DECREF(pModule); 8.60 - if (pStderr == NULL) 8.61 + if (wsgiStderr == NULL) 8.62 goto err; 8.63 8.64 pName = PyString_FromString(moduleName);
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/wsgiinput.c Sun Dec 24 17:25:00 2006 +0000 9.3 @@ -0,0 +1,434 @@ 9.4 +/*- 9.5 + * Copyright (c) 2006 Allan Saddi <allan@saddi.com> 9.6 + * All rights reserved. 9.7 + * 9.8 + * Redistribution and use in source and binary forms, with or without 9.9 + * modification, are permitted provided that the following conditions 9.10 + * are met: 9.11 + * 1. Redistributions of source code must retain the above copyright 9.12 + * notice, this list of conditions and the following disclaimer. 9.13 + * 2. Redistributions in binary form must reproduce the above copyright 9.14 + * notice, this list of conditions and the following disclaimer in the 9.15 + * documentation and/or other materials provided with the distribution. 9.16 + * 9.17 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 9.18 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9.19 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 9.20 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 9.21 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 9.22 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 9.23 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 9.24 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 9.25 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 9.26 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 9.27 + * SUCH DAMAGE. 9.28 + * 9.29 + * $Id$ 9.30 + */ 9.31 + 9.32 +#include <Python.h> 9.33 + 9.34 +#include <assert.h> 9.35 + 9.36 +#include "wsgi-int.h" 9.37 + 9.38 +/* Add data as a new chunk at the tail of our chunk list */ 9.39 +int 9.40 +wsgiBodyHandler(void *ctxt, uint8_t *data, size_t len) 9.41 +{ 9.42 + InputStream *self = (InputStream *)((Request *)wsgiGetRequestData(ctxt))->input; 9.43 + struct InputStream_chunk *chunk; 9.44 + 9.45 + if (!len) return 0; 9.46 + 9.47 + if ((chunk = PyMem_Malloc(sizeof(*chunk) + len)) == NULL) 9.48 + return -1; 9.49 + 9.50 + chunk->next = NULL; 9.51 + chunk->size = len; 9.52 + memcpy(InputStream_chunk_DATA(chunk), data, len); 9.53 + 9.54 + if (self->chunks) { 9.55 + self->tail->next = chunk; 9.56 + self->tail = chunk; 9.57 + } 9.58 + else { 9.59 + self->chunks = self->tail = chunk; 9.60 + } 9.61 + 9.62 + self->avail += len; 9.63 + 9.64 + return 0; 9.65 +} 9.66 + 9.67 +/* Find occurrence of a character within our buffers */ 9.68 +static int 9.69 +InputStream_findChar(InputStream *self, int start, int c) 9.70 +{ 9.71 + struct InputStream_chunk *chunk = self->chunks; 9.72 + int index = 0; 9.73 + 9.74 + /* Find starting chunk */ 9.75 + while (chunk != NULL) { 9.76 + if (chunk->size > start) 9.77 + break; 9.78 + 9.79 + index += chunk->size; 9.80 + start -= chunk->size; 9.81 + chunk = chunk->next; 9.82 + } 9.83 + 9.84 + while (chunk != NULL) { 9.85 + char *data = InputStream_chunk_DATA(chunk); 9.86 + char *found = memchr(&data[start], c, chunk->size - start); 9.87 + if (found != NULL) { 9.88 + return index + (found - data); 9.89 + } 9.90 + else { 9.91 + index += chunk->size; 9.92 + chunk = chunk->next; 9.93 + start = 0; 9.94 + } 9.95 + } 9.96 + 9.97 + return -1; 9.98 +} 9.99 + 9.100 +/* Consume characters between self->pos and newPos, returning it as a 9.101 + new Python string. */ 9.102 +static PyObject * 9.103 +InputStream_consume(InputStream *self, int newPos) 9.104 +{ 9.105 + PyObject *result; 9.106 + int origSize = newPos - self->pos, size; 9.107 + char *data; 9.108 + struct InputStream_chunk *chunk = self->chunks, *next; 9.109 + int start = self->pos, index; 9.110 + 9.111 + assert(chunk != NULL); 9.112 + assert(self->pos <= chunk->size); 9.113 + 9.114 + if (!origSize) 9.115 + return PyString_FromString(""); 9.116 + 9.117 + result = PyString_FromStringAndSize(NULL, origSize); 9.118 + if (result == NULL) 9.119 + return NULL; 9.120 + 9.121 + data = PyString_AS_STRING(result); 9.122 + index = 0; 9.123 + 9.124 + /* Copy chunks into string */ 9.125 + while (self->pos < newPos) { 9.126 + char *cdata = InputStream_chunk_DATA(chunk); 9.127 + 9.128 + /* Constrain copy operations to chunk boundaries */ 9.129 + size = newPos - self->pos; 9.130 + if (size > (chunk->size - start)) 9.131 + size = chunk->size - start; 9.132 + 9.133 + memcpy(&data[index], &cdata[start], size); 9.134 + 9.135 + self->pos += size; 9.136 + index += size; 9.137 + 9.138 + /* Advance to next chunk */ 9.139 + chunk = chunk->next; 9.140 + start = 0; 9.141 + } 9.142 + 9.143 + assert(index == origSize); 9.144 + data[index] = '\0'; 9.145 + 9.146 + /* Free fully-consumed chunks */ 9.147 + chunk = self->chunks; 9.148 + while (self->pos > chunk->size) { 9.149 + next = chunk->next; 9.150 + self->pos -= chunk->size; 9.151 + self->size -= chunk->size; 9.152 + self->avail -= chunk->size; 9.153 + PyMem_Free(chunk); 9.154 + chunk = next; 9.155 + } 9.156 + self->chunks = chunk; 9.157 + 9.158 + assert(self->chunks != NULL); 9.159 + assert(self->pos >= 0); 9.160 + assert(self->size > 0); 9.161 + assert(self->avail > 0); 9.162 + 9.163 + return result; 9.164 +} 9.165 + 9.166 +static void 9.167 +InputStream_dealloc(InputStream *self) 9.168 +{ 9.169 + struct InputStream_chunk *chunk, *next; 9.170 + PyObject *tmp; 9.171 + 9.172 + chunk = self->chunks; 9.173 + while (chunk != NULL) { 9.174 + next = chunk->next; 9.175 + PyMem_Free(chunk); 9.176 + chunk = next; 9.177 + } 9.178 + self->chunks = NULL; 9.179 + 9.180 + tmp = (PyObject *)self->request; 9.181 + self->request = NULL; 9.182 + Py_XDECREF(tmp); 9.183 + 9.184 + self->ob_type->tp_free((PyObject *)self); 9.185 +} 9.186 + 9.187 +static PyObject * 9.188 +InputStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 9.189 +{ 9.190 + InputStream *self; 9.191 + 9.192 + self = (InputStream *)type->tp_alloc(type, 0); 9.193 + if (self != NULL) { 9.194 + self->request = NULL; 9.195 + self->pos = 0; 9.196 + self->size = 0; 9.197 + self->avail = 0; 9.198 + self->chunks = NULL; 9.199 + self->tail = NULL; 9.200 + } 9.201 + 9.202 + return (PyObject *)self; 9.203 +} 9.204 + 9.205 +/* InputStream constructor. Expects to be passed the parent Request and 9.206 + the received Content-Length. */ 9.207 +static int 9.208 +InputStream_init(InputStream *self, PyObject *args, PyObject *kwds) 9.209 +{ 9.210 + Request *request; 9.211 + int size; 9.212 + 9.213 + if (!PyArg_ParseTuple(args, "O!i", &Request_Type, &request, &size)) 9.214 + return -1; 9.215 + 9.216 + Py_INCREF(request); 9.217 + self->request = request; 9.218 + self->size = size; 9.219 + 9.220 + return 0; 9.221 +} 9.222 + 9.223 +/* read() implementation */ 9.224 +static PyObject * 9.225 +InputStream_read(InputStream *self, PyObject *args) 9.226 +{ 9.227 + int size = -1, newPos; 9.228 + 9.229 + if (!PyArg_ParseTuple(args, "|i:read", &size)) 9.230 + return NULL; 9.231 + 9.232 + if (self->pos == self->size) 9.233 + return PyString_FromString(""); 9.234 + 9.235 + for (;;) { 9.236 + if (size < 0 || (self->avail - self->pos) < size) { 9.237 + /* Not enough data available */ 9.238 + if (self->avail == self->size) { 9.239 + /* No more coming */ 9.240 + newPos = self->avail; 9.241 + break; 9.242 + } 9.243 + else { 9.244 + /* Ask for more data */ 9.245 + if (wsgiGetBody(self->request->context)) 9.246 + return NULL; 9.247 + continue; 9.248 + } 9.249 + } 9.250 + else { 9.251 + newPos = self->pos + size; 9.252 + break; 9.253 + } 9.254 + } 9.255 + 9.256 + return InputStream_consume(self, newPos); 9.257 +} 9.258 + 9.259 +/* readline() implementation. Supports "size" argument not required by 9.260 + WSGI spec (but now required by Python 2.5's cgi module) */ 9.261 +static PyObject * 9.262 +InputStream_readline(InputStream *self, PyObject *args) 9.263 +{ 9.264 + int size = -1, start, i, newPos; 9.265 + 9.266 + if (!PyArg_ParseTuple(args, "|i:readline", &size)) 9.267 + return NULL; 9.268 + 9.269 + if (self->pos == self->size) 9.270 + return PyString_FromString(""); 9.271 + 9.272 + start = self->pos; 9.273 + 9.274 + for (;;) { 9.275 + /* Find newline */ 9.276 + i = InputStream_findChar(self, start, '\n'); 9.277 + if (i < 0) { 9.278 + /* Not found? */ 9.279 + if (self->avail == self->size) { 9.280 + /* No more data coming */ 9.281 + newPos = self->avail; 9.282 + break; 9.283 + } 9.284 + else { 9.285 + if (size < 0 || (self->avail - self->pos) < size) { 9.286 + /* Wait for more to come */ 9.287 + start = self->avail; /* Search new chunk only */ 9.288 + if (wsgiGetBody(self->request->context)) 9.289 + return NULL; 9.290 + continue; 9.291 + } 9.292 + else { 9.293 + /* Already have at least size bytes available */ 9.294 + newPos = self->pos + size; 9.295 + break; 9.296 + } 9.297 + } 9.298 + } 9.299 + else { 9.300 + newPos = i + 1; 9.301 + 9.302 + /* Trim line, if necessary */ 9.303 + if (size >= 0 && (self->pos + size) < newPos) 9.304 + newPos = self->pos + size; 9.305 + break; 9.306 + } 9.307 + } 9.308 + 9.309 + return InputStream_consume(self, newPos); 9.310 +} 9.311 + 9.312 +/* readlines() implementation. Supports "hint" argument. */ 9.313 +static PyObject * 9.314 +InputStream_readlines(InputStream *self, PyObject *args) 9.315 +{ 9.316 + int hint = 0, total = 0; 9.317 + PyObject *lines = NULL, *args2 = NULL, *line; 9.318 + int len, ret; 9.319 + 9.320 + if (!PyArg_ParseTuple(args, "|i:readlines", &hint)) 9.321 + return NULL; 9.322 + 9.323 + if ((lines = PyList_New(0)) == NULL) 9.324 + return NULL; 9.325 + 9.326 + if ((args2 = PyTuple_New(0)) == NULL) 9.327 + goto bad; 9.328 + 9.329 + if ((line = InputStream_readline(self, args2)) == NULL) 9.330 + goto bad; 9.331 + 9.332 + while ((len = PyString_GET_SIZE(line)) > 0) { 9.333 + ret = PyList_Append(lines, line); 9.334 + Py_DECREF(line); 9.335 + if (ret) 9.336 + goto bad; 9.337 + total += len; 9.338 + if (hint > 0 && total >= hint) 9.339 + break; 9.340 + 9.341 + if ((line = InputStream_readline(self, args2)) == NULL) 9.342 + goto bad; 9.343 + } 9.344 + 9.345 + Py_DECREF(line); 9.346 + Py_DECREF(args2); 9.347 + 9.348 + return lines; 9.349 + 9.350 + bad: 9.351 + Py_XDECREF(args2); 9.352 + Py_XDECREF(lines); 9.353 + return NULL; 9.354 +} 9.355 + 9.356 +/* __iter__() implementation. Simply returns self. */ 9.357 +static PyObject * 9.358 +InputStream_iter(InputStream *self) 9.359 +{ 9.360 + Py_INCREF(self); 9.361 + return (PyObject *)self; 9.362 +} 9.363 + 9.364 +/* next() implementation for iteration protocol support */ 9.365 +static PyObject * 9.366 +InputStream_iternext(InputStream *self) 9.367 +{ 9.368 + PyObject *line, *args; 9.369 + 9.370 + if ((args = PyTuple_New(0)) == NULL) 9.371 + return NULL; 9.372 + 9.373 + line = InputStream_readline(self, args); 9.374 + Py_DECREF(args); 9.375 + if (line == NULL) 9.376 + return NULL; 9.377 + 9.378 + if (PyString_GET_SIZE(line) == 0) { 9.379 + Py_DECREF(line); 9.380 + PyErr_Clear(); 9.381 + return NULL; 9.382 + } 9.383 + 9.384 + return line; 9.385 +} 9.386 + 9.387 +static PyMethodDef InputStream_methods[] = { 9.388 + { "read", (PyCFunction)InputStream_read, METH_VARARGS, 9.389 + "Read from this input stream" }, 9.390 + { "readline", (PyCFunction)InputStream_readline, METH_VARARGS, 9.391 + "Read a line from this input stream" }, 9.392 + { "readlines", (PyCFunction)InputStream_readlines, METH_VARARGS, 9.393 + "Read lines from this input stream" }, 9.394 + { NULL } 9.395 +}; 9.396 + 9.397 +PyTypeObject InputStream_Type = { 9.398 + PyObject_HEAD_INIT(NULL) 9.399 + 0, /*ob_size*/ 9.400 + "_wsgisup.InputStream", /*tp_name*/ 9.401 + sizeof(InputStream), /*tp_basicsize*/ 9.402 + 0, /*tp_itemsize*/ 9.403 + (destructor)InputStream_dealloc, /*tp_dealloc*/ 9.404 + 0, /*tp_print*/ 9.405 + 0, /*tp_getattr*/ 9.406 + 0, /*tp_setattr*/ 9.407 + 0, /*tp_compare*/ 9.408 + 0, /*tp_repr*/ 9.409 + 0, /*tp_as_number*/ 9.410 + 0, /*tp_as_sequence*/ 9.411 + 0, /*tp_as_mapping*/ 9.412 + 0, /*tp_hash */ 9.413 + 0, /*tp_call*/ 9.414 + 0, /*tp_str*/ 9.415 + 0, /*tp_getattro*/ 9.416 + 0, /*tp_setattro*/ 9.417 + 0, /*tp_as_buffer*/ 9.418 + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ 9.419 + "wsgi.input implementation", /* tp_doc */ 9.420 + 0, /* tp_traverse */ 9.421 + 0, /* tp_clear */ 9.422 + 0, /* tp_richcompare */ 9.423 + 0, /* tp_weaklistoffset */ 9.424 + (getiterfunc)InputStream_iter, /* tp_iter */ 9.425 + (iternextfunc)InputStream_iternext, /* tp_iternext */ 9.426 + InputStream_methods, /* tp_methods */ 9.427 + 0, /* tp_members */ 9.428 + 0, /* tp_getset */ 9.429 + 0, /* tp_base */ 9.430 + 0, /* tp_dict */ 9.431 + 0, /* tp_descr_get */ 9.432 + 0, /* tp_descr_set */ 9.433 + 0, /* tp_dictoffset */ 9.434 + (initproc)InputStream_init, /* tp_init */ 9.435 + 0, /* tp_alloc */ 9.436 + InputStream_new, /* tp_new */ 9.437 +};
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/wsgiwrapper.c Sun Dec 24 17:25:00 2006 +0000 10.3 @@ -0,0 +1,187 @@ 10.4 +/*- 10.5 + * Copyright (c) 2006 Allan Saddi <allan@saddi.com> 10.6 + * All rights reserved. 10.7 + * 10.8 + * Redistribution and use in source and binary forms, with or without 10.9 + * modification, are permitted provided that the following conditions 10.10 + * are met: 10.11 + * 1. Redistributions of source code must retain the above copyright 10.12 + * notice, this list of conditions and the following disclaimer. 10.13 + * 2. Redistributions in binary form must reproduce the above copyright 10.14 + * notice, this list of conditions and the following disclaimer in the 10.15 + * documentation and/or other materials provided with the distribution. 10.16 + * 10.17 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 10.18 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10.19 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 10.20 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 10.21 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 10.22 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 10.23 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 10.24 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 10.25 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 10.26 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 10.27 + * SUCH DAMAGE. 10.28 + * 10.29 + * $Id$ 10.30 + */ 10.31 + 10.32 +#include <Python.h> 10.33 + 10.34 +#include "wsgi-int.h" 10.35 + 10.36 +static void 10.37 +FileWrapper_dealloc(FileWrapper *self) 10.38 +{ 10.39 + PyObject *tmp; 10.40 + 10.41 + tmp = (PyObject *)self->filelike; 10.42 + self->filelike = NULL; 10.43 + Py_XDECREF(tmp); 10.44 + 10.45 + self->ob_type->tp_free((PyObject *)self); 10.46 +} 10.47 + 10.48 +static PyObject * 10.49 +FileWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 10.50 +{ 10.51 + FileWrapper *self; 10.52 + 10.53 + self = (FileWrapper *)type->tp_alloc(type, 0); 10.54 + if (self != NULL) { 10.55 + self->filelike = NULL; 10.56 + } 10.57 + 10.58 + return (PyObject *)self; 10.59 +} 10.60 + 10.61 +static int 10.62 +FileWrapper_init(FileWrapper *self, PyObject *args, PyObject *kwds) 10.63 +{ 10.64 + PyObject *filelike; 10.65 + int blocksize = 4096; 10.66 + 10.67 + if (!PyArg_ParseTuple(args, "O|i", &filelike, &blocksize)) 10.68 + return -1; 10.69 + 10.70 + Py_INCREF(filelike); 10.71 + self->filelike = filelike; 10.72 + self->blocksize = blocksize; 10.73 + 10.74 + return 0; 10.75 +} 10.76 + 10.77 +static PyObject * 10.78 +FileWrapper_iter(FileWrapper *self) 10.79 +{ 10.80 + Py_INCREF(self); 10.81 + return (PyObject *)self; 10.82 +} 10.83 + 10.84 +static PyObject * 10.85 +FileWrapper_iternext(FileWrapper *self) 10.86 +{ 10.87 + PyObject *pRead, *args, *data; 10.88 + int len; 10.89 + 10.90 + if ((pRead = PyObject_GetAttrString(self->filelike, "read")) == NULL) 10.91 + return NULL; 10.92 + 10.93 + if ((args = Py_BuildValue("(i)", self->blocksize)) == NULL) { 10.94 + Py_DECREF(pRead); 10.95 + return NULL; 10.96 + } 10.97 + 10.98 + data = PyObject_CallObject(pRead, args); 10.99 + Py_DECREF(args); 10.100 + Py_DECREF(pRead); 10.101 + if (data == NULL) 10.102 + return NULL; 10.103 + 10.104 + len = PyString_Size(data); 10.105 + if (PyErr_Occurred()) { 10.106 + Py_DECREF(data); 10.107 + return NULL; 10.108 + } 10.109 + 10.110 + if (len == 0) { 10.111 + Py_DECREF(data); 10.112 + PyErr_Clear(); 10.113 + return NULL; 10.114 + } 10.115 + 10.116 + return data; 10.117 +} 10.118 + 10.119 +static PyObject * 10.120 +FileWrapper_close(FileWrapper *self, PyObject *args) 10.121 +{ 10.122 + PyObject *pClose, *args2, *result; 10.123 + 10.124 + if (PyObject_HasAttrString(self->filelike, "close")) { 10.125 + if ((pClose = PyObject_GetAttrString(self->filelike, "close")) == NULL) 10.126 + return NULL; 10.127 + 10.128 + if ((args2 = PyTuple_New(0)) == NULL) { 10.129 + Py_DECREF(pClose); 10.130 + return NULL; 10.131 + } 10.132 + 10.133 + result = PyObject_CallObject(pClose, args2); 10.134 + Py_DECREF(args2); 10.135 + Py_DECREF(pClose); 10.136 + if (result == NULL) 10.137 + return NULL; 10.138 + } 10.139 + 10.140 + Py_INCREF(Py_None); 10.141 + return Py_None; 10.142 +} 10.143 + 10.144 +static PyMethodDef FileWrapper_methods[] = { 10.145 + { "close", (PyCFunction)FileWrapper_close, METH_VARARGS, 10.146 + "Calls the file-like object's close method" }, 10.147 + { NULL } 10.148 +}; 10.149 + 10.150 +PyTypeObject FileWrapper_Type = { 10.151 + PyObject_HEAD_INIT(NULL) 10.152 + 0, /*ob_size*/ 10.153 + "_wsgisup.FileWrapper", /*tp_name*/ 10.154 + sizeof(FileWrapper), /*tp_basicsize*/ 10.155 + 0, /*tp_itemsize*/ 10.156 + (destructor)FileWrapper_dealloc, /*tp_dealloc*/ 10.157 + 0, /*tp_print*/ 10.158 + 0, /*tp_getattr*/ 10.159 + 0, /*tp_setattr*/ 10.160 + 0, /*tp_compare*/ 10.161 + 0, /*tp_repr*/ 10.162 + 0, /*tp_as_number*/ 10.163 + 0, /*tp_as_sequence*/ 10.164 + 0, /*tp_as_mapping*/ 10.165 + 0, /*tp_hash */ 10.166 + 0, /*tp_call*/ 10.167 + 0, /*tp_str*/ 10.168 + 0, /*tp_getattro*/ 10.169 + 0, /*tp_setattro*/ 10.170 + 0, /*tp_as_buffer*/ 10.171 + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ 10.172 + "wsgi.file_wrapper implementation", /* tp_doc */ 10.173 + 0, /* tp_traverse */ 10.174 + 0, /* tp_clear */ 10.175 + 0, /* tp_richcompare */ 10.176 + 0, /* tp_weaklistoffset */ 10.177 + (getiterfunc)FileWrapper_iter, /* tp_iter */ 10.178 + (iternextfunc)FileWrapper_iternext, /* tp_iternext */ 10.179 + FileWrapper_methods, /* tp_methods */ 10.180 + 0, /* tp_members */ 10.181 + 0, /* tp_getset */ 10.182 + 0, /* tp_base */ 10.183 + 0, /* tp_dict */ 10.184 + 0, /* tp_descr_get */ 10.185 + 0, /* tp_descr_set */ 10.186 + 0, /* tp_dictoffset */ 10.187 + (initproc)FileWrapper_init, /* tp_init */ 10.188 + 0, /* tp_alloc */ 10.189 + FileWrapper_new, /* tp_new */ 10.190 +};
