Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion docs/commands/sys.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ $ winml sys [options]
## How it works

`winml sys` queries Python's `platform` and `importlib.metadata` modules to report
library versions, then probes PyTorch for CUDA availability and GPU device names.
library versions. On Windows, it also reads the native
`HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion` registry key to report the
display version, build, update build revision (UBR), build branch, and build lab.
It then probes PyTorch for CUDA availability and GPU device names.
Backend availability checks use the installed runtime environment, while device
enumeration queries hardware directly in NPU > GPU > CPU priority order, and EP
enumeration merges the WinML EP registry with ONNX Runtime's
Expand All @@ -55,6 +58,11 @@ Environment
Python Executable C:\...\python.exe
OS Windows 11
Machine AMD64
Display Version 24H2
Current Build 26100
UBR 4946
Build Branch ge_release
BuildLabEx 26100.1.amd64fre.ge_release.240331-1435

ML Libraries
Library Version Status
Expand Down
54 changes: 53 additions & 1 deletion src/winml/modelkit/commands/sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ def _get_python_info() -> dict[str, Any]:
0x14C: "x86",
}

_WINDOWS_CURRENT_VERSION_KEY = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion"
_WINDOWS_VERSION_VALUES = {
"DisplayVersion": "display_version",
"CurrentBuild": "current_build",
"UBR": "ubr",
"BuildBranch": "build_branch",
"BuildLabEx": "build_lab_ex",
}


if sys.platform == "win32":
try:
Expand Down Expand Up @@ -173,6 +182,34 @@ def _get_windows_native_machine() -> str | None:
return name


def _get_windows_version_info() -> dict[str, str | int]:
"""Read detailed Windows version metadata from the native registry view."""
if sys.platform != "win32":
return {}

import winreg

result: dict[str, str | int] = {}
try:
with winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE,
_WINDOWS_CURRENT_VERSION_KEY,
access=winreg.KEY_READ | winreg.KEY_WOW64_64KEY,
) as key:
for registry_name, output_name in _WINDOWS_VERSION_VALUES.items():
try:
value, _value_type = winreg.QueryValueEx(key, registry_name)
except OSError:
logger.debug("Windows registry value is unavailable: %s", registry_name)
continue
if isinstance(value, (str, int)):
result[output_name] = value
except OSError as exc:
logger.debug("Failed to read detailed Windows version information: %s", exc)

return result


def _get_platform_info() -> dict[str, Any]:
"""Gather OS and platform information."""
system = platform.system()
Expand All @@ -181,6 +218,7 @@ def _get_platform_info() -> dict[str, Any]:

# For Windows, use OS class for accurate Windows 11 detection
# platform.release() may incorrectly report '10' on some Python versions
windows_version: dict[str, str | int] = {}
if system == "Windows":
try:
os_info = OS.get()
Expand All @@ -195,13 +233,16 @@ def _get_platform_info() -> dict[str, Any]:
native_machine = _get_windows_native_machine()
if native_machine:
machine = native_machine
windows_version = _get_windows_version_info()

return {
result: dict[str, Any] = {
"system": system,
"release": release,
"machine": machine,
"processor": platform.processor() or "Unknown",
}
result.update(windows_version)
return result


def _get_memory_info() -> dict[str, int | None]:
Expand Down Expand Up @@ -402,6 +443,17 @@ def _output_text(info: dict[str, Any], verbose: bool = False) -> None:
table.add_row("Python Executable", info["python"]["executable"])
table.add_row("OS", f"{info['platform']['system']} {info['platform']['release']}")
table.add_row("Machine", info["platform"]["machine"])
windows_rows = (
("Display Version", "display_version"),
("Current Build", "current_build"),
("UBR", "ubr"),
("Build Branch", "build_branch"),
("BuildLabEx", "build_lab_ex"),
)
for label, key in windows_rows:
value = info["platform"].get(key)
if value is not None:
table.add_row(label, escape(str(value)))

console.print("\n[bold blue]Environment[/bold blue]")
console.print(table)
Expand Down
108 changes: 107 additions & 1 deletion tests/unit/sysinfo/test_sysinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,115 @@ def test_returns_none_on_non_windows(self, monkeypatch: pytest.MonkeyPatch) -> N
assert sys_mod._get_windows_native_machine() is None


class TestGetWindowsVersionInfo:
"""Test detailed Windows version collection from the registry."""

def test_reads_available_current_version_values(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
from winml.modelkit.commands import sys as sys_mod

values = {
"DisplayVersion": ("24H2", 1),
"CurrentBuild": ("26100", 1),
"UBR": (4946, 4),
"BuildBranch": ("ge_release", 1),
"BuildLabEx": ("26100.1.amd64fre.ge_release.240331-1435", 1),
}
key = MagicMock()
winreg = MagicMock()
winreg.HKEY_LOCAL_MACHINE = object()
winreg.KEY_READ = 0x20019
winreg.KEY_WOW64_64KEY = 0x100
winreg.OpenKey.return_value.__enter__.return_value = key
winreg.QueryValueEx.side_effect = lambda _key, name: values[name]

monkeypatch.setattr(sys, "platform", "win32")
with patch.dict(sys.modules, {"winreg": winreg}):
result = sys_mod._get_windows_version_info()

assert result == {
"display_version": "24H2",
"current_build": "26100",
"ubr": 4946,
"build_branch": "ge_release",
"build_lab_ex": "26100.1.amd64fre.ge_release.240331-1435",
}
winreg.OpenKey.assert_called_once_with(
winreg.HKEY_LOCAL_MACHINE,
sys_mod._WINDOWS_CURRENT_VERSION_KEY,
access=winreg.KEY_READ | winreg.KEY_WOW64_64KEY,
)

def test_keeps_other_values_when_one_is_missing(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
from winml.modelkit.commands import sys as sys_mod

winreg = MagicMock()
winreg.HKEY_LOCAL_MACHINE = object()
winreg.KEY_READ = 0x20019
winreg.KEY_WOW64_64KEY = 0x100
winreg.QueryValueEx.side_effect = [
OSError("missing"),
("26100", 1),
(4946, 4),
("ge_release", 1),
("build-lab", 1),
]

monkeypatch.setattr(sys, "platform", "win32")
with patch.dict(sys.modules, {"winreg": winreg}):
result = sys_mod._get_windows_version_info()

assert "display_version" not in result
assert result["current_build"] == "26100"

def test_returns_empty_when_registry_key_is_unavailable(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
from winml.modelkit.commands import sys as sys_mod

winreg = MagicMock()
winreg.HKEY_LOCAL_MACHINE = object()
winreg.KEY_READ = 0x20019
winreg.KEY_WOW64_64KEY = 0x100
winreg.OpenKey.side_effect = OSError("access denied")

monkeypatch.setattr(sys, "platform", "win32")
with patch.dict(sys.modules, {"winreg": winreg}):
assert sys_mod._get_windows_version_info() == {}

def test_returns_empty_on_non_windows(self, monkeypatch: pytest.MonkeyPatch) -> None:
from winml.modelkit.commands import sys as sys_mod

monkeypatch.setattr(sys, "platform", "linux")

assert sys_mod._get_windows_version_info() == {}


class TestGetPlatformInfo:
"""Test _get_platform_info function."""

@patch("winml.modelkit.commands.sys._get_windows_native_machine", return_value=None)
@patch(
"winml.modelkit.commands.sys._get_windows_version_info",
return_value={
"display_version": "24H2",
"current_build": "26100",
"ubr": 4946,
"build_branch": "ge_release",
"build_lab_ex": "build-lab",
},
)
@patch("winml.modelkit.commands.sys.OS")
@patch("winml.modelkit.commands.sys.platform")
def test_windows_11_detection(
self, mock_platform: MagicMock, mock_os_class: MagicMock, _mock_native: MagicMock
self,
mock_platform: MagicMock,
mock_os_class: MagicMock,
_mock_version: MagicMock,
_mock_native: MagicMock,
) -> None:
"""Test Windows 11 is correctly detected."""
from winml.modelkit.commands.sys import _get_platform_info
Expand All @@ -93,6 +194,11 @@ def test_windows_11_detection(
assert result["system"] == "Windows"
assert result["release"] == "11" # Should be corrected to 11
assert result["machine"] == "AMD64"
assert result["display_version"] == "24H2"
assert result["current_build"] == "26100"
assert result["ubr"] == 4946
assert result["build_branch"] == "ge_release"
assert result["build_lab_ex"] == "build-lab"
mock_os_class.get.assert_called_once()

@patch("winml.modelkit.commands.sys._get_windows_native_machine", return_value=None)
Expand Down
Loading