Skip to content

Commit ae4c2c1

Browse files
authored
[3.15] gh-151929: Get machine ID and uptime on Windows in pythoninfo (#152146) (#152187)
gh-151929: Get machine ID and uptime on Windows in pythoninfo (#152146) * Replace "linux." prefix with "system." in pythoninfo. * Add _winapi.GetTickCount64() function. (cherry picked from commit f991051)
1 parent 1deffc3 commit ae4c2c1

3 files changed

Lines changed: 110 additions & 27 deletions

File tree

Lib/test/pythoninfo.py

Lines changed: 75 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
import warnings
99

1010

11+
MS_WINDOWS = (sys.platform == "win32")
12+
13+
1114
def normalize_text(text):
1215
if text is None:
1316
return None
@@ -906,8 +909,30 @@ def collect_subprocess(info_add):
906909
copy_attributes(info_add, subprocess, 'subprocess.%s', ('_USE_POSIX_SPAWN',))
907910

908911

912+
def winreg_query(path):
913+
try:
914+
import winreg
915+
except ImportError:
916+
return None
917+
918+
key, path = path.split('\\', 1)
919+
sub_key, value = path.rsplit('\\', 1)
920+
if key == "HKEY_LOCAL_MACHINE":
921+
key = winreg.HKEY_LOCAL_MACHINE
922+
else:
923+
raise ValueError(f"unknown key {key!r}")
924+
925+
try:
926+
access = winreg.KEY_READ | winreg.KEY_WOW64_64KEY
927+
with winreg.OpenKey(key, sub_key, access=access) as key_handle:
928+
result, _ = winreg.QueryValueEx(key_handle, value)
929+
return result
930+
except OSError:
931+
return None
932+
933+
909934
def collect_windows(info_add):
910-
if sys.platform != "win32":
935+
if not MS_WINDOWS:
911936
# Code specific to Windows
912937
return
913938

@@ -999,19 +1024,10 @@ def collect_windows(info_add):
9991024
info_add('windows.ver', line)
10001025

10011026
# windows.developer_mode: get AllowDevelopmentWithoutDevLicense registry
1002-
import winreg
1003-
try:
1004-
key = winreg.OpenKey(
1005-
winreg.HKEY_LOCAL_MACHINE,
1006-
r"SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock")
1007-
subkey = "AllowDevelopmentWithoutDevLicense"
1008-
try:
1009-
value, value_type = winreg.QueryValueEx(key, subkey)
1010-
finally:
1011-
winreg.CloseKey(key)
1012-
except OSError:
1013-
pass
1014-
else:
1027+
value = winreg_query(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows"
1028+
r"\CurrentVersion\AppModelUnlock"
1029+
r"\AllowDevelopmentWithoutDevLicense")
1030+
if value is not None:
10151031
info_add('windows.developer_mode', "enabled" if value else "disabled")
10161032

10171033

@@ -1044,38 +1060,71 @@ def collect_libregrtest_utils(info_add):
10441060
info_add('libregrtests.build_info', ' '.join(utils.get_build_info()))
10451061

10461062

1047-
def linux_get_uptime():
1048-
# Use CLOCK_BOOTTIME if available
1063+
def uptime_boottime():
1064+
# Use CLOCK_BOOTTIME
10491065
import time
10501066
try:
10511067
return time.clock_gettime(time.CLOCK_BOOTTIME)
10521068
except (AttributeError, OSError):
1053-
pass
1069+
return None
1070+
10541071

1055-
# Otherwise, parse the first member of /proc/uptime
1056-
uptime = read_first_line("/proc/uptime")
1057-
if not uptime:
1072+
def uptime_linux():
1073+
# Parse the first member of /proc/uptime
1074+
line = read_first_line("/proc/uptime")
1075+
if not line:
10581076
return
10591077
try:
1060-
parts = uptime.split()
1078+
parts = line.split()
10611079
if not parts:
10621080
return
10631081
return float(parts[0])
10641082
except ValueError:
10651083
return
10661084

10671085

1086+
def uptime_windows():
1087+
try:
1088+
import _winapi
1089+
except ImportError:
1090+
return None
1091+
else:
1092+
return _winapi.GetTickCount64() / 1000.
1093+
1094+
1095+
def get_uptime():
1096+
for func in (uptime_boottime, uptime_linux, uptime_windows):
1097+
uptime = func()
1098+
if uptime is not None:
1099+
return uptime
1100+
return None
1101+
1102+
1103+
def get_machine_id():
1104+
if MS_WINDOWS:
1105+
machine_guid = winreg_query(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft"
1106+
r"\Cryptography\MachineGuid")
1107+
if machine_guid:
1108+
return machine_guid
1109+
1110+
machine_id = read_first_line("/etc/machine-id")
1111+
if machine_id:
1112+
return machine_id
1113+
1114+
return None
1115+
1116+
10681117
def collect_linux(info_add):
10691118
boot_id = read_first_line("/proc/sys/kernel/random/boot_id")
10701119
if boot_id:
1071-
info_add('linux.boot_id', boot_id)
1120+
info_add('system.boot_id', boot_id)
10721121

10731122
# https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
1074-
machine_id = read_first_line("/etc/machine-id")
1123+
machine_id = get_machine_id()
10751124
if machine_id:
1076-
info_add('linux.machine_id', machine_id)
1125+
info_add('system.machine_id', machine_id)
10771126

1078-
uptime = linux_get_uptime()
1127+
uptime = get_uptime()
10791128
if uptime is not None:
10801129
# truncate microseconds
10811130
uptime = int(uptime)
@@ -1084,7 +1133,7 @@ def collect_linux(info_add):
10841133
uptime = str(datetime.timedelta(seconds=uptime))
10851134
except ImportError:
10861135
uptime = f'{uptime} sec'
1087-
info_add('linux.uptime', uptime)
1136+
info_add('system.uptime', uptime)
10881137

10891138

10901139
def collect_info(info):

Modules/_winapi.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3087,6 +3087,21 @@ _winapi_ReportEvent_impl(PyObject *module, HANDLE handle,
30873087
}
30883088

30893089

3090+
/*[clinic input]
3091+
_winapi.GetTickCount64
3092+
3093+
Number of milliseconds that have elapsed since the system was started.
3094+
[clinic start generated code]*/
3095+
3096+
static PyObject *
3097+
_winapi_GetTickCount64_impl(PyObject *module)
3098+
/*[clinic end generated code: output=cb33c0568f0b3ed1 input=77ed6539ac7d6590]*/
3099+
{
3100+
ULONGLONG ticks = GetTickCount64();
3101+
return PyLong_FromUnsignedLongLong(ticks);
3102+
}
3103+
3104+
30903105
static PyMethodDef winapi_functions[] = {
30913106
_WINAPI_CLOSEHANDLE_METHODDEF
30923107
_WINAPI_CONNECTNAMEDPIPE_METHODDEF
@@ -3137,6 +3152,7 @@ static PyMethodDef winapi_functions[] = {
31373152
_WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF
31383153
_WINAPI_NEEDCURRENTDIRECTORYFOREXEPATH_METHODDEF
31393154
_WINAPI_COPYFILE2_METHODDEF
3155+
_WINAPI_GETTICKCOUNT64_METHODDEF
31403156
{NULL, NULL}
31413157
};
31423158

Modules/clinic/_winapi.c.h

Lines changed: 19 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)