Branch data Line data Source code
1 : : /* Implementation helper: a struct that looks like a tuple.
2 : : See timemodule and posixmodule for example uses.
3 : :
4 : : The structseq helper is considered an internal CPython implementation
5 : : detail. Docs for modules using structseqs should call them
6 : : "named tuples" (be sure to include a space between the two
7 : : words and add a link back to the term in Docs/glossary.rst).
8 : : */
9 : :
10 : : #include "Python.h"
11 : : #include "pycore_tuple.h" // _PyTuple_FromArray()
12 : : #include "pycore_object.h" // _PyObject_GC_TRACK()
13 : : #include "structmember.h" // PyMemberDef
14 : : #include "pycore_structseq.h" // PyStructSequence_InitType()
15 : : #include "pycore_initconfig.h" // _PyStatus_OK()
16 : :
17 : : static const char visible_length_key[] = "n_sequence_fields";
18 : : static const char real_length_key[] = "n_fields";
19 : : static const char unnamed_fields_key[] = "n_unnamed_fields";
20 : : static const char match_args_key[] = "__match_args__";
21 : :
22 : : /* Fields with this name have only a field index, not a field name.
23 : : They are only allowed for indices < n_visible_fields. */
24 : : const char * const PyStructSequence_UnnamedField = "unnamed field";
25 : :
26 : : static Py_ssize_t
27 : 8949 : get_type_attr_as_size(PyTypeObject *tp, PyObject *name)
28 : : {
29 : 8949 : PyObject *v = PyDict_GetItemWithError(tp->tp_dict, name);
30 [ - + - - ]: 8949 : if (v == NULL && !PyErr_Occurred()) {
31 : 0 : PyErr_Format(PyExc_TypeError,
32 : : "Missed attribute '%U' of type %s",
33 : : name, tp->tp_name);
34 : : }
35 : 8949 : return PyLong_AsSsize_t(v);
36 : : }
37 : :
38 : : #define VISIBLE_SIZE(op) Py_SIZE(op)
39 : : #define VISIBLE_SIZE_TP(tp) \
40 : : get_type_attr_as_size(tp, &_Py_ID(n_sequence_fields))
41 : : #define REAL_SIZE_TP(tp) \
42 : : get_type_attr_as_size(tp, &_Py_ID(n_fields))
43 : : #define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op))
44 : :
45 : : #define UNNAMED_FIELDS_TP(tp) \
46 : : get_type_attr_as_size(tp, &_Py_ID(n_unnamed_fields))
47 : : #define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op))
48 : :
49 : :
50 : : PyObject *
51 : 2981 : PyStructSequence_New(PyTypeObject *type)
52 : : {
53 : : PyStructSequence *obj;
54 : 2981 : Py_ssize_t size = REAL_SIZE_TP(type), i;
55 [ - + ]: 2981 : if (size < 0) {
56 : 0 : return NULL;
57 : : }
58 : 2981 : Py_ssize_t vsize = VISIBLE_SIZE_TP(type);
59 [ - + ]: 2981 : if (vsize < 0) {
60 : 0 : return NULL;
61 : : }
62 : :
63 : 2981 : obj = PyObject_GC_NewVar(PyStructSequence, type, size);
64 [ - + ]: 2981 : if (obj == NULL)
65 : 0 : return NULL;
66 : : /* Hack the size of the variable object, so invisible fields don't appear
67 : : to Python code. */
68 : 2981 : Py_SET_SIZE(obj, vsize);
69 [ + + ]: 57366 : for (i = 0; i < size; i++)
70 : 54385 : obj->ob_item[i] = NULL;
71 : :
72 : 2981 : return (PyObject*)obj;
73 : : }
74 : :
75 : : void
76 : 0 : PyStructSequence_SetItem(PyObject* op, Py_ssize_t i, PyObject* v)
77 : : {
78 : 0 : PyStructSequence_SET_ITEM(op, i, v);
79 : 0 : }
80 : :
81 : : PyObject*
82 : 0 : PyStructSequence_GetItem(PyObject* op, Py_ssize_t i)
83 : : {
84 : 0 : return PyStructSequence_GET_ITEM(op, i);
85 : : }
86 : :
87 : :
88 : : static int
89 : 0 : structseq_traverse(PyStructSequence *obj, visitproc visit, void *arg)
90 : : {
91 [ # # ]: 0 : if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HEAPTYPE) {
92 [ # # # # ]: 0 : Py_VISIT(Py_TYPE(obj));
93 : : }
94 : : Py_ssize_t i, size;
95 : 0 : size = REAL_SIZE(obj);
96 [ # # ]: 0 : for (i = 0; i < size; ++i) {
97 [ # # # # ]: 0 : Py_VISIT(obj->ob_item[i]);
98 : : }
99 : 0 : return 0;
100 : : }
101 : :
102 : : static void
103 : 2957 : structseq_dealloc(PyStructSequence *obj)
104 : : {
105 : : Py_ssize_t i, size;
106 : 2957 : PyObject_GC_UnTrack(obj);
107 : :
108 : 2957 : PyTypeObject *tp = Py_TYPE(obj);
109 : 2957 : size = REAL_SIZE(obj);
110 [ + + ]: 57142 : for (i = 0; i < size; ++i) {
111 : 54185 : Py_XDECREF(obj->ob_item[i]);
112 : : }
113 : 2957 : PyObject_GC_Del(obj);
114 [ + + ]: 2957 : if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
115 : 2807 : Py_DECREF(tp);
116 : : }
117 : 2957 : }
118 : :
119 : : /*[clinic input]
120 : : class structseq "PyStructSequence *" "NULL"
121 : : [clinic start generated code]*/
122 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d781c6922c77752]*/
123 : :
124 : : #include "clinic/structseq.c.h"
125 : :
126 : : /*[clinic input]
127 : : @classmethod
128 : : structseq.__new__ as structseq_new
129 : : sequence as arg: object
130 : : dict: object(c_default="NULL") = {}
131 : : [clinic start generated code]*/
132 : :
133 : : static PyObject *
134 : 10 : structseq_new_impl(PyTypeObject *type, PyObject *arg, PyObject *dict)
135 : : /*[clinic end generated code: output=baa082e788b171da input=90532511101aa3fb]*/
136 : : {
137 : : PyObject *ob;
138 : 10 : PyStructSequence *res = NULL;
139 : : Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;
140 : :
141 : 10 : min_len = VISIBLE_SIZE_TP(type);
142 [ - + ]: 10 : if (min_len < 0) {
143 : 0 : return NULL;
144 : : }
145 : 10 : max_len = REAL_SIZE_TP(type);
146 [ - + ]: 10 : if (max_len < 0) {
147 : 0 : return NULL;
148 : : }
149 : 10 : n_unnamed_fields = UNNAMED_FIELDS_TP(type);
150 [ - + ]: 10 : if (n_unnamed_fields < 0) {
151 : 0 : return NULL;
152 : : }
153 : :
154 : 10 : arg = PySequence_Fast(arg, "constructor requires a sequence");
155 : :
156 [ - + ]: 10 : if (!arg) {
157 : 0 : return NULL;
158 : : }
159 : :
160 [ - + - - ]: 10 : if (dict && !PyDict_Check(dict)) {
161 : 0 : PyErr_Format(PyExc_TypeError,
162 : : "%.500s() takes a dict as second arg, if any",
163 : : type->tp_name);
164 : 0 : Py_DECREF(arg);
165 : 0 : return NULL;
166 : : }
167 : :
168 [ - + ]: 10 : len = PySequence_Fast_GET_SIZE(arg);
169 [ - + ]: 10 : if (min_len != max_len) {
170 [ # # ]: 0 : if (len < min_len) {
171 : 0 : PyErr_Format(PyExc_TypeError,
172 : : "%.500s() takes an at least %zd-sequence (%zd-sequence given)",
173 : : type->tp_name, min_len, len);
174 : 0 : Py_DECREF(arg);
175 : 0 : return NULL;
176 : : }
177 : :
178 [ # # ]: 0 : if (len > max_len) {
179 : 0 : PyErr_Format(PyExc_TypeError,
180 : : "%.500s() takes an at most %zd-sequence (%zd-sequence given)",
181 : : type->tp_name, max_len, len);
182 : 0 : Py_DECREF(arg);
183 : 0 : return NULL;
184 : : }
185 : : }
186 : : else {
187 [ - + ]: 10 : if (len != min_len) {
188 : 0 : PyErr_Format(PyExc_TypeError,
189 : : "%.500s() takes a %zd-sequence (%zd-sequence given)",
190 : : type->tp_name, min_len, len);
191 : 0 : Py_DECREF(arg);
192 : 0 : return NULL;
193 : : }
194 : : }
195 : :
196 : 10 : res = (PyStructSequence*) PyStructSequence_New(type);
197 [ - + ]: 10 : if (res == NULL) {
198 : 0 : Py_DECREF(arg);
199 : 0 : return NULL;
200 : : }
201 [ + + ]: 30 : for (i = 0; i < len; ++i) {
202 [ - + ]: 20 : PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
203 : 20 : res->ob_item[i] = Py_NewRef(v);
204 : : }
205 : 10 : Py_DECREF(arg);
206 [ - + ]: 10 : for (; i < max_len; ++i) {
207 [ # # ]: 0 : if (dict == NULL) {
208 : 0 : ob = Py_None;
209 : : }
210 : : else {
211 : 0 : ob = _PyDict_GetItemStringWithError(dict,
212 : 0 : type->tp_members[i-n_unnamed_fields].name);
213 [ # # ]: 0 : if (ob == NULL) {
214 [ # # ]: 0 : if (PyErr_Occurred()) {
215 : 0 : Py_DECREF(res);
216 : 0 : return NULL;
217 : : }
218 : 0 : ob = Py_None;
219 : : }
220 : : }
221 : 0 : res->ob_item[i] = Py_NewRef(ob);
222 : : }
223 : :
224 : 10 : _PyObject_GC_TRACK(res);
225 : 10 : return (PyObject*) res;
226 : : }
227 : :
228 : :
229 : : static PyObject *
230 : 0 : structseq_repr(PyStructSequence *obj)
231 : : {
232 : 0 : PyTypeObject *typ = Py_TYPE(obj);
233 : : _PyUnicodeWriter writer;
234 : :
235 : : /* Write "typename(" */
236 : 0 : PyObject *type_name = PyUnicode_DecodeUTF8(typ->tp_name,
237 : 0 : strlen(typ->tp_name),
238 : : NULL);
239 [ # # ]: 0 : if (type_name == NULL) {
240 : 0 : return NULL;
241 : : }
242 : :
243 : 0 : _PyUnicodeWriter_Init(&writer);
244 : 0 : writer.overallocate = 1;
245 : : /* count 5 characters per item: "x=1, " */
246 : 0 : writer.min_length = (PyUnicode_GET_LENGTH(type_name) + 1
247 : 0 : + VISIBLE_SIZE(obj) * 5 + 1);
248 : :
249 [ # # ]: 0 : if (_PyUnicodeWriter_WriteStr(&writer, type_name) < 0) {
250 : 0 : Py_DECREF(type_name);
251 : 0 : goto error;
252 : : }
253 : 0 : Py_DECREF(type_name);
254 : :
255 [ # # ]: 0 : if (_PyUnicodeWriter_WriteChar(&writer, '(') < 0) {
256 : 0 : goto error;
257 : : }
258 : :
259 [ # # ]: 0 : for (Py_ssize_t i=0; i < VISIBLE_SIZE(obj); i++) {
260 [ # # ]: 0 : if (i > 0) {
261 : : /* Write ", " */
262 [ # # ]: 0 : if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
263 : 0 : goto error;
264 : : }
265 : : }
266 : :
267 : : /* Write "name=repr" */
268 : 0 : const char *name_utf8 = typ->tp_members[i].name;
269 [ # # ]: 0 : if (name_utf8 == NULL) {
270 : 0 : PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %zd name is NULL"
271 : : " for type %.500s", i, typ->tp_name);
272 : 0 : goto error;
273 : : }
274 : :
275 : 0 : PyObject *name = PyUnicode_DecodeUTF8(name_utf8, strlen(name_utf8), NULL);
276 [ # # ]: 0 : if (name == NULL) {
277 : 0 : goto error;
278 : : }
279 [ # # ]: 0 : if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) {
280 : 0 : Py_DECREF(name);
281 : 0 : goto error;
282 : : }
283 : 0 : Py_DECREF(name);
284 : :
285 [ # # ]: 0 : if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) {
286 : 0 : goto error;
287 : : }
288 : :
289 : 0 : PyObject *value = PyStructSequence_GET_ITEM(obj, i);
290 : : assert(value != NULL);
291 : 0 : PyObject *repr = PyObject_Repr(value);
292 [ # # ]: 0 : if (repr == NULL) {
293 : 0 : goto error;
294 : : }
295 [ # # ]: 0 : if (_PyUnicodeWriter_WriteStr(&writer, repr) < 0) {
296 : 0 : Py_DECREF(repr);
297 : 0 : goto error;
298 : : }
299 : 0 : Py_DECREF(repr);
300 : : }
301 : :
302 [ # # ]: 0 : if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) {
303 : 0 : goto error;
304 : : }
305 : :
306 : 0 : return _PyUnicodeWriter_Finish(&writer);
307 : :
308 : 0 : error:
309 : 0 : _PyUnicodeWriter_Dealloc(&writer);
310 : 0 : return NULL;
311 : : }
312 : :
313 : :
314 : : static PyObject *
315 : 0 : structseq_reduce(PyStructSequence* self, PyObject *Py_UNUSED(ignored))
316 : : {
317 : 0 : PyObject* tup = NULL;
318 : 0 : PyObject* dict = NULL;
319 : : PyObject* result;
320 : : Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields, i;
321 : :
322 : 0 : n_fields = REAL_SIZE(self);
323 [ # # ]: 0 : if (n_fields < 0) {
324 : 0 : return NULL;
325 : : }
326 : 0 : n_visible_fields = VISIBLE_SIZE(self);
327 : 0 : n_unnamed_fields = UNNAMED_FIELDS(self);
328 [ # # ]: 0 : if (n_unnamed_fields < 0) {
329 : 0 : return NULL;
330 : : }
331 : 0 : tup = _PyTuple_FromArray(self->ob_item, n_visible_fields);
332 [ # # ]: 0 : if (!tup)
333 : 0 : goto error;
334 : :
335 : 0 : dict = PyDict_New();
336 [ # # ]: 0 : if (!dict)
337 : 0 : goto error;
338 : :
339 [ # # ]: 0 : for (i = n_visible_fields; i < n_fields; i++) {
340 : 0 : const char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
341 [ # # ]: 0 : if (PyDict_SetItemString(dict, n, self->ob_item[i]) < 0)
342 : 0 : goto error;
343 : : }
344 : :
345 : 0 : result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict);
346 : :
347 : 0 : Py_DECREF(tup);
348 : 0 : Py_DECREF(dict);
349 : :
350 : 0 : return result;
351 : :
352 : 0 : error:
353 : 0 : Py_XDECREF(tup);
354 : 0 : Py_XDECREF(dict);
355 : 0 : return NULL;
356 : : }
357 : :
358 : : static PyMethodDef structseq_methods[] = {
359 : : {"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL},
360 : : {NULL, NULL}
361 : : };
362 : :
363 : : static Py_ssize_t
364 : 479 : count_members(PyStructSequence_Desc *desc, Py_ssize_t *n_unnamed_members) {
365 : : Py_ssize_t i;
366 : :
367 : 479 : *n_unnamed_members = 0;
368 [ + + ]: 3873 : for (i = 0; desc->fields[i].name != NULL; ++i) {
369 [ + + ]: 3394 : if (desc->fields[i].name == PyStructSequence_UnnamedField) {
370 : 78 : (*n_unnamed_members)++;
371 : : }
372 : : }
373 : 479 : return i;
374 : : }
375 : :
376 : : static int
377 : 479 : initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict,
378 : : Py_ssize_t n_members, Py_ssize_t n_unnamed_members) {
379 : : PyObject *v;
380 : :
381 : : #define SET_DICT_FROM_SIZE(key, value) \
382 : : do { \
383 : : v = PyLong_FromSsize_t(value); \
384 : : if (v == NULL) { \
385 : : return -1; \
386 : : } \
387 : : if (PyDict_SetItemString(dict, key, v) < 0) { \
388 : : Py_DECREF(v); \
389 : : return -1; \
390 : : } \
391 : : Py_DECREF(v); \
392 : : } while (0)
393 : :
394 [ - + - + ]: 479 : SET_DICT_FROM_SIZE(visible_length_key, desc->n_in_sequence);
395 [ - + - + ]: 479 : SET_DICT_FROM_SIZE(real_length_key, n_members);
396 [ - + - + ]: 479 : SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members);
397 : :
398 : : // Prepare and set __match_args__
399 : : Py_ssize_t i, k;
400 : 479 : PyObject* keys = PyTuple_New(desc->n_in_sequence);
401 [ - + ]: 479 : if (keys == NULL) {
402 : 0 : return -1;
403 : : }
404 : :
405 [ + + ]: 3559 : for (i = k = 0; i < desc->n_in_sequence; ++i) {
406 [ + + ]: 3080 : if (desc->fields[i].name == PyStructSequence_UnnamedField) {
407 : 78 : continue;
408 : : }
409 : 3002 : PyObject* new_member = PyUnicode_FromString(desc->fields[i].name);
410 [ - + ]: 3002 : if (new_member == NULL) {
411 : 0 : goto error;
412 : : }
413 : 3002 : PyTuple_SET_ITEM(keys, k, new_member);
414 : 3002 : k++;
415 : : }
416 : :
417 [ - + ]: 479 : if (_PyTuple_Resize(&keys, k) == -1) {
418 : 0 : goto error;
419 : : }
420 : :
421 [ - + ]: 479 : if (PyDict_SetItemString(dict, match_args_key, keys) < 0) {
422 : 0 : goto error;
423 : : }
424 : :
425 : 479 : Py_DECREF(keys);
426 : 479 : return 0;
427 : :
428 : 0 : error:
429 : 0 : Py_DECREF(keys);
430 : 0 : return -1;
431 : : }
432 : :
433 : : static PyMemberDef *
434 : 479 : initialize_members(PyStructSequence_Desc *desc,
435 : : Py_ssize_t *pn_members, Py_ssize_t *pn_unnamed_members)
436 : : {
437 : : PyMemberDef *members;
438 : : Py_ssize_t n_members, n_unnamed_members;
439 : :
440 : 479 : n_members = count_members(desc, &n_unnamed_members);
441 [ + - ]: 479 : members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1);
442 [ - + ]: 479 : if (members == NULL) {
443 : 0 : PyErr_NoMemory();
444 : 0 : return NULL;
445 : : }
446 : :
447 : : Py_ssize_t i, k;
448 [ + + ]: 3873 : for (i = k = 0; i < n_members; ++i) {
449 [ + + ]: 3394 : if (desc->fields[i].name == PyStructSequence_UnnamedField) {
450 : 78 : continue;
451 : : }
452 : :
453 : : /* The names and docstrings in these MemberDefs are statically */
454 : : /* allocated so it is expected that they'll outlive the MemberDef */
455 : 3316 : members[k].name = desc->fields[i].name;
456 : 3316 : members[k].type = T_OBJECT;
457 : 3316 : members[k].offset = offsetof(PyStructSequence, ob_item)
458 : 3316 : + i * sizeof(PyObject*);
459 : 3316 : members[k].flags = READONLY;
460 : 3316 : members[k].doc = desc->fields[i].doc;
461 : 3316 : k++;
462 : : }
463 : 479 : members[k].name = NULL;
464 : :
465 : 479 : *pn_members = n_members;
466 : 479 : *pn_unnamed_members = n_unnamed_members;
467 : 479 : return members;
468 : : }
469 : :
470 : :
471 : : static void
472 : 232 : initialize_static_fields(PyTypeObject *type, PyStructSequence_Desc *desc,
473 : : PyMemberDef *tp_members, unsigned long tp_flags)
474 : : {
475 : 232 : type->tp_name = desc->name;
476 : 232 : type->tp_basicsize = sizeof(PyStructSequence) - sizeof(PyObject *);
477 : 232 : type->tp_itemsize = sizeof(PyObject *);
478 : 232 : type->tp_dealloc = (destructor)structseq_dealloc;
479 : 232 : type->tp_repr = (reprfunc)structseq_repr;
480 : 232 : type->tp_doc = desc->doc;
481 : 232 : type->tp_base = &PyTuple_Type;
482 : 232 : type->tp_methods = structseq_methods;
483 : 232 : type->tp_new = structseq_new;
484 : 232 : type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags;
485 : 232 : type->tp_traverse = (traverseproc) structseq_traverse;
486 : 232 : type->tp_members = tp_members;
487 : 232 : }
488 : :
489 : : static int
490 : 232 : initialize_static_type(PyTypeObject *type, PyStructSequence_Desc *desc,
491 : : Py_ssize_t n_members, Py_ssize_t n_unnamed_members) {
492 : : /* initialize_static_fields() should have been called already. */
493 [ - + ]: 232 : if (PyType_Ready(type) < 0) {
494 : 0 : return -1;
495 : : }
496 : 232 : Py_INCREF(type);
497 : :
498 [ - + ]: 232 : if (initialize_structseq_dict(
499 : : desc, type->tp_dict, n_members, n_unnamed_members) < 0) {
500 : 0 : Py_DECREF(type);
501 : 0 : return -1;
502 : : }
503 : :
504 : 232 : return 0;
505 : : }
506 : :
507 : : int
508 : 232 : _PyStructSequence_InitBuiltinWithFlags(PyTypeObject *type,
509 : : PyStructSequence_Desc *desc,
510 : : unsigned long tp_flags)
511 : : {
512 : : PyMemberDef *members;
513 : : Py_ssize_t n_members, n_unnamed_members;
514 : :
515 : 232 : members = initialize_members(desc, &n_members, &n_unnamed_members);
516 [ - + ]: 232 : if (members == NULL) {
517 : 0 : return -1;
518 : : }
519 : 232 : initialize_static_fields(type, desc, members, tp_flags);
520 [ - + ]: 232 : if (_PyStaticType_InitBuiltin(type) < 0) {
521 : 0 : PyMem_Free(members);
522 : 0 : PyErr_Format(PyExc_RuntimeError,
523 : : "Can't initialize builtin type %s",
524 : : desc->name);
525 : 0 : return -1;
526 : : }
527 [ - + ]: 232 : if (initialize_static_type(type, desc, n_members, n_unnamed_members) < 0) {
528 : 0 : PyMem_Free(members);
529 : 0 : return -1;
530 : : }
531 : 232 : return 0;
532 : : }
533 : :
534 : : int
535 : 0 : PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc)
536 : : {
537 : : PyMemberDef *members;
538 : : Py_ssize_t n_members, n_unnamed_members;
539 : :
540 : : #ifdef Py_TRACE_REFS
541 : : /* if the type object was chained, unchain it first
542 : : before overwriting its storage */
543 : : if (type->ob_base.ob_base._ob_next) {
544 : : _Py_ForgetReference((PyObject *)type);
545 : : }
546 : : #endif
547 : :
548 : : /* PyTypeObject has already been initialized */
549 [ # # ]: 0 : if (Py_REFCNT(type) != 0) {
550 : 0 : PyErr_BadInternalCall();
551 : 0 : return -1;
552 : : }
553 : :
554 : 0 : members = initialize_members(desc, &n_members, &n_unnamed_members);
555 [ # # ]: 0 : if (members == NULL) {
556 : 0 : return -1;
557 : : }
558 : 0 : initialize_static_fields(type, desc, members, 0);
559 [ # # ]: 0 : if (initialize_static_type(type, desc, n_members, n_unnamed_members) < 0) {
560 : 0 : PyMem_Free(members);
561 : 0 : return -1;
562 : : }
563 : 0 : return 0;
564 : : }
565 : :
566 : : void
567 : 0 : PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
568 : : {
569 : 0 : (void)PyStructSequence_InitType2(type, desc);
570 : 0 : }
571 : :
572 : :
573 : : void
574 : 200 : _PyStructSequence_FiniType(PyTypeObject *type)
575 : : {
576 : : // Ensure that the type is initialized
577 : : assert(type->tp_name != NULL);
578 : : assert(type->tp_base == &PyTuple_Type);
579 : :
580 : : // Cannot delete a type if it still has subclasses
581 [ - + ]: 200 : if (_PyType_HasSubclasses(type)) {
582 : 0 : return;
583 : : }
584 : :
585 : : // Undo PyStructSequence_NewType()
586 : 200 : type->tp_name = NULL;
587 : 200 : PyMem_Free(type->tp_members);
588 : :
589 : 200 : _PyStaticType_Dealloc(type);
590 : : assert(Py_REFCNT(type) == 1);
591 : : // Undo Py_INCREF(type) of _PyStructSequence_InitType().
592 : : // Don't use Py_DECREF(): static type must not be deallocated
593 : 200 : Py_SET_REFCNT(type, 0);
594 : : #ifdef Py_REF_DEBUG
595 : : _Py_DecRefTotal();
596 : : #endif
597 : :
598 : : // Make sure that _PyStructSequence_InitType() will initialize
599 : : // the type again
600 : : assert(Py_REFCNT(type) == 0);
601 : : assert(type->tp_name == NULL);
602 : : }
603 : :
604 : :
605 : : PyTypeObject *
606 : 247 : _PyStructSequence_NewType(PyStructSequence_Desc *desc, unsigned long tp_flags)
607 : : {
608 : : PyMemberDef *members;
609 : : PyTypeObject *type;
610 : : PyType_Slot slots[8];
611 : : PyType_Spec spec;
612 : : Py_ssize_t n_members, n_unnamed_members;
613 : :
614 : : /* Initialize MemberDefs */
615 : 247 : members = initialize_members(desc, &n_members, &n_unnamed_members);
616 [ - + ]: 247 : if (members == NULL) {
617 : 0 : return NULL;
618 : : }
619 : :
620 : : /* Initialize Slots */
621 : 247 : slots[0] = (PyType_Slot){Py_tp_dealloc, (destructor)structseq_dealloc};
622 : 247 : slots[1] = (PyType_Slot){Py_tp_repr, (reprfunc)structseq_repr};
623 : 247 : slots[2] = (PyType_Slot){Py_tp_doc, (void *)desc->doc};
624 : 247 : slots[3] = (PyType_Slot){Py_tp_methods, structseq_methods};
625 : 247 : slots[4] = (PyType_Slot){Py_tp_new, structseq_new};
626 : 247 : slots[5] = (PyType_Slot){Py_tp_members, members};
627 : 247 : slots[6] = (PyType_Slot){Py_tp_traverse, (traverseproc)structseq_traverse};
628 : 247 : slots[7] = (PyType_Slot){0, 0};
629 : :
630 : : /* Initialize Spec */
631 : : /* The name in this PyType_Spec is statically allocated so it is */
632 : : /* expected that it'll outlive the PyType_Spec */
633 : 247 : spec.name = desc->name;
634 : 247 : spec.basicsize = sizeof(PyStructSequence) - sizeof(PyObject *);
635 : 247 : spec.itemsize = sizeof(PyObject *);
636 : 247 : spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags;
637 : 247 : spec.slots = slots;
638 : :
639 : 247 : type = (PyTypeObject *)PyType_FromSpecWithBases(&spec, (PyObject *)&PyTuple_Type);
640 : 247 : PyMem_Free(members);
641 [ - + ]: 247 : if (type == NULL) {
642 : 0 : return NULL;
643 : : }
644 : :
645 [ - + ]: 247 : if (initialize_structseq_dict(
646 : : desc, type->tp_dict, n_members, n_unnamed_members) < 0) {
647 : 0 : Py_DECREF(type);
648 : 0 : return NULL;
649 : : }
650 : :
651 : 247 : return type;
652 : : }
653 : :
654 : :
655 : : PyTypeObject *
656 : 246 : PyStructSequence_NewType(PyStructSequence_Desc *desc)
657 : : {
658 : 246 : return _PyStructSequence_NewType(desc, 0);
659 : : }
|