/home/mdboom/Work/builds/cpython/Modules/xxsubtype.c
Line | Count | Source (jump to first uncovered line) |
1 | #include "Python.h" |
2 | #include "structmember.h" // PyMemberDef |
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")) Branch (29:9): [True: 0, False: 2]
|
30 | return NULL; |
31 | return PyLong_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)) Branch (39:9): [True: 0, False: 1]
|
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) { Branch (51:9): [True: 6, False: 0]
|
52 | if (self == NULL) Branch (52:13): [True: 2, False: 4]
|
53 | self = Py_None; |
54 | if (kw == NULL) Branch (54:13): [True: 0, False: 6]
|
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_CAST(spamlist_specialmeth), |
74 | METH_VARARGS | METH_KEYWORDS | METH_CLASS, |
75 | PyDoc_STR("classmeth(*args, **kw)")}, |
76 | {"staticmeth", _PyCFunction_CAST(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) Branch (85:9): [True: 0, False: 39]
|
86 | return -1; |
87 | self->state = 0; |
88 | return 0; |
89 | } |
90 | |
91 | static PyObject * |
92 | spamlist_state_get(spamlistobject *self, void *Py_UNUSED(ignored)) |
93 | { |
94 | return PyLong_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_vectorcall_offset */ |
110 | 0, /* tp_getattr */ |
111 | 0, /* tp_setattr */ |
112 | 0, /* tp_as_async */ |
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")) Branch (154:9): [True: 0, False: 2]
|
155 | return NULL; |
156 | return PyLong_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)) Branch (164:9): [True: 0, False: 1]
|
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) Branch (182:9): [True: 0, False: 12]
|
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_vectorcall_offset */ |
201 | 0, /* tp_getattr */ |
202 | 0, /* tp_setattr */ |
203 | 0, /* tp_as_async */ |
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 = 0, t1 = 0; |
241 |
|
242 | if (!PyArg_ParseTuple(args, "OU|i", &obj, &name, &n)) Branch (242:9): [True: 0, False: 0]
|
243 | return NULL; |
244 | #ifdef HAVE_CLOCK |
245 | t0 = clock(); |
246 | while (--n >= 0) { Branch (246:12): [True: 0, False: 0]
|
247 | res = PyObject_GetAttr(obj, name); |
248 | if (res == NULL) Branch (248:13): [True: 0, False: 0]
|
249 | return NULL; |
250 | Py_DECREF(res); |
251 | } |
252 | t1 = clock(); |
253 | #endif |
254 | return PyFloat_FromDouble((double)(t1-t0) / CLOCKS_PER_SEC); |
255 | } |
256 | |
257 | static PyMethodDef xxsubtype_functions[] = { |
258 | {"bench", spam_bench, METH_VARARGS}, |
259 | {NULL, NULL} /* sentinel */ |
260 | }; |
261 | |
262 | static int |
263 | xxsubtype_exec(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) Branch (270:9): [True: 0, False: 1]
|
271 | return -1; |
272 | |
273 | spamlist_type.tp_base = &PyList_Type; |
274 | if (PyType_Ready(&spamlist_type) < 0) Branch (274:9): [True: 0, False: 1]
|
275 | return -1; |
276 | |
277 | if (PyType_Ready(&spamlist_type) < 0) Branch (277:9): [True: 0, False: 1]
|
278 | return -1; |
279 | if (PyType_Ready(&spamdict_type) < 0) Branch (279:9): [True: 0, False: 1]
|
280 | return -1; |
281 | |
282 | Py_INCREF(&spamlist_type); |
283 | if (PyModule_AddObject(m, "spamlist", Branch (283:9): [True: 0, False: 1]
|
284 | (PyObject *) &spamlist_type) < 0) |
285 | return -1; |
286 | |
287 | Py_INCREF(&spamdict_type); |
288 | if (PyModule_AddObject(m, "spamdict", Branch (288:9): [True: 0, False: 1]
|
289 | (PyObject *) &spamdict_type) < 0) |
290 | return -1; |
291 | return 0; |
292 | } |
293 | |
294 | static struct PyModuleDef_Slot xxsubtype_slots[] = { |
295 | {Py_mod_exec, xxsubtype_exec}, |
296 | {0, NULL}, |
297 | }; |
298 | |
299 | static struct PyModuleDef xxsubtypemodule = { |
300 | PyModuleDef_HEAD_INIT, |
301 | "xxsubtype", |
302 | xxsubtype__doc__, |
303 | 0, |
304 | xxsubtype_functions, |
305 | xxsubtype_slots, |
306 | NULL, |
307 | NULL, |
308 | NULL |
309 | }; |
310 | |
311 | |
312 | PyMODINIT_FUNC |
313 | PyInit_xxsubtype(void) |
314 | { |
315 | return PyModuleDef_Init(&xxsubtypemodule); |
316 | } |