]> granicus.if.org Git - python/commitdiff
Merged revisions 77763 via svnmerge from
authorEric Smith <eric@trueblade.com>
Wed, 27 Jan 2010 00:44:57 +0000 (00:44 +0000)
committerEric Smith <eric@trueblade.com>
Wed, 27 Jan 2010 00:44:57 +0000 (00:44 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r77763 | eric.smith | 2010-01-26 19:28:29 -0500 (Tue, 26 Jan 2010) | 1 line

  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.
........

Doc/library/sys.rst
Lib/test/test_sys.py
Misc/NEWS
Python/sysmodule.c

index 33910ae3e8659462ed4e4d0dfafba7efb43908f6..1278248188e0383b66a3520b0e3ecf29ce1f119c 100644 (file)
@@ -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
 
index a4e646f36315f9d51839b63ce25baee4b0207e2d..65b4430e140d56d51d1f00d83a92bce6970a692c 100644 (file)
@@ -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)
index 8318f092d52c57a1a15e5e707f0e26228ea772f6..2e12ffef08f16bd2deec32267d6a54c5b89418a2 100644 (file)
--- 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
index 84813baee5d2a16e2913cce26c78baf4ff3f09a3..f1cbbba48b7e77cd28a8af2977b9a912aa753fd1 100644 (file)
@@ -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",