@@ -1017,7 +1017,7 @@ maxunicode -- the largest supported character\n\
10171017builtin_module_names -- tuple of module names built into this interpreter\n\
10181018subversion -- subversion information of the build as tuple\n\
10191019version -- the version of this interpreter as a string\n\
1020- version_info -- version information as a tuple\n\
1020+ version_info -- version information as a named tuple\n\
10211021hexversion -- version information encoded as a single integer\n\
10221022copyright -- copyright notice pertaining to this interpreter\n\
10231023platform -- platform identifier\n\
@@ -1227,6 +1227,75 @@ make_flags(void)
12271227 return seq ;
12281228}
12291229
1230+ PyDoc_STRVAR (version_info__doc__ ,
1231+ "sys.version_info\n\
1232+ \n\
1233+ Version information as a named tuple." );
1234+
1235+ static PyTypeObject VersionInfoType ;
1236+
1237+ static PyStructSequence_Field version_info_fields [] = {
1238+ {"major" , "Major release number" },
1239+ {"minor" , "Minor release number" },
1240+ {"micro" , "Patch release number" },
1241+ {"releaselevel" , "'alpha', 'beta', 'candidate', or 'release'" },
1242+ {"serial" , "Serial release number" },
1243+ {0 }
1244+ };
1245+
1246+ static PyStructSequence_Desc version_info_desc = {
1247+ "sys.version_info" , /* name */
1248+ version_info__doc__ , /* doc */
1249+ version_info_fields , /* fields */
1250+ 5
1251+ };
1252+
1253+ static PyObject *
1254+ make_version_info (void )
1255+ {
1256+ PyObject * version_info ;
1257+ char * s ;
1258+ int pos = 0 ;
1259+
1260+ version_info = PyStructSequence_New (& VersionInfoType );
1261+ if (version_info == NULL ) {
1262+ return NULL ;
1263+ }
1264+
1265+ /*
1266+ * These release level checks are mutually exclusive and cover
1267+ * the field, so don't get too fancy with the pre-processor!
1268+ */
1269+ #if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_ALPHA
1270+ s = "alpha" ;
1271+ #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_BETA
1272+ s = "beta" ;
1273+ #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_GAMMA
1274+ s = "candidate" ;
1275+ #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_FINAL
1276+ s = "final" ;
1277+ #endif
1278+
1279+ #define SetIntItem (flag ) \
1280+ PyStructSequence_SET_ITEM(version_info, pos++, PyLong_FromLong(flag))
1281+ #define SetStrItem (flag ) \
1282+ PyStructSequence_SET_ITEM(version_info, pos++, PyUnicode_FromString(flag))
1283+
1284+ SetIntItem (PY_MAJOR_VERSION );
1285+ SetIntItem (PY_MINOR_VERSION );
1286+ SetIntItem (PY_MICRO_VERSION );
1287+ SetStrItem (s );
1288+ SetIntItem (PY_RELEASE_SERIAL );
1289+ #undef SetIntItem
1290+ #undef SetStrItem
1291+
1292+ if (PyErr_Occurred ()) {
1293+ Py_CLEAR (version_info );
1294+ return NULL ;
1295+ }
1296+ return version_info ;
1297+ }
1298+
12301299static struct PyModuleDef sysmodule = {
12311300 PyModuleDef_HEAD_INIT ,
12321301 "sys" ,
@@ -1239,8 +1308,6 @@ static struct PyModuleDef sysmodule = {
12391308 NULL
12401309};
12411310
1242-
1243-
12441311PyObject *
12451312_PySys_Init (void )
12461313{
@@ -1291,25 +1358,6 @@ _PySys_Init(void)
12911358 svn_revision ));
12921359 SET_SYS_FROM_STRING ("dont_write_bytecode" ,
12931360 PyBool_FromLong (Py_DontWriteBytecodeFlag ));
1294- /*
1295- * These release level checks are mutually exclusive and cover
1296- * the field, so don't get too fancy with the pre-processor!
1297- */
1298- #if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_ALPHA
1299- s = "alpha" ;
1300- #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_BETA
1301- s = "beta" ;
1302- #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_GAMMA
1303- s = "candidate" ;
1304- #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_FINAL
1305- s = "final" ;
1306- #endif
1307-
1308- SET_SYS_FROM_STRING ("version_info" ,
1309- Py_BuildValue ("iiiUi" , PY_MAJOR_VERSION ,
1310- PY_MINOR_VERSION ,
1311- PY_MICRO_VERSION , s ,
1312- PY_RELEASE_SERIAL ));
13131361 SET_SYS_FROM_STRING ("api_version" ,
13141362 PyLong_FromLong (PYTHON_API_VERSION ));
13151363 SET_SYS_FROM_STRING ("copyright" ,
@@ -1361,6 +1409,15 @@ _PySys_Init(void)
13611409 PyDict_SetItemString (sysdict , "warnoptions" , warnoptions );
13621410 }
13631411
1412+ /* version_info */
1413+ if (VersionInfoType .tp_name == 0 )
1414+ PyStructSequence_InitType (& VersionInfoType , & version_info_desc );
1415+ SET_SYS_FROM_STRING ("version_info" , make_version_info ());
1416+ /* prevent user from creating new instances */
1417+ VersionInfoType .tp_init = NULL ;
1418+ VersionInfoType .tp_new = NULL ;
1419+
1420+ /* flags */
13641421 if (FlagsType .tp_name == 0 )
13651422 PyStructSequence_InitType (& FlagsType , & flags_desc );
13661423 SET_SYS_FROM_STRING ("flags" , make_flags ());
0 commit comments