summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/sys.rst35
-rw-r--r--Lib/test/test_sys.py18
-rw-r--r--Misc/NEWS5
-rw-r--r--Python/sysmodule.c75
4 files changed, 114 insertions, 19 deletions
diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst
index 33910ae..1278248 100644
--- a/Doc/library/sys.rst
+++ b/Doc/library/sys.rst
@@ -394,9 +394,15 @@ always available.
.. function:: getwindowsversion()
- Return a tuple containing five components, describing the Windows version
- currently running. The elements are *major*, *minor*, *build*, *platform*, and
- *text*. *text* contains a string while all other values are integers.
+ Return a named tuple containing describing the Windows version
+ currently running. The named elements are *major*, *minor*,
+ *build*, *platform*, *service_pack*, *service_pack_minor*,
+ *service_pack_major*, *suite_mask*, and *product_type*.
+ *service_pack* contains a string while all other values are
+ integers. The components can also be accessed by name, so
+ ``sys.getwindowsversion()[0]`` is equivalent to
+ ``sys.getwindowsversion().major``. For compatibility with prior
+ versions, only the first 5 elements are retrievable by indexing.
*platform* may be one of the following values:
@@ -412,11 +418,30 @@ always available.
| :const:`3 (VER_PLATFORM_WIN32_CE)` | Windows CE |
+-----------------------------------------+-------------------------+
- This function wraps the Win32 :cfunc:`GetVersionEx` function; see the Microsoft
- documentation for more information about these fields.
+ *product_type* may be one of the following values:
+
+ +---------------------------------------+---------------------------------+
+ | Constant | Meaning |
+ +=======================================+=================================+
+ | :const:`1 (VER_NT_WORKSTATION)` | The system is a workstation. |
+ +---------------------------------------+---------------------------------+
+ | :const:`2 (VER_NT_DOMAIN_CONTROLLER)` | The system is a domain |
+ | | controller. |
+ +---------------------------------------+---------------------------------+
+ | :const:`3 (VER_NT_SERVER)` | The system is a server, but not |
+ | | a domain controller. |
+ +---------------------------------------+---------------------------------+
+
+
+ This function wraps the Win32 :cfunc:`GetVersionEx` function; see the
+ Microsoft documentation on :cfunc:`OSVERSIONINFOEX` for more information
+ about these fields.
Availability: Windows.
+ .. versionchanged:: 2.7
+ Changed to a named tuple and added *service_pack_minor*,
+ *service_pack_major*, *suite_mask*, and *product_type*.
.. data:: hexversion
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index a4e646f..65b4430 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -5,6 +5,7 @@ import struct
import subprocess
import textwrap
import warnings
+import operator
# count the number of test runs, used to create unique
# strings to intern in test_intern()
@@ -227,13 +228,28 @@ class SysModuleTest(unittest.TestCase):
def test_getwindowsversion(self):
if hasattr(sys, "getwindowsversion"):
v = sys.getwindowsversion()
- self.assertIsInstance(v, tuple)
+ self.assertTrue(isinstance(v[:], tuple))
self.assertEqual(len(v), 5)
self.assertIsInstance(v[0], int)
self.assertIsInstance(v[1], int)
self.assertIsInstance(v[2], int)
self.assertIsInstance(v[3], int)
self.assertIsInstance(v[4], str)
+ self.assertRaises(IndexError, operator.getitem, v, 5)
+ self.assertIsInstance(v.major, int)
+ self.assertIsInstance(v.minor, int)
+ self.assertIsInstance(v.build, int)
+ self.assertIsInstance(v.platform, int)
+ self.assertIsInstance(v.service_pack, str)
+ self.assertEqual(v[0], v.major)
+ self.assertEqual(v[1], v.minor)
+ self.assertEqual(v[2], v.build)
+ self.assertEqual(v[3], v.platform)
+ self.assertEqual(v[4], v.service_pack)
+
+ # This is how platform.py calls it. Make sure tuple
+ # still has 5 elements
+ maj, min, buildno, plat, csd = sys.getwindowsversion()
def test_call_tracing(self):
self.assertRaises(TypeError, sys.call_tracing, type, 2)
diff --git a/Misc/NEWS b/Misc/NEWS
index 8318f09..2e12ffe 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,11 @@ What's New in Python 3.2 Alpha 1?
Core and Builtins
-----------------
+- Issue #7766: Change sys.getwindowsversion() return value to a named
+ tuple and add the additional members returned in an OSVERSIONINFOEX
+ structure. The new members are service_pack_major, service_pack_minor,
+ suite_mask, and product_type.
+
- Issue #7561: Operations on empty bytearrays (such as `int(bytearray())`)
could crash in many places because of the PyByteArray_AS_STRING() macro
returning NULL. The macro now returns a statically allocated empty
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 84813ba..f1cbbba 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -597,26 +597,65 @@ recursion from causing an overflow of the C stack and crashing Python."
PyDoc_STRVAR(getwindowsversion_doc,
"getwindowsversion()\n\
\n\
-Return information about the running version of Windows.\n\
-The result is a tuple of (major, minor, build, platform, text)\n\
-All elements are numbers, except text which is a string.\n\
-Platform may be 0 for win32s, 1 for Windows 9x/ME, 2 for Windows NT/2000/XP\n\
-"
+Return information about the running version of Windows as a named tuple.\n\
+The members are named: major, minor, build, platform, service_pack,\n\
+service_pack_major, service_pack_minor, suite_mask, and product_type. For\n\
+backward compatibiliy, only the first 5 items are available by indexing.\n\
+All elements are numbers, except service_pack which is a string. Platform\n\
+may be 0 for win32s, 1 for Windows 9x/ME, 2 for Windows NT/2000/XP/Vista/7,\n\
+3 for Windows CE. Product_type may be 1 for a workstation, 2 for a domain\n\
+controller, 3 for a server."
);
+static PyTypeObject WindowsVersionType = {0, 0, 0, 0, 0, 0};
+
+static PyStructSequence_Field windows_version_fields[] = {
+ {"major", "Major version number"},
+ {"minor", "Minor version number"},
+ {"build", "Build number"},
+ {"platform", "Operating system platform"},
+ {"service_pack", "Latest Service Pack installed on the system"},
+ {"service_pack_major", "Service Pack major version number"},
+ {"service_pack_minor", "Service Pack minor version number"},
+ {"suite_mask", "Bit mask identifying available product suites"},
+ {"product_type", "System product type"},
+ {0}
+};
+
+static PyStructSequence_Desc windows_version_desc = {
+ "sys.getwindowsversion", /* name */
+ getwindowsversion_doc, /* doc */
+ windows_version_fields, /* fields */
+ 5 /* For backward compatibility,
+ only the first 5 items are accessible
+ via indexing, the rest are name only */
+};
+
static PyObject *
sys_getwindowsversion(PyObject *self)
{
- OSVERSIONINFO ver;
+ PyObject *version;
+ int pos = 0;
+ OSVERSIONINFOEX ver;
ver.dwOSVersionInfoSize = sizeof(ver);
- if (!GetVersionEx(&ver))
+ if (!GetVersionEx((OSVERSIONINFO*) &ver))
return PyErr_SetFromWindowsErr(0);
- return Py_BuildValue("HHHHs",
- ver.dwMajorVersion,
- ver.dwMinorVersion,
- ver.dwBuildNumber,
- ver.dwPlatformId,
- ver.szCSDVersion);
+
+ version = PyStructSequence_New(&WindowsVersionType);
+ if (version == NULL)
+ return NULL;
+
+ PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMajorVersion));
+ PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMinorVersion));
+ PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwBuildNumber));
+ PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwPlatformId));
+ PyStructSequence_SET_ITEM(version, pos++, PyUnicode_FromString(ver.szCSDVersion));
+ PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMajor));
+ PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMinor));
+ PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask));
+ PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType));
+
+ return version;
}
#endif /* MS_WINDOWS */
@@ -1488,6 +1527,16 @@ _PySys_Init(void)
FlagsType.tp_init = NULL;
FlagsType.tp_new = NULL;
+
+#if defined(MS_WINDOWS)
+ /* getwindowsversion */
+ if (WindowsVersionType.tp_name == 0)
+ PyStructSequence_InitType(&WindowsVersionType, &windows_version_desc);
+ /* prevent user from creating new instances */
+ WindowsVersionType.tp_init = NULL;
+ WindowsVersionType.tp_new = NULL;
+#endif
+
/* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */
#ifndef PY_NO_SHORT_FLOAT_REPR
SET_SYS_FROM_STRING("float_repr_style",