[Python-checkins] CVS: python/dist/src/Objects structseq.c,1.3.6.1,1.3.6.2
Michael Hudson
mwh@users.sourceforge.net
Thu, 07 Mar 2002 02:16:45 -0800
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv22453
Modified Files:
Tag: release22-maint
structseq.c
Log Message:
After some thinking, I decided to move all of this across onto
the branch. I don't think it can break code, so the only risk
is introducing new bugs. In that vein, can I ask -checkins readers
who have time to carefully look this over, check my refcounts &c?
TIA.
backport my checkin of
revision 1.5 of structseq.c
Apply (my) patch:
[ 526072 ] pickling os.stat results round II
structseq's constructors can now take "invisible" fields in a dict.
Gave the constructors better error messages.
their __reduce__ method puts these fields in a dict.
(this is all in aid of getting os.stat_result's to pickle portably)
Also fixes
[ 526039 ] devious code can crash structseqs
Thought needed about how much of this counts as a bugfix. Certainly
#526039 needs to be fixed.
Index: structseq.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/structseq.c,v
retrieving revision 1.3.6.1
retrieving revision 1.3.6.2
diff -C2 -d -r1.3.6.1 -r1.3.6.2
*** structseq.c 5 Mar 2002 14:00:52 -0000 1.3.6.1
--- structseq.c 7 Mar 2002 10:16:43 -0000 1.3.6.2
***************
*** 85,121 ****
{
PyObject *arg = NULL;
PyStructSequence *res = NULL;
! int len, required_len, i;
! static char *kwlist[] = {"sequence", 0};
! static char msgbuf[128];
! if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:structseq",
! kwlist, &arg))
return NULL;
! if (!PySequence_Check(arg)) {
! PyErr_SetString(PyExc_TypeError,
! "constructor requires a sequence");
return NULL;
}
! len = PySequence_Length(arg);
! required_len = REAL_SIZE_TP(type);
! if (len != required_len) {
! PyOS_snprintf(
! msgbuf, sizeof(msgbuf),
! "constructor takes exactly %d arguments (%d given)",
! required_len,
! len);
! PyErr_SetString(PyExc_TypeError, msgbuf);
return NULL;
}
res = (PyStructSequence*) PyStructSequence_New(type);
for (i = 0; i < len; ++i) {
! /* INCREF???? XXXX */
! res->ob_item[i] = PySequence_GetItem(arg, i);
}
return (PyObject*) res;
}
--- 85,161 ----
{
PyObject *arg = NULL;
+ PyObject *dict = NULL;
+ PyObject *ob;
PyStructSequence *res = NULL;
! int len, min_len, max_len, i;
! 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");
!
! if (!arg) {
return NULL;
}
! if (dict && !PyDict_Check(dict)) {
! PyErr_Format(PyExc_TypeError,
! "%.500s() takes a dict as second arg, if any",
! type->tp_name);
! Py_DECREF(arg);
return NULL;
}
+ len = PySequence_Fast_GET_SIZE(arg);
+ min_len = VISIBLE_SIZE_TP(type);
+ max_len = REAL_SIZE_TP(type);
+
+ if (min_len != max_len) {
+ if (len < min_len) {
+ PyErr_Format(PyExc_TypeError,
+ "%.500s() takes an at least %d-sequence (%d-sequence given)",
+ type->tp_name, min_len, len);
+ Py_DECREF(arg);
+ return NULL;
+ }
+
+ if (len > max_len) {
+ PyErr_Format(PyExc_TypeError,
+ "%.500s() takes an at most %d-sequence (%d-sequence given)",
+ type->tp_name, max_len, len);
+ Py_DECREF(arg);
+ return NULL;
+ }
+ }
+ else {
+ if (len != min_len) {
+ PyErr_Format(PyExc_TypeError,
+ "%.500s() takes a %d-sequence (%d-sequence given)",
+ type->tp_name, min_len, len);
+ Py_DECREF(arg);
+ return NULL;
+ }
+ }
+
res = (PyStructSequence*) PyStructSequence_New(type);
for (i = 0; i < len; ++i) {
! PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
! Py_INCREF(v);
! res->ob_item[i] = v;
! }
! for (; i < max_len; ++i) {
! if (dict && (ob = PyDict_GetItemString(
! dict, type->tp_members[i].name))) {
! }
! else {
! ob = Py_None;
! }
! Py_INCREF(ob);
! res->ob_item[i] = ob;
}
+ Py_DECREF(arg);
return (PyObject*) res;
}
***************
*** 193,211 ****
{
PyObject* tup;
! long n_fields;
int i;
n_fields = REAL_SIZE(self);
! tup = PyTuple_New(n_fields);
if (!tup) {
return NULL;
}
! for (i = 0; i < n_fields; i++) {
Py_INCREF(self->ob_item[i]);
PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
}
! return Py_BuildValue("(O(O))", self->ob_type, tup);
}
--- 233,264 ----
{
PyObject* tup;
! PyObject* dict;
! long n_fields, n_visible_fields;
int i;
n_fields = REAL_SIZE(self);
! n_visible_fields = VISIBLE_SIZE(self);
! tup = PyTuple_New(n_visible_fields);
if (!tup) {
return NULL;
}
! dict = PyDict_New();
! 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_fields; i++) {
! PyDict_SetItemString(dict, self->ob_type->tp_members[i].name,
! self->ob_item[i]);
! }
!
! return Py_BuildValue("(O(OO))", self->ob_type, tup, dict);
}