Skip to content

Commit ccabcd4

Browse files
committed
make struct sequences subclass tuple; kill lots of code
This fixes python#8413.
1 parent a9800a8 commit ccabcd4

File tree

3 files changed

+23
-215
lines changed

3 files changed

+23
-215
lines changed

Include/structseq.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,12 @@ PyAPI_FUNC(void) PyStructSequence_InitType(PyTypeObject *type,
2626

2727
PyAPI_FUNC(PyObject *) PyStructSequence_New(PyTypeObject* type);
2828

29-
typedef struct {
30-
PyObject_VAR_HEAD
31-
PyObject *ob_item[1];
32-
} PyStructSequence;
29+
typedef PyTupleObject PyStructSequence;
3330

3431
/* Macro, *only* to be used to fill in brand new objects */
35-
#define PyStructSequence_SET_ITEM(op, i, v) \
36-
(((PyStructSequence *)(op))->ob_item[i] = v)
32+
#define PyStructSequence_SET_ITEM(op, i, v) PyTuple_SET_ITEM(op, i, v)
3733

38-
#define PyStructSequence_GET_ITEM(op, i) \
39-
(((PyStructSequence *)(op))->ob_item[i])
34+
#define PyStructSequence_GET_ITEM(op, i) PyTuple_GET_ITEM(op, i)
4035

4136

4237
#ifdef __cplusplus

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ What's New in Python 3.2 Alpha 1?
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #8413: structsequence now subclasses tuple.
16+
1517
- Issue #8271: during the decoding of an invalid UTF-8 byte sequence, only the
1618
start byte and the continuation byte(s) are now considered invalid, instead
1719
of the number of bytes specified by the start byte.

Objects/structseq.c

Lines changed: 18 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -30,113 +30,15 @@ PyObject *
3030
PyStructSequence_New(PyTypeObject *type)
3131
{
3232
PyStructSequence *obj;
33+
Py_ssize_t size = REAL_SIZE_TP(type), i;
3334

34-
obj = PyObject_New(PyStructSequence, type);
35+
obj = PyObject_GC_NewVar(PyStructSequence, type, size);
3536
if (obj == NULL)
3637
return NULL;
37-
Py_SIZE(obj) = VISIBLE_SIZE_TP(type);
38+
for (i = 0; i < size; i++)
39+
obj->ob_item[i] = NULL;
3840

39-
return (PyObject*) obj;
40-
}
41-
42-
static void
43-
structseq_dealloc(PyStructSequence *obj)
44-
{
45-
Py_ssize_t i, size;
46-
47-
size = REAL_SIZE(obj);
48-
for (i = 0; i < size; ++i) {
49-
Py_XDECREF(obj->ob_item[i]);
50-
}
51-
PyObject_Del(obj);
52-
}
53-
54-
static Py_ssize_t
55-
structseq_length(PyStructSequence *obj)
56-
{
57-
return VISIBLE_SIZE(obj);
58-
}
59-
60-
static PyObject*
61-
structseq_item(PyStructSequence *obj, Py_ssize_t i)
62-
{
63-
if (i < 0 || i >= VISIBLE_SIZE(obj)) {
64-
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
65-
return NULL;
66-
}
67-
Py_INCREF(obj->ob_item[i]);
68-
return obj->ob_item[i];
69-
}
70-
71-
static PyObject*
72-
structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high)
73-
{
74-
PyTupleObject *np;
75-
Py_ssize_t i;
76-
77-
if (low < 0)
78-
low = 0;
79-
if (high > VISIBLE_SIZE(obj))
80-
high = VISIBLE_SIZE(obj);
81-
if (high < low)
82-
high = low;
83-
np = (PyTupleObject *)PyTuple_New(high-low);
84-
if (np == NULL)
85-
return NULL;
86-
for(i = low; i < high; ++i) {
87-
PyObject *v = obj->ob_item[i];
88-
Py_INCREF(v);
89-
PyTuple_SET_ITEM(np, i-low, v);
90-
}
91-
return (PyObject *) np;
92-
}
93-
94-
static PyObject *
95-
structseq_subscript(PyStructSequence *self, PyObject *item)
96-
{
97-
if (PyIndex_Check(item)) {
98-
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
99-
if (i == -1 && PyErr_Occurred())
100-
return NULL;
101-
102-
if (i < 0)
103-
i += VISIBLE_SIZE(self);
104-
105-
if (i < 0 || i >= VISIBLE_SIZE(self)) {
106-
PyErr_SetString(PyExc_IndexError,
107-
"tuple index out of range");
108-
return NULL;
109-
}
110-
Py_INCREF(self->ob_item[i]);
111-
return self->ob_item[i];
112-
}
113-
else if (PySlice_Check(item)) {
114-
Py_ssize_t start, stop, step, slicelen, cur, i;
115-
PyObject *result;
116-
117-
if (PySlice_GetIndicesEx((PySliceObject *)item,
118-
VISIBLE_SIZE(self), &start, &stop,
119-
&step, &slicelen) < 0) {
120-
return NULL;
121-
}
122-
if (slicelen <= 0)
123-
return PyTuple_New(0);
124-
result = PyTuple_New(slicelen);
125-
if (result == NULL)
126-
return NULL;
127-
for (cur = start, i = 0; i < slicelen;
128-
cur += step, i++) {
129-
PyObject *v = self->ob_item[cur];
130-
Py_INCREF(v);
131-
PyTuple_SET_ITEM(result, i, v);
132-
}
133-
return result;
134-
}
135-
else {
136-
PyErr_SetString(PyExc_TypeError,
137-
"structseq index must be integer");
138-
return NULL;
139-
}
41+
return (PyObject*)obj;
14042
}
14143

14244
static PyObject *
@@ -223,11 +125,6 @@ structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
223125
return (PyObject*) res;
224126
}
225127

226-
static PyObject *
227-
make_tuple(PyStructSequence *obj)
228-
{
229-
return structseq_slice(obj, 0, VISIBLE_SIZE(obj));
230-
}
231128

232129
static PyObject *
233130
structseq_repr(PyStructSequence *obj)
@@ -236,7 +133,6 @@ structseq_repr(PyStructSequence *obj)
236133
#define REPR_BUFFER_SIZE 512
237134
#define TYPE_MAXSIZE 100
238135

239-
PyObject *tup;
240136
PyTypeObject *typ = Py_TYPE(obj);
241137
int i, removelast = 0;
242138
Py_ssize_t len;
@@ -246,10 +142,6 @@ structseq_repr(PyStructSequence *obj)
246142
/* pointer to end of writeable buffer; safes space for "...)\0" */
247143
endofbuf= &buf[REPR_BUFFER_SIZE-5];
248144

249-
if ((tup = make_tuple(obj)) == NULL) {
250-
return NULL;
251-
}
252-
253145
/* "typename(", limited to TYPE_MAXSIZE */
254146
len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE :
255147
strlen(typ->tp_name);
@@ -262,19 +154,14 @@ structseq_repr(PyStructSequence *obj)
262154
char *cname, *crepr;
263155

264156
cname = typ->tp_members[i].name;
265-
266-
val = PyTuple_GetItem(tup, i);
267-
if (cname == NULL || val == NULL) {
157+
if (cname == NULL)
268158
return NULL;
269-
}
159+
val = PyStructSequence_GET_ITEM(obj, i);
270160
repr = PyObject_Repr(val);
271-
if (repr == NULL) {
272-
Py_DECREF(tup);
161+
if (repr == NULL)
273162
return NULL;
274-
}
275163
crepr = _PyUnicode_AsString(repr);
276164
if (crepr == NULL) {
277-
Py_DECREF(tup);
278165
Py_DECREF(repr);
279166
return NULL;
280167
}
@@ -300,7 +187,6 @@ structseq_repr(PyStructSequence *obj)
300187
break;
301188
}
302189
}
303-
Py_DECREF(tup);
304190
if (removelast) {
305191
/* overwrite last ", " */
306192
pbuf-=2;
@@ -311,62 +197,6 @@ structseq_repr(PyStructSequence *obj)
311197
return PyUnicode_FromString(buf);
312198
}
313199

314-
static PyObject *
315-
structseq_concat(PyStructSequence *obj, PyObject *b)
316-
{
317-
PyObject *tup, *result;
318-
tup = make_tuple(obj);
319-
result = PySequence_Concat(tup, b);
320-
Py_DECREF(tup);
321-
return result;
322-
}
323-
324-
static PyObject *
325-
structseq_repeat(PyStructSequence *obj, Py_ssize_t n)
326-
{
327-
PyObject *tup, *result;
328-
tup = make_tuple(obj);
329-
result = PySequence_Repeat(tup, n);
330-
Py_DECREF(tup);
331-
return result;
332-
}
333-
334-
static int
335-
structseq_contains(PyStructSequence *obj, PyObject *o)
336-
{
337-
PyObject *tup;
338-
int result;
339-
tup = make_tuple(obj);
340-
if (!tup)
341-
return -1;
342-
result = PySequence_Contains(tup, o);
343-
Py_DECREF(tup);
344-
return result;
345-
}
346-
347-
static long
348-
structseq_hash(PyObject *obj)
349-
{
350-
PyObject *tup;
351-
long result;
352-
tup = make_tuple((PyStructSequence*) obj);
353-
if (!tup)
354-
return -1;
355-
result = PyObject_Hash(tup);
356-
Py_DECREF(tup);
357-
return result;
358-
}
359-
360-
static PyObject *
361-
structseq_richcompare(PyObject *obj, PyObject *o2, int op)
362-
{
363-
PyObject *tup, *result;
364-
tup = make_tuple((PyStructSequence*) obj);
365-
result = PyObject_RichCompare(tup, o2, op);
366-
Py_DECREF(tup);
367-
return result;
368-
}
369-
370200
static PyObject *
371201
structseq_reduce(PyStructSequence* self)
372202
{
@@ -409,53 +239,36 @@ structseq_reduce(PyStructSequence* self)
409239
return result;
410240
}
411241

412-
static PySequenceMethods structseq_as_sequence = {
413-
(lenfunc)structseq_length,
414-
(binaryfunc)structseq_concat, /* sq_concat */
415-
(ssizeargfunc)structseq_repeat, /* sq_repeat */
416-
(ssizeargfunc)structseq_item, /* sq_item */
417-
0, /* sq_slice */
418-
0, /* sq_ass_item */
419-
0, /* sq_ass_slice */
420-
(objobjproc)structseq_contains, /* sq_contains */
421-
};
422-
423-
static PyMappingMethods structseq_as_mapping = {
424-
(lenfunc)structseq_length,
425-
(binaryfunc)structseq_subscript,
426-
};
427-
428242
static PyMethodDef structseq_methods[] = {
429-
{"__reduce__", (PyCFunction)structseq_reduce,
430-
METH_NOARGS, NULL},
243+
{"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL},
431244
{NULL, NULL}
432245
};
433246

434247
static PyTypeObject _struct_sequence_template = {
435248
PyVarObject_HEAD_INIT(&PyType_Type, 0)
436249
NULL, /* tp_name */
437-
0, /* tp_basicsize */
438-
0, /* tp_itemsize */
439-
(destructor)structseq_dealloc, /* tp_dealloc */
250+
sizeof(PyStructSequence) - sizeof(PyObject *), /* tp_basicsize */
251+
sizeof(PyObject *), /* tp_itemsize */
252+
0, /* tp_dealloc */
440253
0, /* tp_print */
441254
0, /* tp_getattr */
442255
0, /* tp_setattr */
443256
0, /* tp_reserved */
444257
(reprfunc)structseq_repr, /* tp_repr */
445258
0, /* tp_as_number */
446-
&structseq_as_sequence, /* tp_as_sequence */
447-
&structseq_as_mapping, /* tp_as_mapping */
448-
structseq_hash, /* tp_hash */
259+
0, /* tp_as_sequence */
260+
0, /* tp_as_mapping */
261+
0, /* tp_hash */
449262
0, /* tp_call */
450263
0, /* tp_str */
451264
0, /* tp_getattro */
452265
0, /* tp_setattro */
453266
0, /* tp_as_buffer */
454-
Py_TPFLAGS_DEFAULT, /* tp_flags */
267+
Py_TPFLAGS_DEFAULT, /* tp_flags */
455268
NULL, /* tp_doc */
456269
0, /* tp_traverse */
457270
0, /* tp_clear */
458-
structseq_richcompare, /* tp_richcompare */
271+
0, /* tp_richcompare */
459272
0, /* tp_weaklistoffset */
460273
0, /* tp_iter */
461274
0, /* tp_iternext */
@@ -494,11 +307,9 @@ PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
494307
n_members = i;
495308

496309
memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));
310+
type->tp_base = &PyTuple_Type;
497311
type->tp_name = desc->name;
498312
type->tp_doc = desc->doc;
499-
type->tp_basicsize = sizeof(PyStructSequence)+
500-
sizeof(PyObject*)*(n_members-1);
501-
type->tp_itemsize = 0;
502313

503314
members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);
504315
if (members == NULL)

0 commit comments

Comments
 (0)