PageRenderTime 355ms CodeModel.GetById 141ms app.highlight 19ms RepoModel.GetById 122ms app.codeStats 0ms

/Modules/xxsubtype.c

http://unladen-swallow.googlecode.com/
C | 297 lines | 249 code | 33 blank | 15 comment | 24 complexity | 7acbd3f69b7dfc23a539c1e546f5040d MD5 | raw file
  1#include "Python.h"
  2#include "structmember.h"
  3
  4PyDoc_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.");
  9
 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.
 16*/
 17#define DEFERRED_ADDRESS(ADDR) 0
 18
 19/* 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
 46static 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
 66static 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},
 80};
 81
 82static int
 83spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)
 84{
 85	if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0)
 86		return -1;
 87	self->state = 0;
 88	return 0;
 89}
 90
 91static PyObject *
 92spamlist_state_get(spamlistobject *self)
 93{
 94	return PyInt_FromLong(self->state);
 95}
 96
 97static PyGetSetDef spamlist_getsets[] = {
 98	{"state", (getter)spamlist_state_get, NULL,
 99	 PyDoc_STR("an int variable for demonstration purposes")},
100	{0}
101};
102
103static PyTypeObject spamlist_type = {
104	PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
105	"xxsubtype.spamlist",
106	sizeof(spamlistobject),
107	0,
108	0,					/* tp_dealloc */
109	0,					/* tp_print */
110	0,					/* tp_getattr */
111	0,					/* tp_setattr */
112	0,					/* tp_compare */
113	0,					/* tp_repr */
114	0,					/* tp_as_number */
115	0,					/* tp_as_sequence */
116	0,					/* tp_as_mapping */
117	0,					/* tp_hash */
118	0,					/* tp_call */
119	0,					/* tp_str */
120	0,					/* tp_getattro */
121	0,					/* tp_setattro */
122	0,					/* tp_as_buffer */
123	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
124	0,					/* tp_doc */
125	0,					/* tp_traverse */
126	0,					/* tp_clear */
127	0,					/* tp_richcompare */
128	0,					/* tp_weaklistoffset */
129	0,					/* tp_iter */
130	0,					/* tp_iternext */
131	spamlist_methods,			/* tp_methods */
132	0,					/* tp_members */
133	spamlist_getsets,			/* tp_getset */
134	DEFERRED_ADDRESS(&PyList_Type),		/* tp_base */
135	0,					/* tp_dict */
136	0,					/* tp_descr_get */
137	0,					/* tp_descr_set */
138	0,					/* tp_dictoffset */
139	(initproc)spamlist_init,		/* tp_init */
140	0,					/* tp_alloc */
141	0,					/* tp_new */
142};
143
144/* spamdict -- a dict subtype */
145
146typedef struct {
147	PyDictObject dict;
148	int state;
149} spamdictobject;
150
151static PyObject *
152spamdict_getstate(spamdictobject *self, PyObject *args)
153{
154	if (!PyArg_ParseTuple(args, ":getstate"))
155		return NULL;
156	return PyInt_FromLong(self->state);
157}
158
159static PyObject *
160spamdict_setstate(spamdictobject *self, PyObject *args)
161{
162	int state;
163
164	if (!PyArg_ParseTuple(args, "i:setstate", &state))
165		return NULL;
166	self->state = state;
167	Py_INCREF(Py_None);
168	return Py_None;
169}
170
171static PyMethodDef spamdict_methods[] = {
172	{"getstate", (PyCFunction)spamdict_getstate, METH_VARARGS,
173	 	PyDoc_STR("getstate() -> state")},
174	{"setstate", (PyCFunction)spamdict_setstate, METH_VARARGS,
175	 	PyDoc_STR("setstate(state)")},
176	{NULL,	NULL},
177};
178
179static int
180spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)
181{
182	if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
183		return -1;
184	self->state = 0;
185	return 0;
186}
187
188static PyMemberDef spamdict_members[] = {
189	{"state", T_INT, offsetof(spamdictobject, state), READONLY,
190	 PyDoc_STR("an int variable for demonstration purposes")},
191	{0}
192};
193
194static PyTypeObject spamdict_type = {
195	PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
196	"xxsubtype.spamdict",
197	sizeof(spamdictobject),
198	0,
199	0,					/* tp_dealloc */
200	0,					/* tp_print */
201	0,					/* tp_getattr */
202	0,					/* tp_setattr */
203	0,					/* tp_compare */
204	0,					/* tp_repr */
205	0,					/* tp_as_number */
206	0,					/* tp_as_sequence */
207	0,					/* tp_as_mapping */
208	0,					/* tp_hash */
209	0,					/* tp_call */
210	0,					/* tp_str */
211	0,					/* tp_getattro */
212	0,					/* tp_setattro */
213	0,					/* tp_as_buffer */
214	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
215	0,					/* tp_doc */
216	0,					/* tp_traverse */
217	0,					/* tp_clear */
218	0,					/* tp_richcompare */
219	0,					/* tp_weaklistoffset */
220	0,					/* tp_iter */
221	0,					/* tp_iternext */
222	spamdict_methods,			/* tp_methods */
223	spamdict_members,			/* tp_members */
224	0,					/* tp_getset */
225	DEFERRED_ADDRESS(&PyDict_Type),		/* tp_base */
226	0,					/* tp_dict */
227	0,					/* tp_descr_get */
228	0,					/* tp_descr_set */
229	0,					/* tp_dictoffset */
230	(initproc)spamdict_init,		/* tp_init */
231	0,					/* tp_alloc */
232	0,					/* tp_new */
233};
234
235static PyObject *
236spam_bench(PyObject *self, PyObject *args)
237{
238	PyObject *obj, *name, *res;
239	int n = 1000;
240	time_t t0, t1;
241
242	if (!PyArg_ParseTuple(args, "OS|i", &obj, &name, &n))
243		return NULL;
244	t0 = clock();
245	while (--n >= 0) {
246		res = PyObject_GetAttr(obj, name);
247		if (res == NULL)
248			return NULL;
249		Py_DECREF(res);
250	}
251	t1 = clock();
252	return PyFloat_FromDouble((double)(t1-t0) / CLOCKS_PER_SEC);
253}
254
255static PyMethodDef xxsubtype_functions[] = {
256	{"bench",	spam_bench, 	METH_VARARGS},
257	{NULL,		NULL}		/* sentinel */
258};
259
260PyMODINIT_FUNC
261initxxsubtype(void)
262{
263	PyObject *m;
264
265	/* Fill in deferred data addresses.  This must be done before
266	   PyType_Ready() is called.  Note that PyType_Ready() automatically
267	   initializes the ob.ob_type field to &PyType_Type if it's NULL,
268	   so it's not necessary to fill in ob_type first. */
269	spamdict_type.tp_base = &PyDict_Type;
270	if (PyType_Ready(&spamdict_type) < 0)
271		return;
272
273	spamlist_type.tp_base = &PyList_Type;
274	if (PyType_Ready(&spamlist_type) < 0)
275		return;
276
277	m = Py_InitModule3("xxsubtype",
278			   xxsubtype_functions,
279			   xxsubtype__doc__);
280	if (m == NULL)
281		return;
282
283	if (PyType_Ready(&spamlist_type) < 0)
284		return;
285	if (PyType_Ready(&spamdict_type) < 0)
286		return;
287
288	Py_INCREF(&spamlist_type);
289	if (PyModule_AddObject(m, "spamlist",
290			       (PyObject *) &spamlist_type) < 0)
291		return;
292
293	Py_INCREF(&spamdict_type);
294	if (PyModule_AddObject(m, "spamdict",
295			       (PyObject *) &spamdict_type) < 0)
296		return;
297}