blob: 7a7cc1ecd4c11f605f900fae0dfdb6706f00d668 [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
Tim Peters65760b22001-12-10 22:53:30 +00004static char xxsubtype__doc__[] =
5"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"
8"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,
68 "getstate() -> state"},
69 {"setstate", (PyCFunction)spamlist_setstate, METH_VARARGS,
70 "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,
75 "classmeth(*args, **kw)"},
76 {"staticmeth", (PyCFunction)spamlist_specialmeth,
77 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
78 "staticmeth(*args, **kw)"},
Tim Peters6d6c1a32001-08-02 04:15:00 +000079 {NULL, NULL},
80};
81
82staticforward PyTypeObject spamlist_type;
83
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,
101 "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,
176 "getstate() -> state"},
177 {"setstate", (PyCFunction)spamdict_setstate, METH_VARARGS,
178 "setstate(state)"},
179 {NULL, NULL},
180};
181
182staticforward PyTypeObject spamdict_type;
183
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,
195 "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
266DL_EXPORT(void)
267initxxsubtype(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}