https://github.com/python/cpython/commit/be65a38eb71aff2f9cf001099af11a746068609c
commit: be65a38eb71aff2f9cf001099af11a746068609c
branch: 3.14
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-06-25T13:08:35Z
summary:
[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 f9910519af8beecba7d65e0348f48fb70b9a31c8)
(cherry picked from commit ae4c2c126b5a67bcf22f182ce818294c1e71b1c5)
files:
M Lib/test/pythoninfo.py
M Modules/_winapi.c
M Modules/clinic/_winapi.c.h
diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py
index 657552e7aa0ca8a..0d3899d0972165c 100644
--- a/Lib/test/pythoninfo.py
+++ b/Lib/test/pythoninfo.py
@@ -8,6 +8,9 @@
import warnings
+MS_WINDOWS = (sys.platform == "win32")
+
+
def normalize_text(text):
if text is None:
return None
@@ -894,8 +897,30 @@ def collect_subprocess(info_add):
copy_attributes(info_add, subprocess, 'subprocess.%s',
('_USE_POSIX_SPAWN',))
+def winreg_query(path):
+ try:
+ import winreg
+ except ImportError:
+ return None
+
+ key, path = path.split('\\', 1)
+ sub_key, value = path.rsplit('\\', 1)
+ if key == "HKEY_LOCAL_MACHINE":
+ key = winreg.HKEY_LOCAL_MACHINE
+ else:
+ raise ValueError(f"unknown key {key!r}")
+
+ try:
+ access = winreg.KEY_READ | winreg.KEY_WOW64_64KEY
+ with winreg.OpenKey(key, sub_key, access=access) as key_handle:
+ result, _ = winreg.QueryValueEx(key_handle, value)
+ return result
+ except OSError:
+ return None
+
+
def collect_windows(info_add):
- if sys.platform != "win32":
+ if not MS_WINDOWS:
# Code specific to Windows
return
@@ -980,19 +1005,10 @@ def collect_windows(info_add):
info_add('windows.ver', line)
# windows.developer_mode: get AllowDevelopmentWithoutDevLicense registry
- import winreg
- try:
- key = winreg.OpenKey(
- winreg.HKEY_LOCAL_MACHINE,
- r"SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock")
- subkey = "AllowDevelopmentWithoutDevLicense"
- try:
- value, value_type = winreg.QueryValueEx(key, subkey)
- finally:
- winreg.CloseKey(key)
- except OSError:
- pass
- else:
+ value = winreg_query(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows"
+ r"\CurrentVersion\AppModelUnlock"
+ r"\AllowDevelopmentWithoutDevLicense")
+ if value is not None:
info_add('windows.developer_mode', "enabled" if value else "disabled")
@@ -1025,20 +1041,22 @@ def collect_libregrtest_utils(info_add):
info_add('libregrtests.build_info', ' '.join(utils.get_build_info()))
-def linux_get_uptime():
- # Use CLOCK_BOOTTIME if available
+def uptime_boottime():
+ # Use CLOCK_BOOTTIME
import time
try:
return time.clock_gettime(time.CLOCK_BOOTTIME)
except (AttributeError, OSError):
- pass
+ return None
+
- # Otherwise, parse the first member of /proc/uptime
- uptime = read_first_line("/proc/uptime")
- if not uptime:
+def uptime_linux():
+ # Parse the first member of /proc/uptime
+ line = read_first_line("/proc/uptime")
+ if not line:
return
try:
- parts = uptime.split()
+ parts = line.split()
if not parts:
return
return float(parts[0])
@@ -1046,17 +1064,48 @@ def linux_get_uptime():
return
+def uptime_windows():
+ try:
+ import _winapi
+ except ImportError:
+ return None
+ else:
+ return _winapi.GetTickCount64() / 1000.
+
+
+def get_uptime():
+ for func in (uptime_boottime, uptime_linux, uptime_windows):
+ uptime = func()
+ if uptime is not None:
+ return uptime
+ return None
+
+
+def get_machine_id():
+ if MS_WINDOWS:
+ machine_guid = winreg_query(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft"
+ r"\Cryptography\MachineGuid")
+ if machine_guid:
+ return machine_guid
+
+ machine_id = read_first_line("/etc/machine-id")
+ if machine_id:
+ return machine_id
+
+ return None
+
+
def collect_linux(info_add):
boot_id = read_first_line("/proc/sys/kernel/random/boot_id")
if boot_id:
- info_add('linux.boot_id', boot_id)
+ info_add('system.boot_id', boot_id)
# https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
- machine_id = read_first_line("/etc/machine-id")
+ machine_id = get_machine_id()
if machine_id:
- info_add('linux.machine_id', machine_id)
+ info_add('system.machine_id', machine_id)
- uptime = linux_get_uptime()
+ uptime = get_uptime()
if uptime is not None:
# truncate microseconds
uptime = int(uptime)
@@ -1065,7 +1114,7 @@ def collect_linux(info_add):
uptime = str(datetime.timedelta(seconds=uptime))
except ImportError:
uptime = f'{uptime} sec'
- info_add('linux.uptime', uptime)
+ info_add('system.uptime', uptime)
def collect_info(info):
diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index f4e73828121c80c..767a5b35f45664f 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -2960,6 +2960,21 @@ _winapi_CopyFile2_impl(PyObject *module, LPCWSTR
existing_file_name,
}
+/*[clinic input]
+_winapi.GetTickCount64
+
+Number of milliseconds that have elapsed since the system was started.
+[clinic start generated code]*/
+
+static PyObject *
+_winapi_GetTickCount64_impl(PyObject *module)
+/*[clinic end generated code: output=cb33c0568f0b3ed1 input=77ed6539ac7d6590]*/
+{
+ ULONGLONG ticks = GetTickCount64();
+ return PyLong_FromUnsignedLongLong(ticks);
+}
+
+
static PyMethodDef winapi_functions[] = {
_WINAPI_CLOSEHANDLE_METHODDEF
_WINAPI_CONNECTNAMEDPIPE_METHODDEF
@@ -3006,6 +3021,7 @@ static PyMethodDef winapi_functions[] = {
_WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF
_WINAPI_NEEDCURRENTDIRECTORYFOREXEPATH_METHODDEF
_WINAPI_COPYFILE2_METHODDEF
+ _WINAPI_GETTICKCOUNT64_METHODDEF
{NULL, NULL}
};
diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h
index f8b623fca082d2e..bd8a64bb57391ca 100644
--- a/Modules/clinic/_winapi.c.h
+++ b/Modules/clinic/_winapi.c.h
@@ -2161,4 +2161,22 @@ _winapi_CopyFile2(PyObject *module, PyObject *const
*args, Py_ssize_t nargs, PyO
return return_value;
}
-/*[clinic end generated code: output=6cd07628af447d0a input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(_winapi_GetTickCount64__doc__,
+"GetTickCount64($module, /)\n"
+"--\n"
+"\n"
+"Number of milliseconds that have elapsed since the system was started.");
+
+#define _WINAPI_GETTICKCOUNT64_METHODDEF \
+ {"GetTickCount64", (PyCFunction)_winapi_GetTickCount64, METH_NOARGS,
_winapi_GetTickCount64__doc__},
+
+static PyObject *
+_winapi_GetTickCount64_impl(PyObject *module);
+
+static PyObject *
+_winapi_GetTickCount64(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _winapi_GetTickCount64_impl(module);
+}
+/*[clinic end generated code: output=4a408e816118d0a6 input=a9049054013a1b77]*/
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]