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_initconfig.h" // _PyStatus_OK()
12 #include "pycore_modsupport.h" // _PyArg_NoPositional()
13 #include "pycore_object.h" // _PyObject_GC_TRACK()
14 #include "pycore_structseq.h" // PyStructSequence_InitType()
15 #include "pycore_tuple.h" // _PyTuple_FromArray()
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
get_type_attr_as_size(PyTypeObject * tp,PyObject * name)27 get_type_attr_as_size(PyTypeObject *tp, PyObject *name)
28 {
29 PyObject *v = PyDict_GetItemWithError(_PyType_GetDict(tp), name);
30 if (v == NULL && !PyErr_Occurred()) {
31 PyErr_Format(PyExc_TypeError,
32 "Missed attribute '%U' of type %s",
33 name, tp->tp_name);
34 return -1;
35 }
36 return PyLong_AsSsize_t(v);
37 }
38
39 #define VISIBLE_SIZE(op) Py_SIZE(op)
40 #define VISIBLE_SIZE_TP(tp) \
41 get_type_attr_as_size(tp, &_Py_ID(n_sequence_fields))
42 #define REAL_SIZE_TP(tp) \
43 get_type_attr_as_size(tp, &_Py_ID(n_fields))
44 #define REAL_SIZE(op) get_real_size((PyObject *)op)
45
46 #define UNNAMED_FIELDS_TP(tp) \
47 get_type_attr_as_size(tp, &_Py_ID(n_unnamed_fields))
48 #define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op))
49
50 static Py_ssize_t
get_real_size(PyObject * op)51 get_real_size(PyObject *op)
52 {
53 // Compute the real size from the visible size (i.e., Py_SIZE()) and the
54 // number of non-sequence fields accounted for in tp_basicsize.
55 Py_ssize_t hidden = Py_TYPE(op)->tp_basicsize - offsetof(PyStructSequence, ob_item);
56 return Py_SIZE(op) + hidden / sizeof(PyObject *);
57 }
58
59 PyObject *
PyStructSequence_New(PyTypeObject * type)60 PyStructSequence_New(PyTypeObject *type)
61 {
62 PyStructSequence *obj;
63 Py_ssize_t size = REAL_SIZE_TP(type), i;
64 if (size < 0) {
65 return NULL;
66 }
67 Py_ssize_t vsize = VISIBLE_SIZE_TP(type);
68 if (vsize < 0) {
69 return NULL;
70 }
71
72 obj = PyObject_GC_NewVar(PyStructSequence, type, size);
73 if (obj == NULL)
74 return NULL;
75 /* Hack the size of the variable object, so invisible fields don't appear
76 to Python code. */
77 Py_SET_SIZE(obj, vsize);
78 for (i = 0; i < size; i++)
79 obj->ob_item[i] = NULL;
80
81 return (PyObject*)obj;
82 }
83
84 void
PyStructSequence_SetItem(PyObject * op,Py_ssize_t index,PyObject * value)85 PyStructSequence_SetItem(PyObject *op, Py_ssize_t index, PyObject *value)
86 {
87 PyTupleObject *tuple = _PyTuple_CAST(op);
88 assert(0 <= index);
89 #ifndef NDEBUG
90 Py_ssize_t n_fields = REAL_SIZE(op);
91 assert(n_fields >= 0);
92 assert(index < n_fields);
93 #endif
94 tuple->ob_item[index] = value;
95 }
96
97 PyObject*
PyStructSequence_GetItem(PyObject * op,Py_ssize_t index)98 PyStructSequence_GetItem(PyObject *op, Py_ssize_t index)
99 {
100 assert(0 <= index);
101 #ifndef NDEBUG
102 Py_ssize_t n_fields = REAL_SIZE(op);
103 assert(n_fields >= 0);
104 assert(index < n_fields);
105 #endif
106 return PyTuple_GET_ITEM(op, index);
107 }
108
109
110 static int
structseq_traverse(PyStructSequence * obj,visitproc visit,void * arg)111 structseq_traverse(PyStructSequence *obj, visitproc visit, void *arg)
112 {
113 if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HEAPTYPE) {
114 Py_VISIT(Py_TYPE(obj));
115 }
116 Py_ssize_t i, size;
117 size = REAL_SIZE(obj);
118 for (i = 0; i < size; ++i) {
119 Py_VISIT(obj->ob_item[i]);
120 }
121 return 0;
122 }
123
124 static void
structseq_dealloc(PyStructSequence * obj)125 structseq_dealloc(PyStructSequence *obj)
126 {
127 Py_ssize_t i, size;
128 PyObject_GC_UnTrack(obj);
129
130 PyTypeObject *tp = Py_TYPE(obj);
131 // gh-122527: We can't use REAL_SIZE_TP() or any macros that access the
132 // type's dictionary here, because the dictionary may have already been
133 // cleared by the garbage collector.
134 size = REAL_SIZE(obj);
135 for (i = 0; i < size; ++i) {
136 Py_XDECREF(obj->ob_item[i]);
137 }
138 PyObject_GC_Del(obj);
139 if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
140 Py_DECREF(tp);
141 }
142 }
143
144 /*[clinic input]
145 class structseq "PyStructSequence *" "NULL"
146 [clinic start generated code]*/
147 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d781c6922c77752]*/
148
149 #include "clinic/structseq.c.h"
150
151 /*[clinic input]
152 @classmethod
153 structseq.__new__ as structseq_new
154 sequence as arg: object
155 dict: object(c_default="NULL") = {}
156 [clinic start generated code]*/
157
158 static PyObject *
structseq_new_impl(PyTypeObject * type,PyObject * arg,PyObject * dict)159 structseq_new_impl(PyTypeObject *type, PyObject *arg, PyObject *dict)
160 /*[clinic end generated code: output=baa082e788b171da input=90532511101aa3fb]*/
161 {
162 PyStructSequence *res = NULL;
163 Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;
164
165 min_len = VISIBLE_SIZE_TP(type);
166 if (min_len < 0) {
167 return NULL;
168 }
169 max_len = REAL_SIZE_TP(type);
170 if (max_len < 0) {
171 return NULL;
172 }
173 n_unnamed_fields = UNNAMED_FIELDS_TP(type);
174 if (n_unnamed_fields < 0) {
175 return NULL;
176 }
177
178 arg = PySequence_Fast(arg, "constructor requires a sequence");
179
180 if (!arg) {
181 return NULL;
182 }
183
184 if (dict && !PyDict_Check(dict)) {
185 PyErr_Format(PyExc_TypeError,
186 "%.500s() takes a dict as second arg, if any",
187 type->tp_name);
188 Py_DECREF(arg);
189 return NULL;
190 }
191
192 len = PySequence_Fast_GET_SIZE(arg);
193 if (min_len != max_len) {
194 if (len < min_len) {
195 PyErr_Format(PyExc_TypeError,
196 "%.500s() takes an at least %zd-sequence (%zd-sequence given)",
197 type->tp_name, min_len, len);
198 Py_DECREF(arg);
199 return NULL;
200 }
201
202 if (len > max_len) {
203 PyErr_Format(PyExc_TypeError,
204 "%.500s() takes an at most %zd-sequence (%zd-sequence given)",
205 type->tp_name, max_len, len);
206 Py_DECREF(arg);
207 return NULL;
208 }
209 }
210 else {
211 if (len != min_len) {
212 PyErr_Format(PyExc_TypeError,
213 "%.500s() takes a %zd-sequence (%zd-sequence given)",
214 type->tp_name, min_len, len);
215 Py_DECREF(arg);
216 return NULL;
217 }
218 }
219
220 res = (PyStructSequence*) PyStructSequence_New(type);
221 if (res == NULL) {
222 Py_DECREF(arg);
223 return NULL;
224 }
225 for (i = 0; i < len; ++i) {
226 PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
227 res->ob_item[i] = Py_NewRef(v);
228 }
229 Py_DECREF(arg);
230 if (dict != NULL && PyDict_GET_SIZE(dict) > 0) {
231 Py_ssize_t n_found_keys = 0;
232 for (i = len; i < max_len; ++i) {
233 PyObject *ob = NULL;
234 const char *name = type->tp_members[i - n_unnamed_fields].name;
235 if (PyDict_GetItemStringRef(dict, name, &ob) < 0) {
236 Py_DECREF(res);
237 return NULL;
238 }
239 if (ob == NULL) {
240 ob = Py_NewRef(Py_None);
241 }
242 else {
243 ++n_found_keys;
244 }
245 res->ob_item[i] = ob;
246 }
247 if (PyDict_GET_SIZE(dict) > n_found_keys) {
248 PyErr_Format(PyExc_TypeError,
249 "%.500s() got duplicate or unexpected field name(s)",
250 type->tp_name);
251 Py_DECREF(res);
252 return NULL;
253 }
254 } else {
255 for (i = len; i < max_len; ++i) {
256 res->ob_item[i] = Py_NewRef(Py_None);
257 }
258 }
259
260 _PyObject_GC_TRACK(res);
261 return (PyObject*) res;
262 }
263
264
265 static PyObject *
structseq_repr(PyStructSequence * obj)266 structseq_repr(PyStructSequence *obj)
267 {
268 PyTypeObject *typ = Py_TYPE(obj);
269 _PyUnicodeWriter writer;
270
271 /* Write "typename(" */
272 PyObject *type_name = PyUnicode_DecodeUTF8(typ->tp_name,
273 strlen(typ->tp_name),
274 NULL);
275 if (type_name == NULL) {
276 return NULL;
277 }
278
279 _PyUnicodeWriter_Init(&writer);
280 writer.overallocate = 1;
281 /* count 5 characters per item: "x=1, " */
282 writer.min_length = (PyUnicode_GET_LENGTH(type_name) + 1
283 + VISIBLE_SIZE(obj) * 5 + 1);
284
285 if (_PyUnicodeWriter_WriteStr(&writer, type_name) < 0) {
286 Py_DECREF(type_name);
287 goto error;
288 }
289 Py_DECREF(type_name);
290
291 if (_PyUnicodeWriter_WriteChar(&writer, '(') < 0) {
292 goto error;
293 }
294
295 for (Py_ssize_t i=0; i < VISIBLE_SIZE(obj); i++) {
296 if (i > 0) {
297 /* Write ", " */
298 if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
299 goto error;
300 }
301 }
302
303 /* Write "name=repr" */
304 const char *name_utf8 = typ->tp_members[i].name;
305 if (name_utf8 == NULL) {
306 PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %zd name is NULL"
307 " for type %.500s", i, typ->tp_name);
308 goto error;
309 }
310
311 PyObject *name = PyUnicode_DecodeUTF8(name_utf8, strlen(name_utf8), NULL);
312 if (name == NULL) {
313 goto error;
314 }
315 if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) {
316 Py_DECREF(name);
317 goto error;
318 }
319 Py_DECREF(name);
320
321 if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) {
322 goto error;
323 }
324
325 PyObject *value = PyStructSequence_GetItem((PyObject*)obj, i);
326 assert(value != NULL);
327 PyObject *repr = PyObject_Repr(value);
328 if (repr == NULL) {
329 goto error;
330 }
331 if (_PyUnicodeWriter_WriteStr(&writer, repr) < 0) {
332 Py_DECREF(repr);
333 goto error;
334 }
335 Py_DECREF(repr);
336 }
337
338 if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) {
339 goto error;
340 }
341
342 return _PyUnicodeWriter_Finish(&writer);
343
344 error:
345 _PyUnicodeWriter_Dealloc(&writer);
346 return NULL;
347 }
348
349
350 static PyObject *
structseq_reduce(PyStructSequence * self,PyObject * Py_UNUSED (ignored))351 structseq_reduce(PyStructSequence* self, PyObject *Py_UNUSED(ignored))
352 {
353 PyObject* tup = NULL;
354 PyObject* dict = NULL;
355 PyObject* result;
356 Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields, i;
357
358 n_fields = REAL_SIZE(self);
359 if (n_fields < 0) {
360 return NULL;
361 }
362 n_visible_fields = VISIBLE_SIZE(self);
363 n_unnamed_fields = UNNAMED_FIELDS(self);
364 if (n_unnamed_fields < 0) {
365 return NULL;
366 }
367 tup = _PyTuple_FromArray(self->ob_item, n_visible_fields);
368 if (!tup)
369 goto error;
370
371 dict = PyDict_New();
372 if (!dict)
373 goto error;
374
375 for (i = n_visible_fields; i < n_fields; i++) {
376 const char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
377 if (PyDict_SetItemString(dict, n, self->ob_item[i]) < 0)
378 goto error;
379 }
380
381 result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict);
382
383 Py_DECREF(tup);
384 Py_DECREF(dict);
385
386 return result;
387
388 error:
389 Py_XDECREF(tup);
390 Py_XDECREF(dict);
391 return NULL;
392 }
393
394
395 static PyObject *
structseq_replace(PyStructSequence * self,PyObject * args,PyObject * kwargs)396 structseq_replace(PyStructSequence *self, PyObject *args, PyObject *kwargs)
397 {
398 PyStructSequence *result = NULL;
399 Py_ssize_t n_fields, n_unnamed_fields, i;
400
401 if (!_PyArg_NoPositional("__replace__", args)) {
402 return NULL;
403 }
404
405 n_fields = REAL_SIZE(self);
406 if (n_fields < 0) {
407 return NULL;
408 }
409 n_unnamed_fields = UNNAMED_FIELDS(self);
410 if (n_unnamed_fields < 0) {
411 return NULL;
412 }
413 if (n_unnamed_fields > 0) {
414 PyErr_Format(PyExc_TypeError,
415 "__replace__() is not supported for %.500s "
416 "because it has unnamed field(s)",
417 Py_TYPE(self)->tp_name);
418 return NULL;
419 }
420
421 result = (PyStructSequence *) PyStructSequence_New(Py_TYPE(self));
422 if (!result) {
423 return NULL;
424 }
425
426 if (kwargs != NULL) {
427 // We do not support types with unnamed fields, so we can iterate over
428 // i >= n_visible_fields case without slicing with (i - n_unnamed_fields).
429 for (i = 0; i < n_fields; ++i) {
430 PyObject *ob;
431 if (PyDict_PopString(kwargs, Py_TYPE(self)->tp_members[i].name,
432 &ob) < 0) {
433 goto error;
434 }
435 if (ob == NULL) {
436 ob = Py_NewRef(self->ob_item[i]);
437 }
438 result->ob_item[i] = ob;
439 }
440 // Check if there are any unexpected fields.
441 if (PyDict_GET_SIZE(kwargs) > 0) {
442 PyObject *names = PyDict_Keys(kwargs);
443 if (names) {
444 PyErr_Format(PyExc_TypeError, "Got unexpected field name(s): %R", names);
445 Py_DECREF(names);
446 }
447 goto error;
448 }
449 }
450 else
451 {
452 // Just create a copy of the original.
453 for (i = 0; i < n_fields; ++i) {
454 result->ob_item[i] = Py_NewRef(self->ob_item[i]);
455 }
456 }
457
458 return (PyObject *)result;
459
460 error:
461 Py_DECREF(result);
462 return NULL;
463 }
464
465 static PyMethodDef structseq_methods[] = {
466 {"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL},
467 {"__replace__", _PyCFunction_CAST(structseq_replace), METH_VARARGS | METH_KEYWORDS,
468 PyDoc_STR("__replace__($self, /, **changes)\n--\n\n"
469 "Return a copy of the structure with new values for the specified fields.")},
470 {NULL, NULL} // sentinel
471 };
472
473 static Py_ssize_t
count_members(PyStructSequence_Desc * desc,Py_ssize_t * n_unnamed_members)474 count_members(PyStructSequence_Desc *desc, Py_ssize_t *n_unnamed_members) {
475 Py_ssize_t i;
476
477 *n_unnamed_members = 0;
478 for (i = 0; desc->fields[i].name != NULL; ++i) {
479 if (desc->fields[i].name == PyStructSequence_UnnamedField) {
480 (*n_unnamed_members)++;
481 }
482 }
483 return i;
484 }
485
486 static int
initialize_structseq_dict(PyStructSequence_Desc * desc,PyObject * dict,Py_ssize_t n_members,Py_ssize_t n_unnamed_members)487 initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict,
488 Py_ssize_t n_members, Py_ssize_t n_unnamed_members) {
489 PyObject *v;
490
491 #define SET_DICT_FROM_SIZE(key, value) \
492 do { \
493 v = PyLong_FromSsize_t(value); \
494 if (v == NULL) { \
495 return -1; \
496 } \
497 if (PyDict_SetItemString(dict, key, v) < 0) { \
498 Py_DECREF(v); \
499 return -1; \
500 } \
501 Py_DECREF(v); \
502 } while (0)
503
504 SET_DICT_FROM_SIZE(visible_length_key, desc->n_in_sequence);
505 SET_DICT_FROM_SIZE(real_length_key, n_members);
506 SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members);
507
508 // Prepare and set __match_args__
509 Py_ssize_t i, k;
510 PyObject* keys = PyTuple_New(desc->n_in_sequence);
511 if (keys == NULL) {
512 return -1;
513 }
514
515 for (i = k = 0; i < desc->n_in_sequence; ++i) {
516 if (desc->fields[i].name == PyStructSequence_UnnamedField) {
517 continue;
518 }
519 PyObject* new_member = PyUnicode_FromString(desc->fields[i].name);
520 if (new_member == NULL) {
521 goto error;
522 }
523 PyTuple_SET_ITEM(keys, k, new_member);
524 k++;
525 }
526
527 if (_PyTuple_Resize(&keys, k) == -1) {
528 goto error;
529 }
530
531 if (PyDict_SetItemString(dict, match_args_key, keys) < 0) {
532 goto error;
533 }
534
535 Py_DECREF(keys);
536 return 0;
537
538 error:
539 Py_DECREF(keys);
540 return -1;
541 }
542
543 static PyMemberDef *
initialize_members(PyStructSequence_Desc * desc,Py_ssize_t n_members,Py_ssize_t n_unnamed_members)544 initialize_members(PyStructSequence_Desc *desc,
545 Py_ssize_t n_members, Py_ssize_t n_unnamed_members)
546 {
547 PyMemberDef *members;
548
549 members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1);
550 if (members == NULL) {
551 PyErr_NoMemory();
552 return NULL;
553 }
554
555 Py_ssize_t i, k;
556 for (i = k = 0; i < n_members; ++i) {
557 if (desc->fields[i].name == PyStructSequence_UnnamedField) {
558 continue;
559 }
560
561 /* The names and docstrings in these MemberDefs are statically */
562 /* allocated so it is expected that they'll outlive the MemberDef */
563 members[k].name = desc->fields[i].name;
564 members[k].type = _Py_T_OBJECT;
565 members[k].offset = offsetof(PyStructSequence, ob_item)
566 + i * sizeof(PyObject*);
567 members[k].flags = Py_READONLY;
568 members[k].doc = desc->fields[i].doc;
569 k++;
570 }
571 members[k].name = NULL;
572
573 return members;
574 }
575
576
577 static void
initialize_static_fields(PyTypeObject * type,PyStructSequence_Desc * desc,PyMemberDef * tp_members,Py_ssize_t n_members,unsigned long tp_flags)578 initialize_static_fields(PyTypeObject *type, PyStructSequence_Desc *desc,
579 PyMemberDef *tp_members, Py_ssize_t n_members,
580 unsigned long tp_flags)
581 {
582 type->tp_name = desc->name;
583 // Account for hidden members in tp_basicsize because they are not
584 // included in the variable size.
585 Py_ssize_t n_hidden = n_members - desc->n_in_sequence;
586 type->tp_basicsize = sizeof(PyStructSequence) + (n_hidden - 1) * sizeof(PyObject *);
587 type->tp_itemsize = sizeof(PyObject *);
588 type->tp_dealloc = (destructor)structseq_dealloc;
589 type->tp_repr = (reprfunc)structseq_repr;
590 type->tp_doc = desc->doc;
591 type->tp_base = &PyTuple_Type;
592 type->tp_methods = structseq_methods;
593 type->tp_new = structseq_new;
594 type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags;
595 type->tp_traverse = (traverseproc) structseq_traverse;
596 type->tp_members = tp_members;
597 }
598
599 static int
initialize_static_type(PyTypeObject * type,PyStructSequence_Desc * desc,Py_ssize_t n_members,Py_ssize_t n_unnamed_members)600 initialize_static_type(PyTypeObject *type, PyStructSequence_Desc *desc,
601 Py_ssize_t n_members, Py_ssize_t n_unnamed_members) {
602 /* initialize_static_fields() should have been called already. */
603 if (PyType_Ready(type) < 0) {
604 return -1;
605 }
606 Py_INCREF(type);
607
608 if (initialize_structseq_dict(
609 desc, _PyType_GetDict(type), n_members, n_unnamed_members) < 0) {
610 Py_DECREF(type);
611 return -1;
612 }
613
614 return 0;
615 }
616
617 int
_PyStructSequence_InitBuiltinWithFlags(PyInterpreterState * interp,PyTypeObject * type,PyStructSequence_Desc * desc,unsigned long tp_flags)618 _PyStructSequence_InitBuiltinWithFlags(PyInterpreterState *interp,
619 PyTypeObject *type,
620 PyStructSequence_Desc *desc,
621 unsigned long tp_flags)
622 {
623 if (Py_TYPE(type) == NULL) {
624 Py_SET_TYPE(type, &PyType_Type);
625 }
626 Py_ssize_t n_unnamed_members;
627 Py_ssize_t n_members = count_members(desc, &n_unnamed_members);
628 PyMemberDef *members = NULL;
629
630 if ((type->tp_flags & Py_TPFLAGS_READY) == 0) {
631 assert(type->tp_name == NULL);
632 assert(type->tp_members == NULL);
633 assert(type->tp_base == NULL);
634
635 members = initialize_members(desc, n_members, n_unnamed_members);
636 if (members == NULL) {
637 goto error;
638 }
639 initialize_static_fields(type, desc, members, n_members, tp_flags);
640
641 _Py_SetImmortal((PyObject *)type);
642 }
643 #ifndef NDEBUG
644 else {
645 // Ensure that the type was initialized.
646 assert(type->tp_name != NULL);
647 assert(type->tp_members != NULL);
648 assert(type->tp_base == &PyTuple_Type);
649 assert((type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN));
650 assert(_Py_IsImmortal(type));
651 }
652 #endif
653
654 if (_PyStaticType_InitBuiltin(interp, type) < 0) {
655 PyErr_Format(PyExc_RuntimeError,
656 "Can't initialize builtin type %s",
657 desc->name);
658 goto error;
659 }
660
661 if (initialize_structseq_dict(
662 desc, _PyType_GetDict(type), n_members, n_unnamed_members) < 0)
663 {
664 goto error;
665 }
666
667 return 0;
668
669 error:
670 if (members != NULL) {
671 PyMem_Free(members);
672 }
673 return -1;
674 }
675
676 int
PyStructSequence_InitType2(PyTypeObject * type,PyStructSequence_Desc * desc)677 PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc)
678 {
679 PyMemberDef *members;
680 Py_ssize_t n_members, n_unnamed_members;
681
682 #ifdef Py_TRACE_REFS
683 /* if the type object was traced, remove it first
684 before overwriting its storage */
685 PyInterpreterState *interp = _PyInterpreterState_GET();
686 if (_PyRefchain_IsTraced(interp, (PyObject *)type)) {
687 _Py_ForgetReference((PyObject *)type);
688 }
689 #endif
690
691 /* PyTypeObject has already been initialized */
692 if (Py_REFCNT(type) != 0) {
693 PyErr_BadInternalCall();
694 return -1;
695 }
696
697 n_members = count_members(desc, &n_unnamed_members);
698 members = initialize_members(desc, n_members, n_unnamed_members);
699 if (members == NULL) {
700 return -1;
701 }
702 initialize_static_fields(type, desc, members, n_members, 0);
703 if (initialize_static_type(type, desc, n_members, n_unnamed_members) < 0) {
704 PyMem_Free(members);
705 return -1;
706 }
707 return 0;
708 }
709
710 void
PyStructSequence_InitType(PyTypeObject * type,PyStructSequence_Desc * desc)711 PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
712 {
713 (void)PyStructSequence_InitType2(type, desc);
714 }
715
716
717 /* This is exposed in the internal API, not the public API.
718 It is only called on builtin static types, which are all
719 initialized via _PyStructSequence_InitBuiltinWithFlags(). */
720
721 void
_PyStructSequence_FiniBuiltin(PyInterpreterState * interp,PyTypeObject * type)722 _PyStructSequence_FiniBuiltin(PyInterpreterState *interp, PyTypeObject *type)
723 {
724 // Ensure that the type is initialized
725 assert(type->tp_name != NULL);
726 assert(type->tp_base == &PyTuple_Type);
727 assert((type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN));
728 assert(_Py_IsImmortalLoose(type));
729
730 // Cannot delete a type if it still has subclasses
731 if (_PyType_HasSubclasses(type)) {
732 // XXX Shouldn't this be an error?
733 return;
734 }
735
736 _PyStaticType_FiniBuiltin(interp, type);
737
738 if (_Py_IsMainInterpreter(interp)) {
739 // Undo _PyStructSequence_InitBuiltinWithFlags().
740 type->tp_name = NULL;
741 PyMem_Free(type->tp_members);
742 type->tp_members = NULL;
743 type->tp_base = NULL;
744 }
745 }
746
747
748 PyTypeObject *
_PyStructSequence_NewType(PyStructSequence_Desc * desc,unsigned long tp_flags)749 _PyStructSequence_NewType(PyStructSequence_Desc *desc, unsigned long tp_flags)
750 {
751 PyMemberDef *members;
752 PyTypeObject *type;
753 PyType_Slot slots[8];
754 PyType_Spec spec;
755 Py_ssize_t n_members, n_unnamed_members;
756
757 /* Initialize MemberDefs */
758 n_members = count_members(desc, &n_unnamed_members);
759 members = initialize_members(desc, n_members, n_unnamed_members);
760 if (members == NULL) {
761 return NULL;
762 }
763
764 /* Initialize Slots */
765 slots[0] = (PyType_Slot){Py_tp_dealloc, (destructor)structseq_dealloc};
766 slots[1] = (PyType_Slot){Py_tp_repr, (reprfunc)structseq_repr};
767 slots[2] = (PyType_Slot){Py_tp_doc, (void *)desc->doc};
768 slots[3] = (PyType_Slot){Py_tp_methods, structseq_methods};
769 slots[4] = (PyType_Slot){Py_tp_new, structseq_new};
770 slots[5] = (PyType_Slot){Py_tp_members, members};
771 slots[6] = (PyType_Slot){Py_tp_traverse, (traverseproc)structseq_traverse};
772 slots[7] = (PyType_Slot){0, 0};
773
774 /* Initialize Spec */
775 /* The name in this PyType_Spec is statically allocated so it is */
776 /* expected that it'll outlive the PyType_Spec */
777 spec.name = desc->name;
778 Py_ssize_t hidden = n_members - desc->n_in_sequence;
779 spec.basicsize = (int)(sizeof(PyStructSequence) + (hidden - 1) * sizeof(PyObject *));
780 spec.itemsize = sizeof(PyObject *);
781 spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags;
782 spec.slots = slots;
783
784 type = (PyTypeObject *)PyType_FromSpecWithBases(&spec, (PyObject *)&PyTuple_Type);
785 PyMem_Free(members);
786 if (type == NULL) {
787 return NULL;
788 }
789
790 if (initialize_structseq_dict(
791 desc, _PyType_GetDict(type), n_members, n_unnamed_members) < 0) {
792 Py_DECREF(type);
793 return NULL;
794 }
795
796 return type;
797 }
798
799
800 PyTypeObject *
PyStructSequence_NewType(PyStructSequence_Desc * desc)801 PyStructSequence_NewType(PyStructSequence_Desc *desc)
802 {
803 return _PyStructSequence_NewType(desc, 0);
804 }
805