Skip to content

Commit 1745732

Browse files
committed
fix repr of complicated structseqs #9206
1 parent a767a7c commit 1745732

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

Lib/test/test_structseq.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import os
2+
import time
13
import unittest
24
from test import support
35

4-
import time
56

67
class StructSeqTest(unittest.TestCase):
78

@@ -34,6 +35,13 @@ def test_repr(self):
3435
self.assertEqual(repr(t),
3536
"time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, "
3637
"tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)")
38+
# os.stat() gives a complicated struct sequence.
39+
st = os.stat(__file__)
40+
rep = repr(st)
41+
self.assertTrue(rep.startswith("posix.stat_result"))
42+
self.assertIn("st_mode=", rep)
43+
self.assertIn("st_ino=", rep)
44+
self.assertIn("st_dev=", rep)
3745

3846
def test_concat(self):
3947
t1 = time.gmtime()

Objects/structseq.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,27 @@ PyStructSequence_New(PyTypeObject *type)
3535
obj = PyObject_GC_NewVar(PyStructSequence, type, size);
3636
if (obj == NULL)
3737
return NULL;
38+
/* Hack the size of the variable object, so invisible fields don't appear
39+
to Python code. */
40+
Py_SIZE(obj) = VISIBLE_SIZE_TP(type);
3841
for (i = 0; i < size; i++)
3942
obj->ob_item[i] = NULL;
4043

4144
return (PyObject*)obj;
4245
}
4346

47+
static void
48+
structseq_dealloc(PyStructSequence *obj)
49+
{
50+
Py_ssize_t i, size;
51+
52+
size = REAL_SIZE(obj);
53+
for (i = 0; i < size; ++i) {
54+
Py_XDECREF(obj->ob_item[i]);
55+
}
56+
PyObject_GC_Del(obj);
57+
}
58+
4459
static PyObject *
4560
structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
4661
{
@@ -154,8 +169,11 @@ structseq_repr(PyStructSequence *obj)
154169
char *cname, *crepr;
155170

156171
cname = typ->tp_members[i].name;
157-
if (cname == NULL)
172+
if (cname == NULL) {
173+
PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %d name is NULL"
174+
" for type %.500s", i, typ->tp_name);
158175
return NULL;
176+
}
159177
val = PyStructSequence_GET_ITEM(obj, i);
160178
repr = PyObject_Repr(val);
161179
if (repr == NULL)
@@ -249,7 +267,7 @@ static PyTypeObject _struct_sequence_template = {
249267
NULL, /* tp_name */
250268
sizeof(PyStructSequence) - sizeof(PyObject *), /* tp_basicsize */
251269
sizeof(PyObject *), /* tp_itemsize */
252-
0, /* tp_dealloc */
270+
(destructor)structseq_dealloc, /* tp_dealloc */
253271
0, /* tp_print */
254272
0, /* tp_getattr */
255273
0, /* tp_setattr */

0 commit comments

Comments
 (0)