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 */
27 spamlist_getstate(spamlistobject
*self
, PyObject
*args
)
29 if (!PyArg_ParseTuple(args
, ":getstate"))
31 return PyInt_FromLong(self
->state
);
35 spamlist_setstate(spamlistobject
*self
, PyObject
*args
)
39 if (!PyArg_ParseTuple(args
, "i:setstate", &state
))
47 spamlist_specialmeth(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
49 PyObject
*result
= PyTuple_New(3);
57 PyTuple_SET_ITEM(result
, 0, self
);
59 PyTuple_SET_ITEM(result
, 1, args
);
61 PyTuple_SET_ITEM(result
, 2, kw
);
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)")},
83 spamlist_init(spamlistobject
*self
, PyObject
*args
, PyObject
*kwds
)
85 if (PyList_Type
.tp_init((PyObject
*)self
, args
, kwds
) < 0)
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
),
115 0, /* tp_as_number */
116 0, /* tp_as_sequence */
117 0, /* tp_as_mapping */
123 0, /* tp_as_buffer */
124 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
128 0, /* tp_richcompare */
129 0, /* tp_weaklistoffset */
132 spamlist_methods
, /* tp_methods */
134 spamlist_getsets
, /* tp_getset */
135 DEFERRED_ADDRESS(&PyList_Type
), /* tp_base */
137 0, /* tp_descr_get */
138 0, /* tp_descr_set */
139 0, /* tp_dictoffset */
140 (initproc
)spamlist_init
, /* tp_init */
145 /* spamdict -- a dict subtype */
153 spamdict_getstate(spamdictobject
*self
, PyObject
*args
)
155 if (!PyArg_ParseTuple(args
, ":getstate"))
157 return PyInt_FromLong(self
->state
);
161 spamdict_setstate(spamdictobject
*self
, PyObject
*args
)
165 if (!PyArg_ParseTuple(args
, "i:setstate", &state
))
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)")},
181 spamdict_init(spamdictobject
*self
, PyObject
*args
, PyObject
*kwds
)
183 if (PyDict_Type
.tp_init((PyObject
*)self
, args
, kwds
) < 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
),
207 0, /* tp_as_number */
208 0, /* tp_as_sequence */
209 0, /* tp_as_mapping */
215 0, /* tp_as_buffer */
216 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
220 0, /* tp_richcompare */
221 0, /* tp_weaklistoffset */
224 spamdict_methods
, /* tp_methods */
225 spamdict_members
, /* tp_members */
227 DEFERRED_ADDRESS(&PyDict_Type
), /* tp_base */
229 0, /* tp_descr_get */
230 0, /* tp_descr_set */
231 0, /* tp_dictoffset */
232 (initproc
)spamdict_init
, /* tp_init */
238 spam_bench(PyObject
*self
, PyObject
*args
)
240 PyObject
*obj
, *name
, *res
;
244 if (!PyArg_ParseTuple(args
, "OS|i", &obj
, &name
, &n
))
248 res
= PyObject_GetAttr(obj
, name
);
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 */
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)
275 spamlist_type
.tp_base
= &PyList_Type
;
276 if (PyType_Ready(&spamlist_type
) < 0)
279 m
= Py_InitModule3("xxsubtype",
285 if (PyType_Ready(&spamlist_type
) < 0)
287 if (PyType_Ready(&spamdict_type
) < 0)
290 Py_INCREF(&spamlist_type
);
291 if (PyModule_AddObject(m
, "spamlist",
292 (PyObject
*) &spamlist_type
) < 0)
295 Py_INCREF(&spamdict_type
);
296 if (PyModule_AddObject(m
, "spamdict",
297 (PyObject
*) &spamdict_type
) < 0)