Python-2.7.3/Modules/xxsubtype.c

No issues found

  1 #include "Python.h"
  2 #include "structmember.h"
  3 
  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.");
  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 
 21 typedef struct {
 22     PyListObject list;
 23     int state;
 24 } spamlistobject;
 25 
 26 static PyObject *
 27 spamlist_getstate(spamlistobject *self, PyObject *args)
 28 {
 29     if (!PyArg_ParseTuple(args, ":getstate"))
 30         return NULL;
 31     return PyInt_FromLong(self->state);
 32 }
 33 
 34 static PyObject *
 35 spamlist_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 
 46 static PyObject *
 47 spamlist_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 
 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},
 80 };
 81 
 82 static int
 83 spamlist_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 
 91 static PyObject *
 92 spamlist_state_get(spamlistobject *self)
 93 {
 94     return PyInt_FromLong(self->state);
 95 }
 96 
 97 static PyGetSetDef spamlist_getsets[] = {
 98     {"state", (getter)spamlist_state_get, NULL,
 99      PyDoc_STR("an int variable for demonstration purposes")},
100     {0}
101 };
102 
103 static 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 
146 typedef struct {
147     PyDictObject dict;
148     int state;
149 } spamdictobject;
150 
151 static PyObject *
152 spamdict_getstate(spamdictobject *self, PyObject *args)
153 {
154     if (!PyArg_ParseTuple(args, ":getstate"))
155         return NULL;
156     return PyInt_FromLong(self->state);
157 }
158 
159 static PyObject *
160 spamdict_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 
171 static 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 
179 static int
180 spamdict_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 
188 static PyMemberDef spamdict_members[] = {
189     {"state", T_INT, offsetof(spamdictobject, state), READONLY,
190      PyDoc_STR("an int variable for demonstration purposes")},
191     {0}
192 };
193 
194 static 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 
235 static PyObject *
236 spam_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 
255 static PyMethodDef xxsubtype_functions[] = {
256     {"bench",           spam_bench,     METH_VARARGS},
257     {NULL,              NULL}           /* sentinel */
258 };
259 
260 PyMODINIT_FUNC
261 initxxsubtype(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 }