Merged revisions 69331 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r69331 | eric.smith | 2009-02-05 19:48:26 -0500 (Thu, 05 Feb 2009) | 2 lines

  Implement issue #4285, convert sys.version_info to a named
  tuple. Patch by Ross Light.
........
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index f703e09..b47a25b 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -1017,7 +1017,7 @@
 builtin_module_names -- tuple of module names built into this interpreter\n\
 subversion -- subversion information of the build as tuple\n\
 version -- the version of this interpreter as a string\n\
-version_info -- version information as a tuple\n\
+version_info -- version information as a named tuple\n\
 hexversion -- version information encoded as a single integer\n\
 copyright -- copyright notice pertaining to this interpreter\n\
 platform -- platform identifier\n\
@@ -1227,6 +1227,75 @@
 	return seq;
 }
 
+PyDoc_STRVAR(version_info__doc__,
+"sys.version_info\n\
+\n\
+Version information as a named tuple.");
+
+static PyTypeObject VersionInfoType;
+
+static PyStructSequence_Field version_info_fields[] = {
+	{"major", "Major release number"},
+	{"minor", "Minor release number"},
+	{"micro", "Patch release number"},
+	{"releaselevel", "'alpha', 'beta', 'candidate', or 'release'"},
+	{"serial", "Serial release number"},
+	{0}
+};
+
+static PyStructSequence_Desc version_info_desc = {
+	"sys.version_info",     /* name */
+	version_info__doc__,    /* doc */
+	version_info_fields,    /* fields */
+	5
+};
+
+static PyObject *
+make_version_info(void)
+{
+	PyObject *version_info;
+	char *s;
+	int pos = 0;
+
+	version_info = PyStructSequence_New(&VersionInfoType);
+	if (version_info == NULL) {
+		return NULL;
+	}
+
+	/*
+	 * These release level checks are mutually exclusive and cover
+	 * the field, so don't get too fancy with the pre-processor!
+	 */
+#if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_ALPHA
+	s = "alpha";
+#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_BETA
+	s = "beta";
+#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_GAMMA
+	s = "candidate";
+#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_FINAL
+	s = "final";
+#endif
+
+#define SetIntItem(flag) \
+	PyStructSequence_SET_ITEM(version_info, pos++, PyLong_FromLong(flag))
+#define SetStrItem(flag) \
+	PyStructSequence_SET_ITEM(version_info, pos++, PyUnicode_FromString(flag))
+
+	SetIntItem(PY_MAJOR_VERSION);
+	SetIntItem(PY_MINOR_VERSION);
+	SetIntItem(PY_MICRO_VERSION);
+	SetStrItem(s);
+	SetIntItem(PY_RELEASE_SERIAL);
+#undef SetIntItem
+#undef SetStrItem
+
+	if (PyErr_Occurred()) {
+		Py_CLEAR(version_info);
+		return NULL;
+	}
+	return version_info;
+}
+
 static struct PyModuleDef sysmodule = {
 	PyModuleDef_HEAD_INIT,
 	"sys",
@@ -1239,8 +1308,6 @@
 	NULL
 };
 
-
-
 PyObject *
 _PySys_Init(void)
 {
@@ -1291,25 +1358,6 @@
 					  svn_revision));
 	SET_SYS_FROM_STRING("dont_write_bytecode",
 			     PyBool_FromLong(Py_DontWriteBytecodeFlag));
-	/*
-	 * These release level checks are mutually exclusive and cover
-	 * the field, so don't get too fancy with the pre-processor!
-	 */
-#if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_ALPHA
-	s = "alpha";
-#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_BETA
-	s = "beta";
-#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_GAMMA
-	s = "candidate";
-#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_FINAL
-	s = "final";
-#endif
-
-	SET_SYS_FROM_STRING("version_info",
-			    Py_BuildValue("iiiUi", PY_MAJOR_VERSION,
-					       PY_MINOR_VERSION,
-					       PY_MICRO_VERSION, s,
-					       PY_RELEASE_SERIAL));
 	SET_SYS_FROM_STRING("api_version",
 			    PyLong_FromLong(PYTHON_API_VERSION));
 	SET_SYS_FROM_STRING("copyright",
@@ -1361,6 +1409,15 @@
 		PyDict_SetItemString(sysdict, "warnoptions", warnoptions);
 	}
 
+	/* version_info */
+	if (VersionInfoType.tp_name == 0)
+		PyStructSequence_InitType(&VersionInfoType, &version_info_desc);
+	SET_SYS_FROM_STRING("version_info", make_version_info());
+	/* prevent user from creating new instances */
+	VersionInfoType.tp_init = NULL;
+	VersionInfoType.tp_new = NULL;
+
+	/* flags */
 	if (FlagsType.tp_name == 0)
 		PyStructSequence_InitType(&FlagsType, &flags_desc);
 	SET_SYS_FROM_STRING("flags", make_flags());