Skip to content

Commit 5b5f372

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

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
@@ -892,8 +895,30 @@ def collect_subprocess(info_add):
892895
copy_attributes(info_add, subprocess, 'subprocess.%s', ('_USE_POSIX_SPAWN',))
893896

894897

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

@@ -978,19 +1003,10 @@ def collect_windows(info_add):
9781003
info_add('windows.ver', line)
9791004

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

9961012

@@ -1023,38 +1039,71 @@ def collect_libregrtest_utils(info_add):
10231039
info_add('libregrtests.build_info', ' '.join(utils.get_build_info()))
10241040

10251041

1026-
def linux_get_uptime():
1027-
# Use CLOCK_BOOTTIME if available
1042+
def uptime_boottime():
1043+
# Use CLOCK_BOOTTIME
10281044
import time
10291045
try:
10301046
return time.clock_gettime(time.CLOCK_BOOTTIME)
10311047
except (AttributeError, OSError):
1032-
pass
1048+
return None
1049+
10331050

1034-
# Otherwise, parse the first member of /proc/uptime
1035-
uptime = read_first_line("/proc/uptime")
1036-
if not uptime:
1051+
def uptime_linux():
1052+
# Parse the first member of /proc/uptime
1053+
line = read_first_line("/proc/uptime")
1054+
if not line:
10371055
return
10381056
try:
1039-
parts = uptime.split()
1057+
parts = line.split()
10401058
if not parts:
10411059
return
10421060
return float(parts[0])
10431061
except ValueError:
10441062
return
10451063

10461064

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

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

1057-
uptime = linux_get_uptime()
1106+
uptime = get_uptime()
10581107
if uptime is not None:
10591108
# truncate microseconds
10601109
uptime = int(uptime)
@@ -1063,7 +1112,7 @@ def collect_linux(info_add):
10631112
uptime = str(datetime.timedelta(seconds=uptime))
10641113
except ImportError:
10651114
uptime = f'{uptime} sec'
1066-
info_add('linux.uptime', uptime)
1115+
info_add('system.uptime', uptime)
10671116

10681117

10691118
def collect_info(info):

Modules/_winapi.c

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

29592959

2960+
/*[clinic input]
2961+
_winapi.GetTickCount64
2962+
2963+
Number of milliseconds that have elapsed since the system was started.
2964+
[clinic start generated code]*/
2965+
2966+
static PyObject *
2967+
_winapi_GetTickCount64_impl(PyObject *module)
2968+
/*[clinic end generated code: output=cb33c0568f0b3ed1 input=77ed6539ac7d6590]*/
2969+
{
2970+
ULONGLONG ticks = GetTickCount64();
2971+
return PyLong_FromUnsignedLongLong(ticks);
2972+
}
2973+
2974+
29602975
static PyMethodDef winapi_functions[] = {
29612976
_WINAPI_CLOSEHANDLE_METHODDEF
29622977
_WINAPI_CONNECTNAMEDPIPE_METHODDEF
@@ -3003,6 +3018,7 @@ static PyMethodDef winapi_functions[] = {
30033018
_WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF
30043019
_WINAPI_NEEDCURRENTDIRECTORYFOREXEPATH_METHODDEF
30053020
_WINAPI_COPYFILE2_METHODDEF
3021+
_WINAPI_GETTICKCOUNT64_METHODDEF
30063022
{NULL, NULL}
30073023
};
30083024

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)