blob: f6db8511081af9df16b251d4aaeccbbe91e20279 [file] [log] [blame]
Benjamin Peterson190d56e2008-06-11 02:40:25 +00001/*
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002 * Definition of a `Connection` type.
Benjamin Peterson190d56e2008-06-11 02:40:25 +00003 * Used by `socket_connection.c` and `pipe_connection.c`.
4 *
5 * connection.h
6 *
7 * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
8 */
9
10#ifndef CONNECTION_H
11#define CONNECTION_H
12
13/*
14 * Read/write flags
15 */
16
17#define READABLE 1
18#define WRITABLE 2
19
20#define CHECK_READABLE(self) \
21 if (!(self->flags & READABLE)) { \
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000022 PyErr_SetString(PyExc_IOError, "connection is write-only"); \
23 return NULL; \
Benjamin Peterson190d56e2008-06-11 02:40:25 +000024 }
25
26#define CHECK_WRITABLE(self) \
27 if (!(self->flags & WRITABLE)) { \
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000028 PyErr_SetString(PyExc_IOError, "connection is read-only"); \
29 return NULL; \
Benjamin Peterson190d56e2008-06-11 02:40:25 +000030 }
31
32/*
33 * Allocation and deallocation
34 */
35
36static PyObject *
37connection_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
38{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000039 ConnectionObject *self;
40 HANDLE handle;
41 BOOL readable = TRUE, writable = TRUE;
Benjamin Peterson190d56e2008-06-11 02:40:25 +000042
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000043 static char *kwlist[] = {"handle", "readable", "writable", NULL};
Benjamin Peterson190d56e2008-06-11 02:40:25 +000044
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000045 if (!PyArg_ParseTupleAndKeywords(args, kwds, F_HANDLE "|ii", kwlist,
46 &handle, &readable, &writable))
47 return NULL;
Benjamin Peterson190d56e2008-06-11 02:40:25 +000048
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000049 if (handle == INVALID_HANDLE_VALUE || (Py_ssize_t)handle < 0) {
50 PyErr_Format(PyExc_IOError, "invalid handle %zd",
51 (Py_ssize_t)handle);
52 return NULL;
53 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +000054
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000055 if (!readable && !writable) {
56 PyErr_SetString(PyExc_ValueError,
57 "either readable or writable must be true");
58 return NULL;
59 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +000060
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000061 self = PyObject_New(ConnectionObject, type);
62 if (self == NULL)
63 return NULL;
Benjamin Peterson190d56e2008-06-11 02:40:25 +000064
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000065 self->weakreflist = NULL;
66 self->handle = handle;
67 self->flags = 0;
Benjamin Peterson190d56e2008-06-11 02:40:25 +000068
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000069 if (readable)
70 self->flags |= READABLE;
71 if (writable)
72 self->flags |= WRITABLE;
73 assert(self->flags >= 1 && self->flags <= 3);
Benjamin Peterson190d56e2008-06-11 02:40:25 +000074
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000075 return (PyObject*)self;
Benjamin Peterson190d56e2008-06-11 02:40:25 +000076}
77
78static void
79connection_dealloc(ConnectionObject* self)
80{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000081 if (self->weakreflist != NULL)
82 PyObject_ClearWeakRefs((PyObject*)self);
Benjamin Peterson190d56e2008-06-11 02:40:25 +000083
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000084 if (self->handle != INVALID_HANDLE_VALUE) {
85 Py_BEGIN_ALLOW_THREADS
86 CLOSE(self->handle);
87 Py_END_ALLOW_THREADS
88 }
89 PyObject_Del(self);
Benjamin Peterson190d56e2008-06-11 02:40:25 +000090}
91
92/*
93 * Functions for transferring buffers
94 */
95
96static PyObject *
97connection_sendbytes(ConnectionObject *self, PyObject *args)
98{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000099 char *buffer;
100 Py_ssize_t length, offset=0, size=PY_SSIZE_T_MIN;
101 int res;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000102
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000103 if (!PyArg_ParseTuple(args, F_RBUFFER "#|" F_PY_SSIZE_T F_PY_SSIZE_T,
104 &buffer, &length, &offset, &size))
105 return NULL;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000106
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000107 CHECK_WRITABLE(self);
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000108
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000109 if (offset < 0) {
110 PyErr_SetString(PyExc_ValueError, "offset is negative");
111 return NULL;
112 }
113 if (length < offset) {
114 PyErr_SetString(PyExc_ValueError, "buffer length < offset");
115 return NULL;
116 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000117
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000118 if (size == PY_SSIZE_T_MIN) {
119 size = length - offset;
120 } else {
121 if (size < 0) {
122 PyErr_SetString(PyExc_ValueError, "size is negative");
123 return NULL;
124 }
125 if (offset + size > length) {
126 PyErr_SetString(PyExc_ValueError,
127 "buffer length < offset + size");
128 return NULL;
129 }
130 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000131
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000132 res = conn_send_string(self, buffer + offset, size);
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000133
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000134 if (res < 0)
135 return mp_SetError(PyExc_IOError, res);
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000136
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000137 Py_RETURN_NONE;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000138}
139
140static PyObject *
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000141connection_recvbytes(ConnectionObject *self, PyObject *args)
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000142{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000143 char *freeme = NULL;
144 Py_ssize_t res, maxlength = PY_SSIZE_T_MAX;
145 PyObject *result = NULL;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000146
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000147 if (!PyArg_ParseTuple(args, "|" F_PY_SSIZE_T, &maxlength))
148 return NULL;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000149
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000150 CHECK_READABLE(self);
151
152 if (maxlength < 0) {
153 PyErr_SetString(PyExc_ValueError, "maxlength < 0");
154 return NULL;
155 }
156
157 res = conn_recv_string(self, self->buffer, CONNECTION_BUFFER_SIZE,
158 &freeme, maxlength);
159
160 if (res < 0) {
161 if (res == MP_BAD_MESSAGE_LENGTH) {
162 if ((self->flags & WRITABLE) == 0) {
163 Py_BEGIN_ALLOW_THREADS
164 CLOSE(self->handle);
165 Py_END_ALLOW_THREADS
166 self->handle = INVALID_HANDLE_VALUE;
167 } else {
168 self->flags = WRITABLE;
169 }
170 }
171 mp_SetError(PyExc_IOError, res);
172 } else {
173 if (freeme == NULL) {
174 result = PyString_FromStringAndSize(self->buffer, res);
175 } else {
176 result = PyString_FromStringAndSize(freeme, res);
177 PyMem_Free(freeme);
178 }
179 }
180
181 return result;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000182}
183
184static PyObject *
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000185connection_recvbytes_into(ConnectionObject *self, PyObject *args)
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000186{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000187 char *freeme = NULL, *buffer = NULL;
188 Py_ssize_t res, length, offset = 0;
189 PyObject *result = NULL;
190 Py_buffer pbuf;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000191
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000192 CHECK_READABLE(self);
Martin v. Löwisf91d46a2008-08-12 14:49:50 +0000193
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000194 if (!PyArg_ParseTuple(args, "w*|" F_PY_SSIZE_T,
195 &pbuf, &offset))
196 return NULL;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000197
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000198 buffer = pbuf.buf;
199 length = pbuf.len;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000200
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000201 if (offset < 0) {
202 PyErr_SetString(PyExc_ValueError, "negative offset");
203 goto _error;
204 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000205
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000206 if (offset > length) {
207 PyErr_SetString(PyExc_ValueError, "offset too large");
208 goto _error;
209 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000210
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000211 res = conn_recv_string(self, buffer+offset, length-offset,
212 &freeme, PY_SSIZE_T_MAX);
213
214 if (res < 0) {
215 if (res == MP_BAD_MESSAGE_LENGTH) {
216 if ((self->flags & WRITABLE) == 0) {
217 Py_BEGIN_ALLOW_THREADS
218 CLOSE(self->handle);
219 Py_END_ALLOW_THREADS
220 self->handle = INVALID_HANDLE_VALUE;
221 } else {
222 self->flags = WRITABLE;
223 }
224 }
225 mp_SetError(PyExc_IOError, res);
226 } else {
227 if (freeme == NULL) {
228 result = PyInt_FromSsize_t(res);
229 } else {
230 result = PyObject_CallFunction(BufferTooShort,
231 F_RBUFFER "#",
232 freeme, res);
233 PyMem_Free(freeme);
234 if (result) {
235 PyErr_SetObject(BufferTooShort, result);
236 Py_DECREF(result);
237 }
238 goto _error;
239 }
240 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000241
Martin v. Löwisf91d46a2008-08-12 14:49:50 +0000242_cleanup:
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000243 PyBuffer_Release(&pbuf);
244 return result;
Martin v. Löwisf91d46a2008-08-12 14:49:50 +0000245
246_error:
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000247 result = NULL;
248 goto _cleanup;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000249}
250
251/*
252 * Functions for transferring objects
253 */
254
255static PyObject *
256connection_send_obj(ConnectionObject *self, PyObject *obj)
257{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000258 char *buffer;
259 int res;
260 Py_ssize_t length;
261 PyObject *pickled_string = NULL;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000262
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000263 CHECK_WRITABLE(self);
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000264
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000265 pickled_string = PyObject_CallFunctionObjArgs(pickle_dumps, obj,
266 pickle_protocol, NULL);
267 if (!pickled_string)
268 goto failure;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000269
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000270 if (PyString_AsStringAndSize(pickled_string, &buffer, &length) < 0)
271 goto failure;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000272
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000273 res = conn_send_string(self, buffer, (int)length);
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000274
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000275 if (res < 0) {
276 mp_SetError(PyExc_IOError, res);
277 goto failure;
278 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000279
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000280 Py_XDECREF(pickled_string);
281 Py_RETURN_NONE;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000282
283 failure:
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000284 Py_XDECREF(pickled_string);
285 return NULL;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000286}
287
288static PyObject *
289connection_recv_obj(ConnectionObject *self)
290{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000291 char *freeme = NULL;
292 Py_ssize_t res;
293 PyObject *temp = NULL, *result = NULL;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000294
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000295 CHECK_READABLE(self);
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000296
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000297 res = conn_recv_string(self, self->buffer, CONNECTION_BUFFER_SIZE,
298 &freeme, PY_SSIZE_T_MAX);
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000299
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000300 if (res < 0) {
301 if (res == MP_BAD_MESSAGE_LENGTH) {
302 if ((self->flags & WRITABLE) == 0) {
303 Py_BEGIN_ALLOW_THREADS
304 CLOSE(self->handle);
305 Py_END_ALLOW_THREADS
306 self->handle = INVALID_HANDLE_VALUE;
307 } else {
308 self->flags = WRITABLE;
309 }
310 }
311 mp_SetError(PyExc_IOError, res);
312 } else {
313 if (freeme == NULL) {
314 temp = PyString_FromStringAndSize(self->buffer, res);
315 } else {
316 temp = PyString_FromStringAndSize(freeme, res);
317 PyMem_Free(freeme);
318 }
319 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000320
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000321 if (temp)
322 result = PyObject_CallFunctionObjArgs(pickle_loads,
323 temp, NULL);
324 Py_XDECREF(temp);
325 return result;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000326}
327
328/*
329 * Other functions
330 */
331
332static PyObject *
333connection_poll(ConnectionObject *self, PyObject *args)
334{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000335 PyObject *timeout_obj = NULL;
336 double timeout = 0.0;
337 int res;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000338
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000339 CHECK_READABLE(self);
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000340
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000341 if (!PyArg_ParseTuple(args, "|O", &timeout_obj))
342 return NULL;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000343
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000344 if (timeout_obj == NULL) {
345 timeout = 0.0;
346 } else if (timeout_obj == Py_None) {
347 timeout = -1.0; /* block forever */
348 } else {
349 timeout = PyFloat_AsDouble(timeout_obj);
350 if (PyErr_Occurred())
351 return NULL;
352 if (timeout < 0.0)
353 timeout = 0.0;
354 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000355
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000356 Py_BEGIN_ALLOW_THREADS
357 res = conn_poll(self, timeout, _save);
358 Py_END_ALLOW_THREADS
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000359
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000360 switch (res) {
361 case TRUE:
362 Py_RETURN_TRUE;
363 case FALSE:
364 Py_RETURN_FALSE;
365 default:
366 return mp_SetError(PyExc_IOError, res);
367 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000368}
369
370static PyObject *
371connection_fileno(ConnectionObject* self)
372{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000373 if (self->handle == INVALID_HANDLE_VALUE) {
374 PyErr_SetString(PyExc_IOError, "handle is invalid");
375 return NULL;
376 }
377 return PyInt_FromLong((long)self->handle);
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000378}
379
380static PyObject *
381connection_close(ConnectionObject *self)
382{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000383 if (self->handle != INVALID_HANDLE_VALUE) {
384 Py_BEGIN_ALLOW_THREADS
385 CLOSE(self->handle);
386 Py_END_ALLOW_THREADS
387 self->handle = INVALID_HANDLE_VALUE;
388 }
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000389
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000390 Py_RETURN_NONE;
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000391}
392
393static PyObject *
394connection_repr(ConnectionObject *self)
395{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000396 static char *conn_type[] = {"read-only", "write-only", "read-write"};
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000397
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000398 assert(self->flags >= 1 && self->flags <= 3);
399 return FROM_FORMAT("<%s %s, handle %zd>",
400 conn_type[self->flags - 1],
401 CONNECTION_NAME, (Py_ssize_t)self->handle);
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000402}
403
404/*
405 * Getters and setters
406 */
407
408static PyObject *
409connection_closed(ConnectionObject *self, void *closure)
410{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000411 return PyBool_FromLong((long)(self->handle == INVALID_HANDLE_VALUE));
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000412}
413
414static PyObject *
415connection_readable(ConnectionObject *self, void *closure)
416{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000417 return PyBool_FromLong((long)(self->flags & READABLE));
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000418}
419
420static PyObject *
421connection_writable(ConnectionObject *self, void *closure)
422{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000423 return PyBool_FromLong((long)(self->flags & WRITABLE));
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000424}
425
426/*
427 * Tables
428 */
429
430static PyMethodDef connection_methods[] = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000431 {"send_bytes", (PyCFunction)connection_sendbytes, METH_VARARGS,
432 "send the byte data from a readable buffer-like object"},
433 {"recv_bytes", (PyCFunction)connection_recvbytes, METH_VARARGS,
434 "receive byte data as a string"},
435 {"recv_bytes_into",(PyCFunction)connection_recvbytes_into,METH_VARARGS,
436 "receive byte data into a writeable buffer-like object\n"
437 "returns the number of bytes read"},
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000438
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000439 {"send", (PyCFunction)connection_send_obj, METH_O,
440 "send a (picklable) object"},
441 {"recv", (PyCFunction)connection_recv_obj, METH_NOARGS,
442 "receive a (picklable) object"},
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000443
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000444 {"poll", (PyCFunction)connection_poll, METH_VARARGS,
445 "whether there is any input available to be read"},
446 {"fileno", (PyCFunction)connection_fileno, METH_NOARGS,
447 "file descriptor or handle of the connection"},
448 {"close", (PyCFunction)connection_close, METH_NOARGS,
449 "close the connection"},
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000450
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000451 {NULL} /* Sentinel */
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000452};
453
454static PyGetSetDef connection_getset[] = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000455 {"closed", (getter)connection_closed, NULL,
456 "True if the connection is closed", NULL},
457 {"readable", (getter)connection_readable, NULL,
458 "True if the connection is readable", NULL},
459 {"writable", (getter)connection_writable, NULL,
460 "True if the connection is writable", NULL},
461 {NULL}
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000462};
463
464/*
465 * Connection type
466 */
467
468PyDoc_STRVAR(connection_doc,
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000469 "Connection type whose constructor signature is\n\n"
470 " Connection(handle, readable=True, writable=True).\n\n"
471 "The constructor does *not* duplicate the handle.");
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000472
473PyTypeObject CONNECTION_TYPE = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000474 PyVarObject_HEAD_INIT(NULL, 0)
475 /* tp_name */ "_multiprocessing." CONNECTION_NAME,
476 /* tp_basicsize */ sizeof(ConnectionObject),
477 /* tp_itemsize */ 0,
478 /* tp_dealloc */ (destructor)connection_dealloc,
479 /* tp_print */ 0,
480 /* tp_getattr */ 0,
481 /* tp_setattr */ 0,
482 /* tp_compare */ 0,
483 /* tp_repr */ (reprfunc)connection_repr,
484 /* tp_as_number */ 0,
485 /* tp_as_sequence */ 0,
486 /* tp_as_mapping */ 0,
487 /* tp_hash */ 0,
488 /* tp_call */ 0,
489 /* tp_str */ 0,
490 /* tp_getattro */ 0,
491 /* tp_setattro */ 0,
492 /* tp_as_buffer */ 0,
493 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
494 Py_TPFLAGS_HAVE_WEAKREFS,
495 /* tp_doc */ connection_doc,
496 /* tp_traverse */ 0,
497 /* tp_clear */ 0,
498 /* tp_richcompare */ 0,
499 /* tp_weaklistoffset */ offsetof(ConnectionObject, weakreflist),
500 /* tp_iter */ 0,
501 /* tp_iternext */ 0,
502 /* tp_methods */ connection_methods,
503 /* tp_members */ 0,
504 /* tp_getset */ connection_getset,
505 /* tp_base */ 0,
506 /* tp_dict */ 0,
507 /* tp_descr_get */ 0,
508 /* tp_descr_set */ 0,
509 /* tp_dictoffset */ 0,
510 /* tp_init */ 0,
511 /* tp_alloc */ 0,
512 /* tp_new */ connection_new,
Benjamin Peterson190d56e2008-06-11 02:40:25 +0000513};
514
515#endif /* CONNECTION_H */