Skip to content

Commit be65a38

Browse files
authored
[3.14] gh-151929: Get machine ID and uptime on Windows in pythoninfo (#152146) (#152187) (#152193)
[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) (cherry picked from commit ae4c2c1)
1 parent 7e30c9e commit be65a38

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
@@ -894,8 +897,30 @@ def collect_subprocess(info_add):
894897
copy_attributes(info_add, subprocess, 'subprocess.%s', ('_USE_POSIX_SPAWN',))
895898

896899

900+
def winreg_query(path):
901+
try:
902+
import winreg
903+
except ImportError:
904+
return None
905+
906+
key, path = path.split('\\', 1)
907+
sub_key, value = path.rsplit('\\', 1)
908+
if key == "HKEY_LOCAL_MACHINE":
909+
key = winreg.HKEY_LOCAL_MACHINE
910+
else:
911+
raise ValueError(f"unknown key {key!r}")
912+
913+
try:
914+
access = winreg.KEY_READ | winreg.KEY_WOW64_64KEY
915+
with winreg.OpenKey(key, sub_key, access=access) as key_handle:
916+
result, _ = winreg.QueryValueEx(key_handle, value)
917+
return result
918+
except OSError:
919+
return None
920+
921+
897922
def collect_windows(info_add):
898-
if sys.platform != "win32":
923+
if not MS_WINDOWS:
899924
# Code specific to Windows
900925
return
901926

@@ -980,19 +1005,10 @@ def collect_windows(info_add):
9801005
info_add('windows.ver', line)
9811006

9821007
# windows.developer_mode: get AllowDevelopmentWithoutDevLicense registry
983-
import winreg
984-
try:
985-
key = winreg.OpenKey(
986-
winreg.HKEY_LOCAL_MACHINE,
987-
r"SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock")
988-
subkey = "AllowDevelopmentWithoutDevLicense"
989-
try:
990-
value, value_type = winreg.QueryValueEx(key, subkey)
991-
finally:
992-
winreg.CloseKey(key)
993-
except OSError:
994-
pass
995-
else:
1008+
value = winreg_query(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows"
1009+
r"\CurrentVersion\AppModelUnlock"
1010+
r"\AllowDevelopmentWithoutDevLicense")
1011+
if value is not None:
9961012
info_add('windows.developer_mode', "enabled" if value else "disabled")
9971013

9981014

@@ -1025,38 +1041,71 @@ def collect_libregrtest_utils(info_add):
10251041
info_add('libregrtests.build_info', ' '.join(utils.get_build_info()))
10261042

10271043

1028-
def linux_get_uptime():
1029-
# Use CLOCK_BOOTTIME if available
1044+
def uptime_boottime():
1045+
# Use CLOCK_BOOTTIME
10301046
import time
10311047
try:
10321048
return time.clock_gettime(time.CLOCK_BOOTTIME)
10331049
except (AttributeError, OSError):
1034-
pass
1050+
return None
1051+
10351052

1036-
# Otherwise, parse the first member of /proc/uptime
1037-
uptime = read_first_line("/proc/uptime")
1038-
if not uptime:
1053+
def uptime_linux():
1054+
# Parse the first member of /proc/uptime
1055+
line = read_first_line("/proc/uptime")
1056+
if not line:
10391057
return
10401058
try:
1041-
parts = uptime.split()
1059+
parts = line.split()
10421060
if not parts:
10431061
return
10441062
return float(parts[0])
10451063
except ValueError:
10461064
return
10471065

10481066

1067+
def uptime_windows():
1068+
try:
1069+
import _winapi
1070+
except ImportError:
1071+
return None
1072+
else:
1073+
return _winapi.GetTickCount64() / 1000.
1074+
1075+
1076+
def get_uptime():
1077+
for func in (uptime_boottime, uptime_linux, uptime_windows):
1078+
uptime = func()
1079+
if uptime is not None:
1080+
return uptime
1081+
return None
1082+
1083+
1084+
def get_machine_id():
1085+
if MS_WINDOWS:
1086+
machine_guid = winreg_query(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft"
1087+
r"\Cryptography\MachineGuid")
1088+
if machine_guid:
1089+
return machine_guid
1090+
1091+
machine_id = read_first_line("/etc/machine-id")
1092+
if machine_id:
1093+
return machine_id
1094+
1095+
return None
1096+
1097+
10491098
def collect_linux(info_add):
10501099
boot_id = read_first_line("/proc/sys/kernel/random/boot_id")
10511100
if boot_id:
1052-
info_add('linux.boot_id', boot_id)
1101+
info_add('system.boot_id', boot_id)
10531102

10541103
# https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
1055-
machine_id = read_first_line("/etc/machine-id")
1104+
machine_id = get_machine_id()
10561105
if machine_id:
1057-
info_add('linux.machine_id', machine_id)
1106+
info_add('system.machine_id', machine_id)
10581107

1059-
uptime = linux_get_uptime()
1108+
uptime = get_uptime()
10601109
if uptime is not None:
10611110
# truncate microseconds
10621111
uptime = int(uptime)
@@ -1065,7 +1114,7 @@ def collect_linux(info_add):
10651114
uptime = str(datetime.timedelta(seconds=uptime))
10661115
except ImportError:
10671116
uptime = f'{uptime} sec'
1068-
info_add('linux.uptime', uptime)
1117+
info_add('system.uptime', uptime)
10691118

10701119

10711120
def collect_info(info):

Modules/_winapi.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2960,6 +2960,21 @@ _winapi_CopyFile2_impl(PyObject *module, LPCWSTR existing_file_name,
29602960
}
29612961

29622962

2963+
/*[clinic input]
2964+
_winapi.GetTickCount64
2965+
2966+
Number of milliseconds that have elapsed since the system was started.
2967+
[clinic start generated code]*/
2968+
2969+
static PyObject *
2970+
_winapi_GetTickCount64_impl(PyObject *module)
2971+
/*[clinic end generated code: output=cb33c0568f0b3ed1 input=77ed6539ac7d6590]*/
2972+
{
2973+
ULONGLONG ticks = GetTickCount64();
2974+
return PyLong_FromUnsignedLongLong(ticks);
2975+
}
2976+
2977+
29632978
static PyMethodDef winapi_functions[] = {
29642979
_WINAPI_CLOSEHANDLE_METHODDEF
29652980
_WINAPI_CONNECTNAMEDPIPE_METHODDEF
@@ -3006,6 +3021,7 @@ static PyMethodDef winapi_functions[] = {
30063021
_WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF
30073022
_WINAPI_NEEDCURRENTDIRECTORYFOREXEPATH_METHODDEF
30083023
_WINAPI_COPYFILE2_METHODDEF
3024+
_WINAPI_GETTICKCOUNT64_METHODDEF
30093025
{NULL, NULL}
30103026
};
30113027

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)