blob: 002d5aa9cc56b3867c845ca8e9ab72f0a9655fce [file] [log] [blame]
Benjamin Petersone711caf2008-06-11 16:44:04 +00001/*
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002 * Definition of a `Connection` type.
Benjamin Petersone711caf2008-06-11 16:44:04 +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 Pitrouf95a1b32010-05-09 15:52:27 +000022 PyErr_SetString(PyExc_IOError, "connection is write-only"); \
23 return NULL; \
Benjamin Petersone711caf2008-06-11 16:44:04 +000024 }
25
26#define CHECK_WRITABLE(self) \
27 if (!(self->flags & WRITABLE)) { \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000028 PyErr_SetString(PyExc_IOError, "connection is read-only"); \
29 return NULL; \
Benjamin Petersone711caf2008-06-11 16:44:04 +000030 }
31
32/*
33 * Allocation and deallocation
34 */
35
36static PyObject *
37connection_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
38{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000039 ConnectionObject *self;
40 HANDLE handle;
41 BOOL readable = TRUE, writable = TRUE;
Benjamin Petersone711caf2008-06-11 16:44:04 +000042
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000043 static char *kwlist[] = {"handle", "readable", "writable", NULL};
Benjamin Petersone711caf2008-06-11 16:44:04 +000044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000045 if (!PyArg_ParseTupleAndKeywords(args, kwds, F_HANDLE "|ii", kwlist,
46 &handle, &readable, &writable))
47 return NULL;
Benjamin Petersone711caf2008-06-11 16:44:04 +000048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +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 Petersone711caf2008-06-11 16:44:04 +000054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000055 if (!readable && !writable) {
56 PyErr_SetString(PyExc_ValueError,
57 "either readable or writable must be true");
58 return NULL;
59 }
Benjamin Petersone711caf2008-06-11 16:44:04 +000060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000061 self = PyObject_New(ConnectionObject, type);
62 if (self == NULL)
63 return NULL;
Benjamin Petersone711caf2008-06-11 16:44:04 +000064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 self->weakreflist = NULL;
66 self->handle = handle;
67 self->flags = 0;
Benjamin Petersone711caf2008-06-11 16:44:04 +000068
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000069 if (readable)
70 self->flags |= READABLE;
71 if (writable)
72 self->flags |= WRITABLE;
73 assert(self->flags >= 1 && self->flags <= 3);
Benjamin Petersone711caf2008-06-11 16:44:04 +000074
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000075 return (PyObject*)self;
Benjamin Petersone711caf2008-06-11 16:44:04 +000076}
77
78static void
79connection_dealloc(ConnectionObject* self)
80{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 if (self->weakreflist != NULL)
82 PyObject_ClearWeakRefs((PyObject*)self);
Benjamin Petersone711caf2008-06-11 16:44:04 +000083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +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 Petersone711caf2008-06-11 16:44:04 +000090}
91
92/*
93 * Functions for transferring buffers
94 */
95
96static PyObject *
97connection_sendbytes(ConnectionObject *self, PyObject *args)
98{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 Py_buffer pbuffer;
100 char *buffer;
101 Py_ssize_t length, offset=0, size=PY_SSIZE_T_MIN;
102 int res;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 if (!PyArg_ParseTuple(args, F_RBUFFER "*|" F_PY_SSIZE_T F_PY_SSIZE_T,
105 &pbuffer, &offset, &size))
106 return NULL;
107 buffer = pbuffer.buf;
108 length = pbuffer.len;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000109
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000110 CHECK_WRITABLE(self); /* XXX release buffer in case of failure */
Benjamin Petersone711caf2008-06-11 16:44:04 +0000111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000112 if (offset < 0) {
113 PyBuffer_Release(&pbuffer);
114 PyErr_SetString(PyExc_ValueError, "offset is negative");
115 return NULL;
116 }
117 if (length < offset) {
118 PyBuffer_Release(&pbuffer);
119 PyErr_SetString(PyExc_ValueError, "buffer length < offset");
120 return NULL;
121 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000122
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000123 if (size == PY_SSIZE_T_MIN) {
124 size = length - offset;
125 } else {
126 if (size < 0) {
127 PyBuffer_Release(&pbuffer);
128 PyErr_SetString(PyExc_ValueError, "size is negative");
129 return NULL;
130 }
131 if (offset + size > length) {
132 PyBuffer_Release(&pbuffer);
133 PyErr_SetString(PyExc_ValueError,
134 "buffer length < offset + size");
135 return NULL;
136 }
137 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000139 res = conn_send_string(self, buffer + offset, size);
Benjamin Petersone711caf2008-06-11 16:44:04 +0000140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 PyBuffer_Release(&pbuffer);
142 if (res < 0) {
143 if (PyErr_Occurred())
144 return NULL;
145 else
146 return mp_SetError(PyExc_IOError, res);
147 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000148
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000149 Py_RETURN_NONE;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000150}
151
152static PyObject *
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000153connection_recvbytes(ConnectionObject *self, PyObject *args)
Benjamin Petersone711caf2008-06-11 16:44:04 +0000154{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 char *freeme = NULL;
156 Py_ssize_t res, maxlength = PY_SSIZE_T_MAX;
157 PyObject *result = NULL;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000158
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000159 if (!PyArg_ParseTuple(args, "|" F_PY_SSIZE_T, &maxlength))
160 return NULL;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000161
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 CHECK_READABLE(self);
163
164 if (maxlength < 0) {
165 PyErr_SetString(PyExc_ValueError, "maxlength < 0");
166 return NULL;
167 }
168
169 res = conn_recv_string(self, self->buffer, CONNECTION_BUFFER_SIZE,
170 &freeme, maxlength);
171
172 if (res < 0) {
173 if (res == MP_BAD_MESSAGE_LENGTH) {
174 if ((self->flags & WRITABLE) == 0) {
175 Py_BEGIN_ALLOW_THREADS
176 CLOSE(self->handle);
177 Py_END_ALLOW_THREADS
178 self->handle = INVALID_HANDLE_VALUE;
179 } else {
180 self->flags = WRITABLE;
181 }
182 }
183 mp_SetError(PyExc_IOError, res);
184 } else {
185 if (freeme == NULL) {
186 result = PyBytes_FromStringAndSize(self->buffer, res);
187 } else {
188 result = PyBytes_FromStringAndSize(freeme, res);
189 PyMem_Free(freeme);
190 }
191 }
192
193 return result;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000194}
195
196static PyObject *
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197connection_recvbytes_into(ConnectionObject *self, PyObject *args)
Benjamin Petersone711caf2008-06-11 16:44:04 +0000198{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 char *freeme = NULL, *buffer = NULL;
200 Py_ssize_t res, length, offset = 0;
201 PyObject *result = NULL;
202 Py_buffer pbuf;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000203
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000204 CHECK_READABLE(self);
Martin v. Löwis423be952008-08-13 15:53:07 +0000205
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000206 if (!PyArg_ParseTuple(args, "w*|" F_PY_SSIZE_T,
207 &pbuf, &offset))
208 return NULL;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000210 buffer = pbuf.buf;
211 length = pbuf.len;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000212
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000213 if (offset < 0) {
214 PyErr_SetString(PyExc_ValueError, "negative offset");
215 goto _error;
216 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000217
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000218 if (offset > length) {
219 PyErr_SetString(PyExc_ValueError, "offset too large");
220 goto _error;
221 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000222
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000223 res = conn_recv_string(self, buffer+offset, length-offset,
224 &freeme, PY_SSIZE_T_MAX);
225
226 if (res < 0) {
227 if (res == MP_BAD_MESSAGE_LENGTH) {
228 if ((self->flags & WRITABLE) == 0) {
229 Py_BEGIN_ALLOW_THREADS
230 CLOSE(self->handle);
231 Py_END_ALLOW_THREADS
232 self->handle = INVALID_HANDLE_VALUE;
233 } else {
234 self->flags = WRITABLE;
235 }
236 }
237 mp_SetError(PyExc_IOError, res);
238 } else {
239 if (freeme == NULL) {
240 result = PyInt_FromSsize_t(res);
241 } else {
242 result = PyObject_CallFunction(BufferTooShort,
243 F_RBUFFER "#",
244 freeme, res);
245 PyMem_Free(freeme);
246 if (result) {
247 PyErr_SetObject(BufferTooShort, result);
248 Py_DECREF(result);
249 }
250 goto _error;
251 }
252 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000253
Martin v. Löwis423be952008-08-13 15:53:07 +0000254_cleanup:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000255 PyBuffer_Release(&pbuf);
256 return result;
Martin v. Löwis423be952008-08-13 15:53:07 +0000257
258_error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000259 result = NULL;
260 goto _cleanup;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000261}
262
263/*
264 * Functions for transferring objects
265 */
266
267static PyObject *
268connection_send_obj(ConnectionObject *self, PyObject *obj)
269{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 char *buffer;
271 int res;
272 Py_ssize_t length;
273 PyObject *pickled_string = NULL;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275 CHECK_WRITABLE(self);
Benjamin Petersone711caf2008-06-11 16:44:04 +0000276
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000277 pickled_string = PyObject_CallFunctionObjArgs(pickle_dumps, obj,
278 pickle_protocol, NULL);
279 if (!pickled_string)
280 goto failure;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000282 if (PyBytes_AsStringAndSize(pickled_string, &buffer, &length) < 0)
283 goto failure;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000285 res = conn_send_string(self, buffer, (int)length);
Benjamin Petersone711caf2008-06-11 16:44:04 +0000286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000287 if (res < 0) {
288 mp_SetError(PyExc_IOError, res);
289 goto failure;
290 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000292 Py_XDECREF(pickled_string);
293 Py_RETURN_NONE;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000294
295 failure:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296 Py_XDECREF(pickled_string);
297 return NULL;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000298}
299
300static PyObject *
301connection_recv_obj(ConnectionObject *self)
302{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000303 char *freeme = NULL;
304 Py_ssize_t res;
305 PyObject *temp = NULL, *result = NULL;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000307 CHECK_READABLE(self);
Benjamin Petersone711caf2008-06-11 16:44:04 +0000308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000309 res = conn_recv_string(self, self->buffer, CONNECTION_BUFFER_SIZE,
310 &freeme, PY_SSIZE_T_MAX);
Benjamin Petersone711caf2008-06-11 16:44:04 +0000311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000312 if (res < 0) {
313 if (res == MP_BAD_MESSAGE_LENGTH) {
314 if ((self->flags & WRITABLE) == 0) {
315 Py_BEGIN_ALLOW_THREADS
316 CLOSE(self->handle);
317 Py_END_ALLOW_THREADS
318 self->handle = INVALID_HANDLE_VALUE;
319 } else {
320 self->flags = WRITABLE;
321 }
322 }
323 mp_SetError(PyExc_IOError, res);
324 } else {
325 if (freeme == NULL) {
326 temp = PyBytes_FromStringAndSize(self->buffer, res);
327 } else {
328 temp = PyBytes_FromStringAndSize(freeme, res);
329 PyMem_Free(freeme);
330 }
331 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000333 if (temp)
334 result = PyObject_CallFunctionObjArgs(pickle_loads,
335 temp, NULL);
336 Py_XDECREF(temp);
337 return result;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000338}
339
340/*
341 * Other functions
342 */
343
344static PyObject *
345connection_poll(ConnectionObject *self, PyObject *args)
346{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000347 PyObject *timeout_obj = NULL;
348 double timeout = 0.0;
349 int res;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000350
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000351 CHECK_READABLE(self);
Benjamin Petersone711caf2008-06-11 16:44:04 +0000352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000353 if (!PyArg_ParseTuple(args, "|O", &timeout_obj))
354 return NULL;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356 if (timeout_obj == NULL) {
357 timeout = 0.0;
358 } else if (timeout_obj == Py_None) {
359 timeout = -1.0; /* block forever */
360 } else {
361 timeout = PyFloat_AsDouble(timeout_obj);
362 if (PyErr_Occurred())
363 return NULL;
364 if (timeout < 0.0)
365 timeout = 0.0;
366 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000367
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000368 Py_BEGIN_ALLOW_THREADS
369 res = conn_poll(self, timeout, _save);
370 Py_END_ALLOW_THREADS
Benjamin Petersone711caf2008-06-11 16:44:04 +0000371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000372 switch (res) {
373 case TRUE:
374 Py_RETURN_TRUE;
375 case FALSE:
376 Py_RETURN_FALSE;
377 default:
378 return mp_SetError(PyExc_IOError, res);
379 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000380}
381
382static PyObject *
383connection_fileno(ConnectionObject* self)
384{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385 if (self->handle == INVALID_HANDLE_VALUE) {
386 PyErr_SetString(PyExc_IOError, "handle is invalid");
387 return NULL;
388 }
389 return PyInt_FromLong((long)self->handle);
Benjamin Petersone711caf2008-06-11 16:44:04 +0000390}
391
392static PyObject *
393connection_close(ConnectionObject *self)
394{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 if (self->handle != INVALID_HANDLE_VALUE) {
396 Py_BEGIN_ALLOW_THREADS
397 CLOSE(self->handle);
398 Py_END_ALLOW_THREADS
399 self->handle = INVALID_HANDLE_VALUE;
400 }
Benjamin Petersone711caf2008-06-11 16:44:04 +0000401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000402 Py_RETURN_NONE;
Benjamin Petersone711caf2008-06-11 16:44:04 +0000403}
404
405static PyObject *
406connection_repr(ConnectionObject *self)
407{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000408 static char *conn_type[] = {"read-only", "write-only", "read-write"};
Benjamin Petersone711caf2008-06-11 16:44:04 +0000409
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000410 assert(self->flags >= 1 && self->flags <= 3);
411 return FROM_FORMAT("<%s %s, handle %zd>",
412 conn_type[self->flags - 1],
413 CONNECTION_NAME, (Py_ssize_t)self->handle);
Benjamin Petersone711caf2008-06-11 16:44:04 +0000414}
415
416/*
417 * Getters and setters
418 */
419
420static PyObject *
421connection_closed(ConnectionObject *self, void *closure)
422{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 return PyBool_FromLong((long)(self->handle == INVALID_HANDLE_VALUE));
Benjamin Petersone711caf2008-06-11 16:44:04 +0000424}
425
426static PyObject *
427connection_readable(ConnectionObject *self, void *closure)
428{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000429 return PyBool_FromLong((long)(self->flags & READABLE));
Benjamin Petersone711caf2008-06-11 16:44:04 +0000430}
431
432static PyObject *
433connection_writable(ConnectionObject *self, void *closure)
434{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000435 return PyBool_FromLong((long)(self->flags & WRITABLE));
Benjamin Petersone711caf2008-06-11 16:44:04 +0000436}
437
438/*
439 * Tables
440 */
441
442static PyMethodDef connection_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443 {"send_bytes", (PyCFunction)connection_sendbytes, METH_VARARGS,
444 "send the byte data from a readable buffer-like object"},
445 {"recv_bytes", (PyCFunction)connection_recvbytes, METH_VARARGS,
446 "receive byte data as a string"},
447 {"recv_bytes_into",(PyCFunction)connection_recvbytes_into,METH_VARARGS,
448 "receive byte data into a writeable buffer-like object\n"
449 "returns the number of bytes read"},
Benjamin Petersone711caf2008-06-11 16:44:04 +0000450
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000451 {"send", (PyCFunction)connection_send_obj, METH_O,
452 "send a (picklable) object"},
453 {"recv", (PyCFunction)connection_recv_obj, METH_NOARGS,
454 "receive a (picklable) object"},
Benjamin Petersone711caf2008-06-11 16:44:04 +0000455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 {"poll", (PyCFunction)connection_poll, METH_VARARGS,
457 "whether there is any input available to be read"},
458 {"fileno", (PyCFunction)connection_fileno, METH_NOARGS,
459 "file descriptor or handle of the connection"},
460 {"close", (PyCFunction)connection_close, METH_NOARGS,
461 "close the connection"},
Benjamin Petersone711caf2008-06-11 16:44:04 +0000462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000463 {NULL} /* Sentinel */
Benjamin Petersone711caf2008-06-11 16:44:04 +0000464};
465
466static PyGetSetDef connection_getset[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000467 {"closed", (getter)connection_closed, NULL,
468 "True if the connection is closed", NULL},
469 {"readable", (getter)connection_readable, NULL,
470 "True if the connection is readable", NULL},
471 {"writable", (getter)connection_writable, NULL,
472 "True if the connection is writable", NULL},
473 {NULL}
Benjamin Petersone711caf2008-06-11 16:44:04 +0000474};
475
476/*
477 * Connection type
478 */
479
480PyDoc_STRVAR(connection_doc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000481 "Connection type whose constructor signature is\n\n"
482 " Connection(handle, readable=True, writable=True).\n\n"
483 "The constructor does *not* duplicate the handle.");
Benjamin Petersone711caf2008-06-11 16:44:04 +0000484
485PyTypeObject CONNECTION_TYPE = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 PyVarObject_HEAD_INIT(NULL, 0)
487 /* tp_name */ "_multiprocessing." CONNECTION_NAME,
488 /* tp_basicsize */ sizeof(ConnectionObject),
489 /* tp_itemsize */ 0,
490 /* tp_dealloc */ (destructor)connection_dealloc,
491 /* tp_print */ 0,
492 /* tp_getattr */ 0,
493 /* tp_setattr */ 0,
494 /* tp_reserved */ 0,
495 /* tp_repr */ (reprfunc)connection_repr,
496 /* tp_as_number */ 0,
497 /* tp_as_sequence */ 0,
498 /* tp_as_mapping */ 0,
499 /* tp_hash */ 0,
500 /* tp_call */ 0,
501 /* tp_str */ 0,
502 /* tp_getattro */ 0,
503 /* tp_setattro */ 0,
504 /* tp_as_buffer */ 0,
505 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
506 Py_TPFLAGS_HAVE_WEAKREFS,
507 /* tp_doc */ connection_doc,
508 /* tp_traverse */ 0,
509 /* tp_clear */ 0,
510 /* tp_richcompare */ 0,
511 /* tp_weaklistoffset */ offsetof(ConnectionObject, weakreflist),
512 /* tp_iter */ 0,
513 /* tp_iternext */ 0,
514 /* tp_methods */ connection_methods,
515 /* tp_members */ 0,
516 /* tp_getset */ connection_getset,
517 /* tp_base */ 0,
518 /* tp_dict */ 0,
519 /* tp_descr_get */ 0,
520 /* tp_descr_set */ 0,
521 /* tp_dictoffset */ 0,
522 /* tp_init */ 0,
523 /* tp_alloc */ 0,
524 /* tp_new */ connection_new,
Benjamin Petersone711caf2008-06-11 16:44:04 +0000525};
526
527#endif /* CONNECTION_H */