Skip to content

Commit f7bb578

Browse files
committed
Merged revisions 77763 via svnmerge from
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. ........
1 parent 38f0033 commit f7bb578

4 files changed

Lines changed: 114 additions & 19 deletions

File tree

Doc/library/sys.rst

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,15 @@ always available.
394394

395395
.. function:: getwindowsversion()
396396

397-
Return a tuple containing five components, describing the Windows version
398-
currently running. The elements are *major*, *minor*, *build*, *platform*, and
399-
*text*. *text* contains a string while all other values are integers.
397+
Return a named tuple containing describing the Windows version
398+
currently running. The named elements are *major*, *minor*,
399+
*build*, *platform*, *service_pack*, *service_pack_minor*,
400+
*service_pack_major*, *suite_mask*, and *product_type*.
401+
*service_pack* contains a string while all other values are
402+
integers. The components can also be accessed by name, so
403+
``sys.getwindowsversion()[0]`` is equivalent to
404+
``sys.getwindowsversion().major``. For compatibility with prior
405+
versions, only the first 5 elements are retrievable by indexing.
400406

401407
*platform* may be one of the following values:
402408

@@ -412,11 +418,30 @@ always available.
412418
| :const:`3 (VER_PLATFORM_WIN32_CE)` | Windows CE |
413419
+-----------------------------------------+-------------------------+
414420

415-
This function wraps the Win32 :cfunc:`GetVersionEx` function; see the Microsoft
416-
documentation for more information about these fields.
421+
*product_type* may be one of the following values:
422+
423+
+---------------------------------------+---------------------------------+
424+
| Constant | Meaning |
425+
+=======================================+=================================+
426+
| :const:`1 (VER_NT_WORKSTATION)` | The system is a workstation. |
427+
+---------------------------------------+---------------------------------+
428+
| :const:`2 (VER_NT_DOMAIN_CONTROLLER)` | The system is a domain |
429+
| | controller. |
430+
+---------------------------------------+---------------------------------+
431+
| :const:`3 (VER_NT_SERVER)` | The system is a server, but not |
432+
| | a domain controller. |
433+
+---------------------------------------+---------------------------------+
434+
435+
436+
This function wraps the Win32 :cfunc:`GetVersionEx` function; see the
437+
Microsoft documentation on :cfunc:`OSVERSIONINFOEX` for more information
438+
about these fields.
417439

418440
Availability: Windows.
419441

442+
.. versionchanged:: 2.7
443+
Changed to a named tuple and added *service_pack_minor*,
444+
*service_pack_major*, *suite_mask*, and *product_type*.
420445

421446
.. data:: hexversion
422447

Lib/test/test_sys.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import subprocess
66
import textwrap
77
import warnings
8+
import operator
89

910
# count the number of test runs, used to create unique
1011
# strings to intern in test_intern()
@@ -227,13 +228,28 @@ def f():
227228
def test_getwindowsversion(self):
228229
if hasattr(sys, "getwindowsversion"):
229230
v = sys.getwindowsversion()
230-
self.assertIsInstance(v, tuple)
231+
self.assertTrue(isinstance(v[:], tuple))
231232
self.assertEqual(len(v), 5)
232233
self.assertIsInstance(v[0], int)
233234
self.assertIsInstance(v[1], int)
234235
self.assertIsInstance(v[2], int)
235236
self.assertIsInstance(v[3], int)
236237
self.assertIsInstance(v[4], str)
238+
self.assertRaises(IndexError, operator.getitem, v, 5)
239+
self.assertIsInstance(v.major, int)
240+
self.assertIsInstance(v.minor, int)
241+
self.assertIsInstance(v.build, int)
242+
self.assertIsInstance(v.platform, int)
243+
self.assertIsInstance(v.service_pack, str)
244+
self.assertEqual(v[0], v.major)
245+
self.assertEqual(v[1], v.minor)
246+
self.assertEqual(v[2], v.build)
247+
self.assertEqual(v[3], v.platform)
248+
self.assertEqual(v[4], v.service_pack)
249+
250+
# This is how platform.py calls it. Make sure tuple
251+
# still has 5 elements
252+
maj, min, buildno, plat, csd = sys.getwindowsversion()
237253

238254
def test_call_tracing(self):
239255
self.assertRaises(TypeError, sys.call_tracing, type, 2)

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ What's New in Python 3.2 Alpha 1?
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #7766: Change sys.getwindowsversion() return value to a named
16+
tuple and add the additional members returned in an OSVERSIONINFOEX
17+
structure. The new members are service_pack_major, service_pack_minor,
18+
suite_mask, and product_type.
19+
1520
- Issue #7561: Operations on empty bytearrays (such as `int(bytearray())`)
1621
could crash in many places because of the PyByteArray_AS_STRING() macro
1722
returning NULL. The macro now returns a statically allocated empty

Python/sysmodule.c

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -597,26 +597,65 @@ recursion from causing an overflow of the C stack and crashing Python."
597597
PyDoc_STRVAR(getwindowsversion_doc,
598598
"getwindowsversion()\n\
599599
\n\
600-
Return information about the running version of Windows.\n\
601-
The result is a tuple of (major, minor, build, platform, text)\n\
602-
All elements are numbers, except text which is a string.\n\
603-
Platform may be 0 for win32s, 1 for Windows 9x/ME, 2 for Windows NT/2000/XP\n\
604-
"
600+
Return information about the running version of Windows as a named tuple.\n\
601+
The members are named: major, minor, build, platform, service_pack,\n\
602+
service_pack_major, service_pack_minor, suite_mask, and product_type. For\n\
603+
backward compatibiliy, only the first 5 items are available by indexing.\n\
604+
All elements are numbers, except service_pack which is a string. Platform\n\
605+
may be 0 for win32s, 1 for Windows 9x/ME, 2 for Windows NT/2000/XP/Vista/7,\n\
606+
3 for Windows CE. Product_type may be 1 for a workstation, 2 for a domain\n\
607+
controller, 3 for a server."
605608
);
606609

610+
static PyTypeObject WindowsVersionType = {0, 0, 0, 0, 0, 0};
611+
612+
static PyStructSequence_Field windows_version_fields[] = {
613+
{"major", "Major version number"},
614+
{"minor", "Minor version number"},
615+
{"build", "Build number"},
616+
{"platform", "Operating system platform"},
617+
{"service_pack", "Latest Service Pack installed on the system"},
618+
{"service_pack_major", "Service Pack major version number"},
619+
{"service_pack_minor", "Service Pack minor version number"},
620+
{"suite_mask", "Bit mask identifying available product suites"},
621+
{"product_type", "System product type"},
622+
{0}
623+
};
624+
625+
static PyStructSequence_Desc windows_version_desc = {
626+
"sys.getwindowsversion", /* name */
627+
getwindowsversion_doc, /* doc */
628+
windows_version_fields, /* fields */
629+
5 /* For backward compatibility,
630+
only the first 5 items are accessible
631+
via indexing, the rest are name only */
632+
};
633+
607634
static PyObject *
608635
sys_getwindowsversion(PyObject *self)
609636
{
610-
OSVERSIONINFO ver;
637+
PyObject *version;
638+
int pos = 0;
639+
OSVERSIONINFOEX ver;
611640
ver.dwOSVersionInfoSize = sizeof(ver);
612-
if (!GetVersionEx(&ver))
641+
if (!GetVersionEx((OSVERSIONINFO*) &ver))
613642
return PyErr_SetFromWindowsErr(0);
614-
return Py_BuildValue("HHHHs",
615-
ver.dwMajorVersion,
616-
ver.dwMinorVersion,
617-
ver.dwBuildNumber,
618-
ver.dwPlatformId,
619-
ver.szCSDVersion);
643+
644+
version = PyStructSequence_New(&WindowsVersionType);
645+
if (version == NULL)
646+
return NULL;
647+
648+
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMajorVersion));
649+
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMinorVersion));
650+
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwBuildNumber));
651+
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwPlatformId));
652+
PyStructSequence_SET_ITEM(version, pos++, PyUnicode_FromString(ver.szCSDVersion));
653+
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMajor));
654+
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMinor));
655+
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask));
656+
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType));
657+
658+
return version;
620659
}
621660

622661
#endif /* MS_WINDOWS */
@@ -1488,6 +1527,16 @@ _PySys_Init(void)
14881527
FlagsType.tp_init = NULL;
14891528
FlagsType.tp_new = NULL;
14901529

1530+
1531+
#if defined(MS_WINDOWS)
1532+
/* getwindowsversion */
1533+
if (WindowsVersionType.tp_name == 0)
1534+
PyStructSequence_InitType(&WindowsVersionType, &windows_version_desc);
1535+
/* prevent user from creating new instances */
1536+
WindowsVersionType.tp_init = NULL;
1537+
WindowsVersionType.tp_new = NULL;
1538+
#endif
1539+
14911540
/* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */
14921541
#ifndef PY_NO_SHORT_FLOAT_REPR
14931542
SET_SYS_FROM_STRING("float_repr_style",

0 commit comments

Comments
 (0)