Skip to content

Commit

Permalink
bpo-43284: Update platform.win32_ver to use _syscmd_ver instead of sy…
Browse files Browse the repository at this point in the history
…s.getwindowsversion() (GH-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.
  • Loading branch information
shreyanavigyan committed Apr 22, 2021
1 parent a07da09 commit 2a3f489
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 11 deletions.
7 changes: 6 additions & 1 deletion Doc/library/sys.rst
Expand Up @@ -796,11 +796,16 @@ always available.
Microsoft documentation on :c:func:`OSVERSIONINFOEX` for more information
about these fields.

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

.. note::
*platform_version* derives the version from kernel32.dll which can be of a different
version than the OS version. Please use :mod:`platform` module for achieving accurate
OS version.

.. availability:: Windows.

.. versionchanged:: 3.2
Expand Down
21 changes: 11 additions & 10 deletions Lib/platform.py
Expand Up @@ -239,11 +239,9 @@ def _norm_version(version, build=''):
if build:
l.append(build)
try:
ints = map(int, l)
strings = list(map(str, map(int, l)))
except ValueError:
strings = l
else:
strings = list(map(str, ints))
version = '.'.join(strings[:3])
return version

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

winver = getwindowsversion()
maj, min, build = winver.platform_version or winver[:3]
version = '{0}.{1}.{2}'.format(maj, min, build)
try:
major, minor, build = map(int, _syscmd_ver()[2].split('.'))
except ValueError:
major, minor, build = winver.platform_version or winver[:3]
version = '{0}.{1}.{2}'.format(major, minor, build)

release = (_WIN32_CLIENT_RELEASES.get((maj, min)) or
_WIN32_CLIENT_RELEASES.get((maj, None)) or
release = (_WIN32_CLIENT_RELEASES.get((major, minor)) or
_WIN32_CLIENT_RELEASES.get((major, None)) or
release)

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

# VER_NT_SERVER = 3
if getattr(winver, 'product_type', None) == 3:
release = (_WIN32_SERVER_RELEASES.get((maj, min)) or
_WIN32_SERVER_RELEASES.get((maj, None)) or
release = (_WIN32_SERVER_RELEASES.get((major, minor)) or
_WIN32_SERVER_RELEASES.get((major, None)) or
release)

try:
Expand Down
@@ -0,0 +1,6 @@
platform.win32_ver derives the windows version from
sys.getwindowsversion().platform_version which in turn derives the version
from kernel32.dll (which can be of a different version than Windows itself).
Therefore change the platform.win32_ver to determine the version using the
platform module's _syscmd_ver private function to return an accurate
version.

0 comments on commit 2a3f489

Please sign in to comment.