blob: ffbc72b1657ef7a0c4a5b8a54384d4ad6ac394d8 [file] [log] [blame]
Tim Peters6d6c1a32001-08-02 04:15:00 +00001#include "Python.h"
Guido van Rossume6b90ea2001-08-15 18:09:11 +00002#include "structmember.h"
Tim Peters6d6c1a32001-08-02 04:15:00 +00003
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00004PyDoc_STRVAR(xxsubtype__doc__,
Tim Peters65760b22001-12-10 22:53:30 +00005"xxsubtype is an example module showing how to subtype builtin types from C.\n"
6"test_descr.py in the standard test suite requires it in order to complete.\n"
7"If you don't care about the examples, and don't intend to run the Python\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00008"test suite, you can recompile Python without Modules/xxsubtype.c.");
Tim Peters6d6c1a32001-08-02 04:15:00 +00009
Tim Petersdd5c05f2001-12-17 01:27:01 +000010/* We link this module statically for convenience. If compiled as a shared
11 library instead, some compilers don't allow addresses of Python objects
12 defined in other libraries to be used in static initializers here. The
13 DEFERRED_ADDRESS macro is used to tag the slots where such addresses
14 appear; the module init function must fill in the tagged slots at runtime.
15 The argument is for documentation -- the macro ignores it.
16*/
17#define DEFERRED_ADDRESS(ADDR) 0
18
Tim Peters6d6c1a32001-08-02 04:15:00 +000019/* spamlist -- a list subtype */
20
21typedef struct {
22 PyListObject list;
23 int state;
24} spamlistobject;
25
26static PyObject *
27spamlist_getstate(spamlistobject *self, PyObject *args)
28{
29 if (!PyArg_ParseTuple(args, ":getstate"))
30 return NULL;
31 return PyInt_FromLong(self->state);
32}
33
34static PyObject *
35spamlist_setstate(spamlistobject *self, PyObject *args)
36{
37 int state;
38
39 if (!PyArg_ParseTuple(args, "i:setstate", &state))
40 return NULL;
41 self->state = state;
42 Py_INCREF(Py_None);
43 return Py_None;
44}
45
Fred Drakef841aa62002-03-28 15:49:54 +000046static PyObject *
47spamlist_specialmeth(PyObject *self, PyObject *args, PyObject *kw)
48{
49 PyObject *result = PyTuple_New(3);
50
51 if (result != NULL) {
52 if (self == NULL)
53 self = Py_None;
54 if (kw == NULL)
55 kw = Py_None;
56 Py_INCREF(self);
57 PyTuple_SET_ITEM(result, 0, self);
58 Py_INCREF(args);
59 PyTuple_SET_ITEM(result, 1, args);
60 Py_INCREF(kw);
61 PyTuple_SET_ITEM(result, 2, kw);
62 }
63 return result;
64}
65
Tim Peters6d6c1a32001-08-02 04:15:00 +000066static PyMethodDef spamlist_methods[] = {
67 {"getstate", (PyCFunction)spamlist_getstate, METH_VARARGS,
Skip Montanaro23b59182002-08-14 01:45:37 +000068 PyDoc_STR("getstate() -> state")},
Tim Peters6d6c1a32001-08-02 04:15:00 +000069 {"setstate", (PyCFunction)spamlist_setstate, METH_VARARGS,
Skip Montanaro23b59182002-08-14 01:45:37 +000070 PyDoc_STR("setstate(state)")},
Fred Drakef841aa62002-03-28 15:49:54 +000071 /* These entries differ only in the flags; they are used by the tests
72 in test.test_descr. */
73 {"classmeth", (PyCFunction)spamlist_specialmeth,
74 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
Skip Montanaro23b59182002-08-14 01:45:37 +000075 PyDoc_STR("classmeth(*args, **kw)")},
Fred Drakef841aa62002-03-28 15:49:54 +000076 {"staticmeth", (PyCFunction)spamlist_specialmeth,
77 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
Skip Montanaro23b59182002-08-14 01:45:37 +000078 PyDoc_STR("staticmeth(*args, **kw)")},
Tim Peters6d6c1a32001-08-02 04:15:00 +000079 {NULL, NULL},
80};
81
Jeremy Hylton938ace62002-07-17 16:30:39 +000082static PyTypeObject spamlist_type;
Tim Peters6d6c1a32001-08-02 04:15:00 +000083
84static int
85spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)
86{
87 if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0)
88 return -1;
89 self->state = 0;
90 return 0;
91}
92
Guido van Rossum88dcf032001-08-15 18:18:58 +000093static PyObject *
94spamlist_state_get(spamlistobject *self)
95{
96 return PyInt_FromLong(self->state);
97}
98
Guido van Rossum32d34c82001-09-20 21:45:26 +000099static PyGetSetDef spamlist_getsets[] = {
100 {"state", (getter)spamlist_state_get, NULL,
Skip Montanaro23b59182002-08-14 01:45:37 +0000101 PyDoc_STR("an int variable for demonstration purposes")},
Guido van Rossum88dcf032001-08-15 18:18:58 +0000102 {0}
103};
104
Tim Peters6d6c1a32001-08-02 04:15:00 +0000105static PyTypeObject spamlist_type = {
Tim Petersdd5c05f2001-12-17 01:27:01 +0000106 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
Tim Peters6d6c1a32001-08-02 04:15:00 +0000107 0,
Guido van Rossum83f56cb2001-08-16 09:10:42 +0000108 "xxsubtype.spamlist",
Tim Peters6d6c1a32001-08-02 04:15:00 +0000109 sizeof(spamlistobject),
110 0,
111 0, /* tp_dealloc */
112 0, /* tp_print */
113 0, /* tp_getattr */
114 0, /* tp_setattr */
115 0, /* tp_compare */
116 0, /* tp_repr */
117 0, /* tp_as_number */
118 0, /* tp_as_sequence */
119 0, /* tp_as_mapping */
120 0, /* tp_hash */
121 0, /* tp_call */
122 0, /* tp_str */
123 0, /* tp_getattro */
124 0, /* tp_setattro */
125 0, /* tp_as_buffer */
126 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
127 0, /* tp_doc */
128 0, /* tp_traverse */
129 0, /* tp_clear */
130 0, /* tp_richcompare */
131 0, /* tp_weaklistoffset */
132 0, /* tp_iter */
133 0, /* tp_iternext */
134 spamlist_methods, /* tp_methods */
135 0, /* tp_members */
Guido van Rossum88dcf032001-08-15 18:18:58 +0000136 spamlist_getsets, /* tp_getset */
Tim Petersdd5c05f2001-12-17 01:27:01 +0000137 DEFERRED_ADDRESS(&PyList_Type), /* tp_base */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000138 0, /* tp_dict */
139 0, /* tp_descr_get */
140 0, /* tp_descr_set */
141 0, /* tp_dictoffset */
142 (initproc)spamlist_init, /* tp_init */
143 0, /* tp_alloc */
144 0, /* tp_new */
145};
146
147/* spamdict -- a dict subtype */
148
149typedef struct {
150 PyDictObject dict;
151 int state;
152} spamdictobject;
153
154static PyObject *
155spamdict_getstate(spamdictobject *self, PyObject *args)
156{
157 if (!PyArg_ParseTuple(args, ":getstate"))
158 return NULL;
159 return PyInt_FromLong(self->state);
160}
161
162static PyObject *
163spamdict_setstate(spamdictobject *self, PyObject *args)
164{
165 int state;
166
167 if (!PyArg_ParseTuple(args, "i:setstate", &state))
168 return NULL;
169 self->state = state;
170 Py_INCREF(Py_None);
171 return Py_None;
172}
173
174static PyMethodDef spamdict_methods[] = {
175 {"getstate", (PyCFunction)spamdict_getstate, METH_VARARGS,
Skip Montanaro23b59182002-08-14 01:45:37 +0000176 PyDoc_STR("getstate() -> state")},
Tim Peters6d6c1a32001-08-02 04:15:00 +0000177 {"setstate", (PyCFunction)spamdict_setstate, METH_VARARGS,
Skip Montanaro23b59182002-08-14 01:45:37 +0000178 PyDoc_STR("setstate(state)")},
Tim Peters6d6c1a32001-08-02 04:15:00 +0000179 {NULL, NULL},
180};
181
Jeremy Hylton938ace62002-07-17 16:30:39 +0000182static PyTypeObject spamdict_type;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000183
184static int
185spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)
186{
187 if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
188 return -1;
189 self->state = 0;
190 return 0;
191}
192
Guido van Rossum6f799372001-09-20 20:46:19 +0000193static PyMemberDef spamdict_members[] = {
194 {"state", T_INT, offsetof(spamdictobject, state), READONLY,
Skip Montanaro23b59182002-08-14 01:45:37 +0000195 PyDoc_STR("an int variable for demonstration purposes")},
Guido van Rossume6b90ea2001-08-15 18:09:11 +0000196 {0}
197};
198
Tim Peters6d6c1a32001-08-02 04:15:00 +0000199static PyTypeObject spamdict_type = {
Tim Petersdd5c05f2001-12-17 01:27:01 +0000200 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
Tim Peters6d6c1a32001-08-02 04:15:00 +0000201 0,
Guido van Rossum83f56cb2001-08-16 09:10:42 +0000202 "xxsubtype.spamdict",
Tim Peters6d6c1a32001-08-02 04:15:00 +0000203 sizeof(spamdictobject),
204 0,
205 0, /* tp_dealloc */
206 0, /* tp_print */
207 0, /* tp_getattr */
208 0, /* tp_setattr */
209 0, /* tp_compare */
210 0, /* tp_repr */
211 0, /* tp_as_number */
212 0, /* tp_as_sequence */
213 0, /* tp_as_mapping */
214 0, /* tp_hash */
215 0, /* tp_call */
216 0, /* tp_str */
217 0, /* tp_getattro */
218 0, /* tp_setattro */
219 0, /* tp_as_buffer */
220 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
221 0, /* tp_doc */
222 0, /* tp_traverse */
223 0, /* tp_clear */
224 0, /* tp_richcompare */
225 0, /* tp_weaklistoffset */
226 0, /* tp_iter */
227 0, /* tp_iternext */
228 spamdict_methods, /* tp_methods */
Guido van Rossume6b90ea2001-08-15 18:09:11 +0000229 spamdict_members, /* tp_members */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000230 0, /* tp_getset */
Tim Petersdd5c05f2001-12-17 01:27:01 +0000231 DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000232 0, /* tp_dict */
233 0, /* tp_descr_get */
234 0, /* tp_descr_set */
235 0, /* tp_dictoffset */
236 (initproc)spamdict_init, /* tp_init */
237 0, /* tp_alloc */
238 0, /* tp_new */
239};
240
Neil Schemenauer26775122001-10-21 22:26:43 +0000241static PyObject *
Tim Peters6d6c1a32001-08-02 04:15:00 +0000242spam_bench(PyObject *self, PyObject *args)
243{
244 PyObject *obj, *name, *res;
245 int n = 1000;
246 time_t t0, t1;
247
248 if (!PyArg_ParseTuple(args, "OS|i", &obj, &name, &n))
249 return NULL;
250 t0 = clock();
251 while (--n >= 0) {
252 res = PyObject_GetAttr(obj, name);
253 if (res == NULL)
254 return NULL;
255 Py_DECREF(res);
256 }
257 t1 = clock();
258 return PyFloat_FromDouble((double)(t1-t0) / CLOCKS_PER_SEC);
259}
260
261static PyMethodDef xxsubtype_functions[] = {
262 {"bench", spam_bench, METH_VARARGS},
263 {NULL, NULL} /* sentinel */
264};
265
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000266PyMODINIT_FUNC
Tim Peters6d6c1a32001-08-02 04:15:00 +0000267initxxsubtype(void)
268{
Fred Drake1de5a722002-03-12 21:49:44 +0000269 PyObject *m;
Tim Peters6d6c1a32001-08-02 04:15:00 +0000270
Tim Peters4befff92001-12-17 18:26:19 +0000271 /* Fill in deferred data addresses. This must be done before
272 PyType_Ready() is called. Note that PyType_Ready() automatically
273 initializes the ob.ob_type field to &PyType_Type if it's NULL,
274 so it's not necessary to fill in ob_type first. */
Tim Petersdd5c05f2001-12-17 01:27:01 +0000275 spamdict_type.tp_base = &PyDict_Type;
Guido van Rossuma7b9b3c2001-12-17 17:25:53 +0000276 if (PyType_Ready(&spamdict_type) < 0)
277 return;
Tim Petersdd5c05f2001-12-17 01:27:01 +0000278
Tim Petersdd5c05f2001-12-17 01:27:01 +0000279 spamlist_type.tp_base = &PyList_Type;
Guido van Rossuma7b9b3c2001-12-17 17:25:53 +0000280 if (PyType_Ready(&spamlist_type) < 0)
281 return;
Tim Petersdd5c05f2001-12-17 01:27:01 +0000282
Tim Peters65760b22001-12-10 22:53:30 +0000283 m = Py_InitModule3("xxsubtype",
284 xxsubtype_functions,
285 xxsubtype__doc__);
Tim Peters6d6c1a32001-08-02 04:15:00 +0000286 if (m == NULL)
287 return;
288
Guido van Rossum528b7eb2001-08-07 17:24:28 +0000289 if (PyType_Ready(&spamlist_type) < 0)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000290 return;
Guido van Rossum528b7eb2001-08-07 17:24:28 +0000291 if (PyType_Ready(&spamdict_type) < 0)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000292 return;
293
Tim Peters6d6c1a32001-08-02 04:15:00 +0000294 Py_INCREF(&spamlist_type);
Fred Drake1de5a722002-03-12 21:49:44 +0000295 if (PyModule_AddObject(m, "spamlist",
296 (PyObject *) &spamlist_type) < 0)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000297 return;
298
299 Py_INCREF(&spamdict_type);
Fred Drake1de5a722002-03-12 21:49:44 +0000300 if (PyModule_AddObject(m, "spamdict",
301 (PyObject *) &spamdict_type) < 0)
Tim Peters6d6c1a32001-08-02 04:15:00 +0000302 return;
303}