diff options
Diffstat (limited to 'Objects/structseq.c')
-rw-r--r-- | Objects/structseq.c | 667 |
1 files changed, 349 insertions, 318 deletions
diff --git a/Objects/structseq.c b/Objects/structseq.c index c86fbe5..82df926 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -1,38 +1,28 @@ -/* Implementation helper: a struct that looks like a tuple. - See timemodule and posixmodule for example uses. - - The structseq helper is considered an internal CPython implementation - detail. Docs for modules using structseqs should call them - "named tuples" (be sure to include a space between the two - words and add a link back to the term in Docs/glossary.rst). -*/ +/* Implementation helper: a struct that looks like a tuple. See timemodule + and posixmodule for example uses. */ #include "Python.h" -#include "pycore_tupleobject.h" -#include "pycore_object.h" #include "structmember.h" +#include "structseq.h" -static const char visible_length_key[] = "n_sequence_fields"; -static const char real_length_key[] = "n_fields"; -static const char unnamed_fields_key[] = "n_unnamed_fields"; +static char visible_length_key[] = "n_sequence_fields"; +static char real_length_key[] = "n_fields"; +static char unnamed_fields_key[] = "n_unnamed_fields"; /* Fields with this name have only a field index, not a field name. They are only allowed for indices < n_visible_fields. */ -const char * const PyStructSequence_UnnamedField = "unnamed field"; -_Py_IDENTIFIER(n_sequence_fields); -_Py_IDENTIFIER(n_fields); -_Py_IDENTIFIER(n_unnamed_fields); +char *PyStructSequence_UnnamedField = "unnamed field"; #define VISIBLE_SIZE(op) Py_SIZE(op) -#define VISIBLE_SIZE_TP(tp) PyLong_AsSsize_t( \ - _PyDict_GetItemId((tp)->tp_dict, &PyId_n_sequence_fields)) +#define VISIBLE_SIZE_TP(tp) PyInt_AsLong( \ + PyDict_GetItemString((tp)->tp_dict, visible_length_key)) -#define REAL_SIZE_TP(tp) PyLong_AsSsize_t( \ - _PyDict_GetItemId((tp)->tp_dict, &PyId_n_fields)) +#define REAL_SIZE_TP(tp) PyInt_AsLong( \ + PyDict_GetItemString((tp)->tp_dict, real_length_key)) #define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op)) -#define UNNAMED_FIELDS_TP(tp) PyLong_AsSsize_t( \ - _PyDict_GetItemId((tp)->tp_dict, &PyId_n_unnamed_fields)) +#define UNNAMED_FIELDS_TP(tp) PyInt_AsLong( \ + PyDict_GetItemString((tp)->tp_dict, unnamed_fields_key)) #define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op)) @@ -40,83 +30,128 @@ PyObject * PyStructSequence_New(PyTypeObject *type) { PyStructSequence *obj; - Py_ssize_t size = REAL_SIZE_TP(type), i; - obj = PyObject_GC_NewVar(PyStructSequence, type, size); + obj = PyObject_New(PyStructSequence, type); if (obj == NULL) return NULL; - /* Hack the size of the variable object, so invisible fields don't appear - to Python code. */ Py_SIZE(obj) = VISIBLE_SIZE_TP(type); - for (i = 0; i < size; i++) - obj->ob_item[i] = NULL; - return (PyObject*)obj; + return (PyObject*) obj; } -void -PyStructSequence_SetItem(PyObject* op, Py_ssize_t i, PyObject* v) +static void +structseq_dealloc(PyStructSequence *obj) { - PyStructSequence_SET_ITEM(op, i, v); + Py_ssize_t i, size; + + size = REAL_SIZE(obj); + for (i = 0; i < size; ++i) { + Py_XDECREF(obj->ob_item[i]); + } + PyObject_Del(obj); } -PyObject* -PyStructSequence_GetItem(PyObject* op, Py_ssize_t i) +static Py_ssize_t +structseq_length(PyStructSequence *obj) { - return PyStructSequence_GET_ITEM(op, i); + return VISIBLE_SIZE(obj); } - -static int -structseq_traverse(PyStructSequence *obj, visitproc visit, void *arg) +static PyObject* +structseq_item(PyStructSequence *obj, Py_ssize_t i) { - Py_ssize_t i, size; - size = REAL_SIZE(obj); - for (i = 0; i < size; ++i) { - Py_VISIT(obj->ob_item[i]); + if (i < 0 || i >= VISIBLE_SIZE(obj)) { + PyErr_SetString(PyExc_IndexError, "tuple index out of range"); + return NULL; } - return 0; + Py_INCREF(obj->ob_item[i]); + return obj->ob_item[i]; } -static void -structseq_dealloc(PyStructSequence *obj) +static PyObject* +structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high) { - Py_ssize_t i, size; - PyTypeObject *tp; - PyObject_GC_UnTrack(obj); + PyTupleObject *np; + Py_ssize_t i; - tp = (PyTypeObject *) Py_TYPE(obj); - size = REAL_SIZE(obj); - for (i = 0; i < size; ++i) { - Py_XDECREF(obj->ob_item[i]); - } - PyObject_GC_Del(obj); - if (PyType_GetFlags(tp) & Py_TPFLAGS_HEAPTYPE) { - Py_DECREF(tp); + if (low < 0) + low = 0; + if (high > VISIBLE_SIZE(obj)) + high = VISIBLE_SIZE(obj); + if (high < low) + high = low; + np = (PyTupleObject *)PyTuple_New(high-low); + if (np == NULL) + return NULL; + for(i = low; i < high; ++i) { + PyObject *v = obj->ob_item[i]; + Py_INCREF(v); + PyTuple_SET_ITEM(np, i-low, v); } + return (PyObject *) np; } -/*[clinic input] -class structseq "PyStructSequence *" "NULL" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d781c6922c77752]*/ +static PyObject * +structseq_subscript(PyStructSequence *self, PyObject *item) +{ + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) + return NULL; + + if (i < 0) + i += VISIBLE_SIZE(self); -#include "clinic/structseq.c.h" + if (i < 0 || i >= VISIBLE_SIZE(self)) { + PyErr_SetString(PyExc_IndexError, + "tuple index out of range"); + return NULL; + } + Py_INCREF(self->ob_item[i]); + return self->ob_item[i]; + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelen, cur, i; + PyObject *result; -/*[clinic input] -@classmethod -structseq.__new__ as structseq_new - sequence as arg: object - dict: object(c_default="NULL") = {} -[clinic start generated code]*/ + if (_PySlice_Unpack(item, &start, &stop, &step) < 0) { + return NULL; + } + slicelen = _PySlice_AdjustIndices(VISIBLE_SIZE(self), &start, &stop, + step); + if (slicelen <= 0) + return PyTuple_New(0); + result = PyTuple_New(slicelen); + if (result == NULL) + return NULL; + for (cur = start, i = 0; i < slicelen; + cur += step, i++) { + PyObject *v = self->ob_item[cur]; + Py_INCREF(v); + PyTuple_SET_ITEM(result, i, v); + } + return result; + } + else { + PyErr_SetString(PyExc_TypeError, + "structseq index must be integer"); + return NULL; + } +} static PyObject * -structseq_new_impl(PyTypeObject *type, PyObject *arg, PyObject *dict) -/*[clinic end generated code: output=baa082e788b171da input=90532511101aa3fb]*/ +structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + PyObject *arg = NULL; + PyObject *dict = NULL; PyObject *ob; PyStructSequence *res = NULL; Py_ssize_t len, min_len, max_len, i, n_unnamed_fields; + static char *kwlist[] = {"sequence", "dict", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq", + kwlist, &arg, &dict)) + return NULL; arg = PySequence_Fast(arg, "constructor requires a sequence"); @@ -148,8 +183,8 @@ structseq_new_impl(PyTypeObject *type, PyObject *arg, PyObject *dict) if (len > max_len) { PyErr_Format(PyExc_TypeError, - "%.500s() takes an at most %zd-sequence (%zd-sequence given)", - type->tp_name, max_len, len); + "%.500s() takes an at most %zd-sequence (%zd-sequence given)", + type->tp_name, max_len, len); Py_DECREF(arg); return NULL; } @@ -186,119 +221,188 @@ structseq_new_impl(PyTypeObject *type, PyObject *arg, PyObject *dict) } Py_DECREF(arg); - _PyObject_GC_TRACK(res); return (PyObject*) res; } +static PyObject * +make_tuple(PyStructSequence *obj) +{ + return structseq_slice(obj, 0, VISIBLE_SIZE(obj)); +} static PyObject * structseq_repr(PyStructSequence *obj) { - PyTypeObject *typ = Py_TYPE(obj); - _PyUnicodeWriter writer; + /* buffer and type size were chosen well considered. */ +#define REPR_BUFFER_SIZE 512 +#define TYPE_MAXSIZE 100 - /* Write "typename(" */ - PyObject *type_name = PyUnicode_DecodeUTF8(typ->tp_name, - strlen(typ->tp_name), - NULL); - if (type_name == NULL) { - return NULL; - } + PyObject *tup; + PyTypeObject *typ = Py_TYPE(obj); + int i, removelast = 0; + Py_ssize_t len; + char buf[REPR_BUFFER_SIZE]; + char *endofbuf, *pbuf = buf; - _PyUnicodeWriter_Init(&writer); - writer.overallocate = 1; - /* count 5 characters per item: "x=1, " */ - writer.min_length = (PyUnicode_GET_LENGTH(type_name) + 1 - + VISIBLE_SIZE(obj) * 5 + 1); + /* pointer to end of writeable buffer; safes space for "...)\0" */ + endofbuf= &buf[REPR_BUFFER_SIZE-5]; - if (_PyUnicodeWriter_WriteStr(&writer, type_name) < 0) { - Py_DECREF(type_name); - goto error; + if ((tup = make_tuple(obj)) == NULL) { + return NULL; } - Py_DECREF(type_name); - if (_PyUnicodeWriter_WriteChar(&writer, '(') < 0) { - goto error; + /* "typename(", limited to TYPE_MAXSIZE */ + len = strlen(typ->tp_name); + if (len > TYPE_MAXSIZE) { + len = TYPE_MAXSIZE; } + pbuf = memcpy(pbuf, typ->tp_name, len); + pbuf += len; + *pbuf++ = '('; - for (Py_ssize_t i=0; i < VISIBLE_SIZE(obj); i++) { - if (i > 0) { - /* Write ", " */ - if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { - goto error; - } - } + for (i=0; i < VISIBLE_SIZE(obj); i++) { + PyObject *val, *repr; + char *cname, *crepr; - /* Write "name=repr" */ - const char *name_utf8 = typ->tp_members[i].name; - if (name_utf8 == NULL) { - PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %zd name is NULL" - " for type %.500s", i, typ->tp_name); - goto error; - } + cname = typ->tp_members[i].name; - PyObject *name = PyUnicode_DecodeUTF8(name_utf8, strlen(name_utf8), NULL); - if (name == NULL) { - goto error; + val = PyTuple_GetItem(tup, i); + if (cname == NULL || val == NULL) { + Py_DECREF(tup); + return NULL; } - if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) { - Py_DECREF(name); - goto error; + repr = PyObject_Repr(val); + if (repr == NULL) { + Py_DECREF(tup); + return NULL; } - Py_DECREF(name); - - if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) { - goto error; + crepr = PyString_AsString(repr); + if (crepr == NULL) { + Py_DECREF(tup); + Py_DECREF(repr); + return NULL; } - PyObject *value = PyStructSequence_GET_ITEM(obj, i); - assert(value != NULL); - PyObject *repr = PyObject_Repr(value); - if (repr == NULL) { - goto error; + /* + 3: keep space for "=" and ", " */ + len = strlen(cname) + strlen(crepr) + 3; + if ((pbuf+len) <= endofbuf) { + strcpy(pbuf, cname); + pbuf += strlen(cname); + *pbuf++ = '='; + strcpy(pbuf, crepr); + pbuf += strlen(crepr); + *pbuf++ = ','; + *pbuf++ = ' '; + removelast = 1; + Py_DECREF(repr); } - if (_PyUnicodeWriter_WriteStr(&writer, repr) < 0) { + else { + strcpy(pbuf, "..."); + pbuf += 3; + removelast = 0; Py_DECREF(repr); - goto error; + break; } - Py_DECREF(repr); } - - if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) { - goto error; + Py_DECREF(tup); + if (removelast) { + /* overwrite last ", " */ + pbuf-=2; } + *pbuf++ = ')'; + *pbuf = '\0'; - return _PyUnicodeWriter_Finish(&writer); + return PyString_FromString(buf); +} + +static PyObject * +structseq_concat(PyStructSequence *obj, PyObject *b) +{ + PyObject *tup, *result; + tup = make_tuple(obj); + result = PySequence_Concat(tup, b); + Py_DECREF(tup); + return result; +} + +static PyObject * +structseq_repeat(PyStructSequence *obj, Py_ssize_t n) +{ + PyObject *tup, *result; + tup = make_tuple(obj); + result = PySequence_Repeat(tup, n); + Py_DECREF(tup); + return result; +} + +static int +structseq_contains(PyStructSequence *obj, PyObject *o) +{ + PyObject *tup; + int result; + tup = make_tuple(obj); + if (!tup) + return -1; + result = PySequence_Contains(tup, o); + Py_DECREF(tup); + return result; +} -error: - _PyUnicodeWriter_Dealloc(&writer); - return NULL; +static long +structseq_hash(PyObject *obj) +{ + PyObject *tup; + long result; + tup = make_tuple((PyStructSequence*) obj); + if (!tup) + return -1; + result = PyObject_Hash(tup); + Py_DECREF(tup); + return result; } +static PyObject * +structseq_richcompare(PyObject *obj, PyObject *o2, int op) +{ + PyObject *tup, *result; + tup = make_tuple((PyStructSequence*) obj); + result = PyObject_RichCompare(tup, o2, op); + Py_DECREF(tup); + return result; +} static PyObject * -structseq_reduce(PyStructSequence* self, PyObject *Py_UNUSED(ignored)) +structseq_reduce(PyStructSequence* self) { - PyObject* tup = NULL; - PyObject* dict = NULL; + PyObject* tup; + PyObject* dict; PyObject* result; - Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields, i; + Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields; + int i; n_fields = REAL_SIZE(self); n_visible_fields = VISIBLE_SIZE(self); n_unnamed_fields = UNNAMED_FIELDS(self); - tup = _PyTuple_FromArray(self->ob_item, n_visible_fields); - if (!tup) - goto error; + tup = PyTuple_New(n_visible_fields); + if (!tup) { + return NULL; + } dict = PyDict_New(); - if (!dict) - goto error; + if (!dict) { + Py_DECREF(tup); + return NULL; + } + + for (i = 0; i < n_visible_fields; i++) { + Py_INCREF(self->ob_item[i]); + PyTuple_SET_ITEM(tup, i, self->ob_item[i]); + } - for (i = n_visible_fields; i < n_fields; i++) { - const char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name; - if (PyDict_SetItemString(dict, n, self->ob_item[i]) < 0) - goto error; + for (; i < n_fields; i++) { + char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name; + PyDict_SetItemString(dict, n, + self->ob_item[i]); } result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict); @@ -307,67 +411,106 @@ structseq_reduce(PyStructSequence* self, PyObject *Py_UNUSED(ignored)) Py_DECREF(dict); return result; - -error: - Py_XDECREF(tup); - Py_XDECREF(dict); - return NULL; } +static PySequenceMethods structseq_as_sequence = { + (lenfunc)structseq_length, + (binaryfunc)structseq_concat, /* sq_concat */ + (ssizeargfunc)structseq_repeat, /* sq_repeat */ + (ssizeargfunc)structseq_item, /* sq_item */ + (ssizessizeargfunc)structseq_slice, /* sq_slice */ + 0, /* sq_ass_item */ + 0, /* sq_ass_slice */ + (objobjproc)structseq_contains, /* sq_contains */ +}; + +static PyMappingMethods structseq_as_mapping = { + (lenfunc)structseq_length, + (binaryfunc)structseq_subscript, +}; + static PyMethodDef structseq_methods[] = { - {"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL}, + {"__reduce__", (PyCFunction)structseq_reduce, + METH_NOARGS, NULL}, {NULL, NULL} }; -static Py_ssize_t -count_members(PyStructSequence_Desc *desc, Py_ssize_t *n_unnamed_members) { - Py_ssize_t i; +static PyTypeObject _struct_sequence_template = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + NULL, /* tp_name */ + 0, /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)structseq_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)structseq_repr, /* tp_repr */ + 0, /* tp_as_number */ + &structseq_as_sequence, /* tp_as_sequence */ + &structseq_as_mapping, /* tp_as_mapping */ + structseq_hash, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + NULL, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + structseq_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + structseq_methods, /* tp_methods */ + NULL, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + structseq_new, /* tp_new */ +}; - *n_unnamed_members = 0; - for (i = 0; desc->fields[i].name != NULL; ++i) { - if (desc->fields[i].name == PyStructSequence_UnnamedField) { - (*n_unnamed_members)++; - } +void +PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc) +{ + PyObject *dict; + PyMemberDef* members; + int n_members, n_unnamed_members, i, k; + +#ifdef Py_TRACE_REFS + /* if the type object was chained, unchain it first + before overwriting its storage */ + if (type->_ob_next) { + _Py_ForgetReference((PyObject*)type); } - return i; -} +#endif -static int -initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict, - Py_ssize_t n_members, Py_ssize_t n_unnamed_members) { - PyObject *v; - -#define SET_DICT_FROM_SIZE(key, value) \ - do { \ - v = PyLong_FromSsize_t(value); \ - if (v == NULL) { \ - return -1; \ - } \ - if (PyDict_SetItemString(dict, key, v) < 0) { \ - Py_DECREF(v); \ - return -1; \ - } \ - Py_DECREF(v); \ - } while (0) + n_unnamed_members = 0; + for (i = 0; desc->fields[i].name != NULL; ++i) + if (desc->fields[i].name == PyStructSequence_UnnamedField) + n_unnamed_members++; + n_members = i; - SET_DICT_FROM_SIZE(visible_length_key, desc->n_in_sequence); - SET_DICT_FROM_SIZE(real_length_key, n_members); - SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members); - return 0; -} + memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject)); + type->tp_name = desc->name; + type->tp_doc = desc->doc; + type->tp_basicsize = sizeof(PyStructSequence)+ + sizeof(PyObject*)*(n_members-1); + type->tp_itemsize = 0; -static void -initialize_members(PyStructSequence_Desc *desc, PyMemberDef* members, - Py_ssize_t n_members) { - Py_ssize_t i, k; + members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1); + if (members == NULL) + return; for (i = k = 0; i < n_members; ++i) { - if (desc->fields[i].name == PyStructSequence_UnnamedField) { + if (desc->fields[i].name == PyStructSequence_UnnamedField) continue; - } - - /* The names and docstrings in these MemberDefs are statically */ - /* allocated so it is expected that they'll outlive the MemberDef */ members[k].name = desc->fields[i].name; members[k].type = T_OBJECT; members[k].offset = offsetof(PyStructSequence, ob_item) @@ -377,136 +520,24 @@ initialize_members(PyStructSequence_Desc *desc, PyMemberDef* members, k++; } members[k].name = NULL; -} -int -PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) -{ - PyMemberDef *members; - Py_ssize_t n_members, n_unnamed_members; - -#ifdef Py_TRACE_REFS - /* if the type object was chained, unchain it first - before overwriting its storage */ - if (type->ob_base.ob_base._ob_next) { - _Py_ForgetReference((PyObject *)type); - } -#endif - - /* PyTypeObject has already been initialized */ - if (Py_REFCNT(type) != 0) { - PyErr_BadInternalCall(); - return -1; - } - - type->tp_name = desc->name; - type->tp_basicsize = sizeof(PyStructSequence) - sizeof(PyObject *); - type->tp_itemsize = sizeof(PyObject *); - type->tp_dealloc = (destructor)structseq_dealloc; - type->tp_repr = (reprfunc)structseq_repr; - type->tp_doc = desc->doc; - type->tp_base = &PyTuple_Type; - type->tp_methods = structseq_methods; - type->tp_new = structseq_new; - type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC; - type->tp_traverse = (traverseproc) structseq_traverse; - - n_members = count_members(desc, &n_unnamed_members); - members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1); - if (members == NULL) { - PyErr_NoMemory(); - return -1; - } - initialize_members(desc, members, n_members); type->tp_members = members; - if (PyType_Ready(type) < 0) { - PyMem_FREE(members); - return -1; - } + if (PyType_Ready(type) < 0) + return; Py_INCREF(type); - if (initialize_structseq_dict( - desc, type->tp_dict, n_members, n_unnamed_members) < 0) { - PyMem_FREE(members); - Py_DECREF(type); - return -1; - } - - return 0; -} - -void -PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc) -{ - (void)PyStructSequence_InitType2(type, desc); -} - -PyTypeObject * -PyStructSequence_NewType(PyStructSequence_Desc *desc) -{ - PyMemberDef *members; - PyObject *bases; - PyTypeObject *type; - PyType_Slot slots[8]; - PyType_Spec spec; - Py_ssize_t n_members, n_unnamed_members; - - /* Initialize MemberDefs */ - n_members = count_members(desc, &n_unnamed_members); - members = PyMem_NEW(PyMemberDef, n_members - n_unnamed_members + 1); - if (members == NULL) { - PyErr_NoMemory(); - return NULL; - } - initialize_members(desc, members, n_members); - - /* Initialize Slots */ - slots[0] = (PyType_Slot){Py_tp_dealloc, (destructor)structseq_dealloc}; - slots[1] = (PyType_Slot){Py_tp_repr, (reprfunc)structseq_repr}; - slots[2] = (PyType_Slot){Py_tp_doc, (void *)desc->doc}; - slots[3] = (PyType_Slot){Py_tp_methods, structseq_methods}; - slots[4] = (PyType_Slot){Py_tp_new, structseq_new}; - slots[5] = (PyType_Slot){Py_tp_members, members}; - slots[6] = (PyType_Slot){Py_tp_traverse, (traverseproc)structseq_traverse}; - slots[7] = (PyType_Slot){0, 0}; - - /* Initialize Spec */ - /* The name in this PyType_Spec is statically allocated so it is */ - /* expected that it'll outlive the PyType_Spec */ - spec.name = desc->name; - spec.basicsize = sizeof(PyStructSequence) - sizeof(PyObject *); - spec.itemsize = sizeof(PyObject *); - spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC; - spec.slots = slots; - - bases = PyTuple_Pack(1, &PyTuple_Type); - if (bases == NULL) { - PyMem_FREE(members); - return NULL; - } - type = (PyTypeObject *)PyType_FromSpecWithBases(&spec, bases); - Py_DECREF(bases); - PyMem_FREE(members); - if (type == NULL) { - return NULL; - } - - if (initialize_structseq_dict( - desc, type->tp_dict, n_members, n_unnamed_members) < 0) { - Py_DECREF(type); - return NULL; - } - - return type; -} - -int _PyStructSequence_Init(void) -{ - if (_PyUnicode_FromId(&PyId_n_sequence_fields) == NULL - || _PyUnicode_FromId(&PyId_n_fields) == NULL - || _PyUnicode_FromId(&PyId_n_unnamed_fields) == NULL) - return -1; + dict = type->tp_dict; +#define SET_DICT_FROM_INT(key, value) \ + do { \ + PyObject *v = PyInt_FromLong((long) value); \ + if (v != NULL) { \ + PyDict_SetItemString(dict, key, v); \ + Py_DECREF(v); \ + } \ + } while (0) - return 0; + SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence); + SET_DICT_FROM_INT(real_length_key, n_members); + SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members); } |