Skip to content

Commit 2a3f489

Browse files
bpo-43284: Update platform.win32_ver to use _syscmd_ver instead of sys.getwindowsversion() (pythonGH-25500)
The sys module uses the kernel32.dll version number, which can vary from the "actual" Windows version. Since the best option for getting the version is WMI (which is expensive), we switch back to launching cmd.exe (which is also expensive, but a lot less code on our part). sys.getwindowsversion() is not updated to avoid launching executables from that module.
1 parent a07da09 commit 2a3f489

File tree

3 files changed

+23
-11
lines changed

3 files changed

+23
-11
lines changed

Doc/library/sys.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,11 +796,16 @@ always available.
796796
Microsoft documentation on :c:func:`OSVERSIONINFOEX` for more information
797797
about these fields.
798798

799-
*platform_version* returns the accurate major version, minor version and
799+
*platform_version* returns the major version, minor version and
800800
build number of the current operating system, rather than the version that
801801
is being emulated for the process. It is intended for use in logging rather
802802
than for feature detection.
803803

804+
.. note::
805+
*platform_version* derives the version from kernel32.dll which can be of a different
806+
version than the OS version. Please use :mod:`platform` module for achieving accurate
807+
OS version.
808+
804809
.. availability:: Windows.
805810

806811
.. versionchanged:: 3.2

Lib/platform.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,9 @@ def _norm_version(version, build=''):
239239
if build:
240240
l.append(build)
241241
try:
242-
ints = map(int, l)
242+
strings = list(map(str, map(int, l)))
243243
except ValueError:
244244
strings = l
245-
else:
246-
strings = list(map(str, ints))
247245
version = '.'.join(strings[:3])
248246
return version
249247

@@ -365,17 +363,20 @@ def win32_ver(release='', version='', csd='', ptype=''):
365363
return release, version, csd, ptype
366364

367365
winver = getwindowsversion()
368-
maj, min, build = winver.platform_version or winver[:3]
369-
version = '{0}.{1}.{2}'.format(maj, min, build)
366+
try:
367+
major, minor, build = map(int, _syscmd_ver()[2].split('.'))
368+
except ValueError:
369+
major, minor, build = winver.platform_version or winver[:3]
370+
version = '{0}.{1}.{2}'.format(major, minor, build)
370371

371-
release = (_WIN32_CLIENT_RELEASES.get((maj, min)) or
372-
_WIN32_CLIENT_RELEASES.get((maj, None)) or
372+
release = (_WIN32_CLIENT_RELEASES.get((major, minor)) or
373+
_WIN32_CLIENT_RELEASES.get((major, None)) or
373374
release)
374375

375376
# getwindowsversion() reflect the compatibility mode Python is
376377
# running under, and so the service pack value is only going to be
377378
# valid if the versions match.
378-
if winver[:2] == (maj, min):
379+
if winver[:2] == (major, minor):
379380
try:
380381
csd = 'SP{}'.format(winver.service_pack_major)
381382
except AttributeError:
@@ -384,8 +385,8 @@ def win32_ver(release='', version='', csd='', ptype=''):
384385

385386
# VER_NT_SERVER = 3
386387
if getattr(winver, 'product_type', None) == 3:
387-
release = (_WIN32_SERVER_RELEASES.get((maj, min)) or
388-
_WIN32_SERVER_RELEASES.get((maj, None)) or
388+
release = (_WIN32_SERVER_RELEASES.get((major, minor)) or
389+
_WIN32_SERVER_RELEASES.get((major, None)) or
389390
release)
390391

391392
try:
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
platform.win32_ver derives the windows version from
2+
sys.getwindowsversion().platform_version which in turn derives the version
3+
from kernel32.dll (which can be of a different version than Windows itself).
4+
Therefore change the platform.win32_ver to determine the version using the
5+
platform module's _syscmd_ver private function to return an accurate
6+
version.

0 commit comments

Comments
 (0)