SF patch #462296: Add attributes to os.stat results; by Nick Mathewson.

This is a big one, touching lots of files.  Some of the platforms
aren't tested yet.  Briefly, this changes the return value of the
os/posix functions stat(), fstat(), statvfs(), fstatvfs(), and the
time functions localtime(), gmtime(), and strptime() from tuples into
pseudo-sequences.  When accessed as a sequence, they behave exactly as
before.  But they also have attributes like st_mtime or tm_year.  The
stat return value, moreover, has a few platform-specific attributes
that are not available through the sequence interface (because
everybody expects the sequence to have a fixed length, these couldn't
be added there).  If your platform's struct stat doesn't define
st_blksize, st_blocks or st_rdev, they won't be accessible from Python
either.

(Still missing is a documentation update.)
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 2834738..bb7f358 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -2,6 +2,7 @@
 /* Time module */
 
 #include "Python.h"
+#include "structseq.h"
 
 #include <ctype.h>
 
@@ -210,19 +211,53 @@
 Delay execution for a given number of seconds.  The argument may be\n\
 a floating point number for subsecond precision.";
 
+static PyStructSequence_Field struct_time_type_fields[] = {
+	{"tm_year", NULL},
+	{"tm_mon", NULL},
+	{"tm_mday", NULL},
+	{"tm_hour", NULL},
+	{"tm_min", NULL},
+	{"tm_sec", NULL},
+	{"tm_wday", NULL},
+	{"tm_yday", NULL},
+	{"tm_isdst", NULL},
+	{0}
+};
+
+static PyStructSequence_Desc struct_time_type_desc = {
+	"struct_time",
+	NULL,
+	struct_time_type_fields,
+	9,
+};
+	
+static PyTypeObject StructTimeType;
+
 static PyObject *
 tmtotuple(struct tm *p)
 {
-	return Py_BuildValue("(iiiiiiiii)",
-			     p->tm_year + 1900,
-			     p->tm_mon + 1,	   /* Want January == 1 */
-			     p->tm_mday,
-			     p->tm_hour,
-			     p->tm_min,
-			     p->tm_sec,
-			     (p->tm_wday + 6) % 7, /* Want Monday == 0 */
-			     p->tm_yday + 1,	   /* Want January, 1 == 1 */
-			     p->tm_isdst);
+	PyObject *v = PyStructSequence_New(&StructTimeType);
+	if (v == NULL)
+		return NULL;
+	
+#define SET(i,val) PyStructSequence_SET_ITEM(v, i, PyInt_FromLong((long) val))
+
+	SET(0, p->tm_year + 1900);
+	SET(1, p->tm_mon + 1);	   /* Want January == 1 */
+	SET(2, p->tm_mday);
+	SET(3, p->tm_hour);
+	SET(4, p->tm_min);
+	SET(5, p->tm_sec);
+	SET(6, (p->tm_wday + 6) % 7); /* Want Monday == 0 */
+	SET(7, p->tm_yday + 1);	   /* Want January, 1 == 1 */
+	SET(8, p->tm_isdst);
+#undef SET
+	if (PyErr_Occurred()) {
+		Py_XDECREF(v);
+		return NULL;
+	}
+
+	return v;
 }
 
 static PyObject *
@@ -674,6 +709,9 @@
 	ins(d, "tzname", Py_BuildValue("(zz)", _tzname[0], _tzname[1]));
 #endif /* __CYGWIN__ */
 #endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
+
+        PyStructSequence_InitType(&StructTimeType, &struct_time_type_desc);
+	PyDict_SetItemString(d, "struct_time", (PyObject*) &StructTimeType);
 }
 
 
@@ -852,5 +890,6 @@
 #endif /* !__WATCOMC__ || __QNX__ */
 #endif /* !macintosh */
 #endif /* !HAVE_SELECT */
+
 	return 0;
 }