Updated documentation for findCaller() to indicate that a 3-tuple is now returned...
[python.git] / Modules / xxsubtype.c
blob88ce6c5bba48fd5afd5ecbc60590f7514210fdbf
1 #include "Python.h"
2 #include "structmember.h"
4 PyDoc_STRVAR(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.");
10 /* 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.
17 #define DEFERRED_ADDRESS(ADDR) 0
19 /* spamlist -- a list subtype */
21 typedef struct {
22 PyListObject list;
23 int state;
24 } spamlistobject;
26 static PyObject *
27 spamlist_getstate(spamlistobject *self, PyObject *args)
29 if (!PyArg_ParseTuple(args, ":getstate"))
30 return NULL;
31 return PyInt_FromLong(self->state);
34 static PyObject *
35 spamlist_setstate(spamlistobject *self, PyObject *args)
37 int state;
39 if (!PyArg_ParseTuple(args, "i:setstate", &state))
40 return NULL;
41 self->state = state;
42 Py_INCREF(Py_None);
43 return Py_None;
46 static PyObject *
47 spamlist_specialmeth(PyObject *self, PyObject *args, PyObject *kw)
49 PyObject *result = PyTuple_New(3);
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);
63 return result;
66 static PyMethodDef spamlist_methods[] = {
67 {"getstate", (PyCFunction)spamlist_getstate, METH_VARARGS,
68 PyDoc_STR("getstate() -> state")},
69 {"setstate", (PyCFunction)spamlist_setstate, METH_VARARGS,
70 PyDoc_STR("setstate(state)")},
71 /* 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 PyDoc_STR("classmeth(*args, **kw)")},
76 {"staticmeth", (PyCFunction)spamlist_specialmeth,
77 METH_VARARGS | METH_KEYWORDS | METH_STATIC,
78 PyDoc_STR("staticmeth(*args, **kw)")},
79 {NULL, NULL},
82 static int
83 spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)
85 if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0)
86 return -1;
87 self->state = 0;
88 return 0;
91 static PyObject *
92 spamlist_state_get(spamlistobject *self)
94 return PyInt_FromLong(self->state);
97 static PyGetSetDef spamlist_getsets[] = {
98 {"state", (getter)spamlist_state_get, NULL,
99 PyDoc_STR("an int variable for demonstration purposes")},
103 static PyTypeObject spamlist_type = {
104 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
106 "xxsubtype.spamlist",
107 sizeof(spamlistobject),
109 0, /* tp_dealloc */
110 0, /* tp_print */
111 0, /* tp_getattr */
112 0, /* tp_setattr */
113 0, /* tp_compare */
114 0, /* tp_repr */
115 0, /* tp_as_number */
116 0, /* tp_as_sequence */
117 0, /* tp_as_mapping */
118 0, /* tp_hash */
119 0, /* tp_call */
120 0, /* tp_str */
121 0, /* tp_getattro */
122 0, /* tp_setattro */
123 0, /* tp_as_buffer */
124 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
125 0, /* tp_doc */
126 0, /* tp_traverse */
127 0, /* tp_clear */
128 0, /* tp_richcompare */
129 0, /* tp_weaklistoffset */
130 0, /* tp_iter */
131 0, /* tp_iternext */
132 spamlist_methods, /* tp_methods */
133 0, /* tp_members */
134 spamlist_getsets, /* tp_getset */
135 DEFERRED_ADDRESS(&PyList_Type), /* tp_base */
136 0, /* tp_dict */
137 0, /* tp_descr_get */
138 0, /* tp_descr_set */
139 0, /* tp_dictoffset */
140 (initproc)spamlist_init, /* tp_init */
141 0, /* tp_alloc */
142 0, /* tp_new */
145 /* spamdict -- a dict subtype */
147 typedef struct {
148 PyDictObject dict;
149 int state;
150 } spamdictobject;
152 static PyObject *
153 spamdict_getstate(spamdictobject *self, PyObject *args)
155 if (!PyArg_ParseTuple(args, ":getstate"))
156 return NULL;
157 return PyInt_FromLong(self->state);
160 static PyObject *
161 spamdict_setstate(spamdictobject *self, PyObject *args)
163 int state;
165 if (!PyArg_ParseTuple(args, "i:setstate", &state))
166 return NULL;
167 self->state = state;
168 Py_INCREF(Py_None);
169 return Py_None;
172 static PyMethodDef spamdict_methods[] = {
173 {"getstate", (PyCFunction)spamdict_getstate, METH_VARARGS,
174 PyDoc_STR("getstate() -> state")},
175 {"setstate", (PyCFunction)spamdict_setstate, METH_VARARGS,
176 PyDoc_STR("setstate(state)")},
177 {NULL, NULL},
180 static int
181 spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)
183 if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
184 return -1;
185 self->state = 0;
186 return 0;
189 static PyMemberDef spamdict_members[] = {
190 {"state", T_INT, offsetof(spamdictobject, state), READONLY,
191 PyDoc_STR("an int variable for demonstration purposes")},
195 static PyTypeObject spamdict_type = {
196 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
198 "xxsubtype.spamdict",
199 sizeof(spamdictobject),
201 0, /* tp_dealloc */
202 0, /* tp_print */
203 0, /* tp_getattr */
204 0, /* tp_setattr */
205 0, /* tp_compare */
206 0, /* tp_repr */
207 0, /* tp_as_number */
208 0, /* tp_as_sequence */
209 0, /* tp_as_mapping */
210 0, /* tp_hash */
211 0, /* tp_call */
212 0, /* tp_str */
213 0, /* tp_getattro */
214 0, /* tp_setattro */
215 0, /* tp_as_buffer */
216 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
217 0, /* tp_doc */
218 0, /* tp_traverse */
219 0, /* tp_clear */
220 0, /* tp_richcompare */
221 0, /* tp_weaklistoffset */
222 0, /* tp_iter */
223 0, /* tp_iternext */
224 spamdict_methods, /* tp_methods */
225 spamdict_members, /* tp_members */
226 0, /* tp_getset */
227 DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */
228 0, /* tp_dict */
229 0, /* tp_descr_get */
230 0, /* tp_descr_set */
231 0, /* tp_dictoffset */
232 (initproc)spamdict_init, /* tp_init */
233 0, /* tp_alloc */
234 0, /* tp_new */
237 static PyObject *
238 spam_bench(PyObject *self, PyObject *args)
240 PyObject *obj, *name, *res;
241 int n = 1000;
242 time_t t0, t1;
244 if (!PyArg_ParseTuple(args, "OS|i", &obj, &name, &n))
245 return NULL;
246 t0 = clock();
247 while (--n >= 0) {
248 res = PyObject_GetAttr(obj, name);
249 if (res == NULL)
250 return NULL;
251 Py_DECREF(res);
253 t1 = clock();
254 return PyFloat_FromDouble((double)(t1-t0) / CLOCKS_PER_SEC);
257 static PyMethodDef xxsubtype_functions[] = {
258 {"bench", spam_bench, METH_VARARGS},
259 {NULL, NULL} /* sentinel */
262 PyMODINIT_FUNC
263 initxxsubtype(void)
265 PyObject *m;
267 /* Fill in deferred data addresses. This must be done before
268 PyType_Ready() is called. Note that PyType_Ready() automatically
269 initializes the ob.ob_type field to &PyType_Type if it's NULL,
270 so it's not necessary to fill in ob_type first. */
271 spamdict_type.tp_base = &PyDict_Type;
272 if (PyType_Ready(&spamdict_type) < 0)
273 return;
275 spamlist_type.tp_base = &PyList_Type;
276 if (PyType_Ready(&spamlist_type) < 0)
277 return;
279 m = Py_InitModule3("xxsubtype",
280 xxsubtype_functions,
281 xxsubtype__doc__);
282 if (m == NULL)
283 return;
285 if (PyType_Ready(&spamlist_type) < 0)
286 return;
287 if (PyType_Ready(&spamdict_type) < 0)
288 return;
290 Py_INCREF(&spamlist_type);
291 if (PyModule_AddObject(m, "spamlist",
292 (PyObject *) &spamlist_type) < 0)
293 return;
295 Py_INCREF(&spamdict_type);
296 if (PyModule_AddObject(m, "spamdict",
297 (PyObject *) &spamdict_type) < 0)
298 return;