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
8 changes: 6 additions & 2 deletions src/koru/init_host_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"""


import grp
import json
import os
import shutil
Expand All @@ -16,6 +15,11 @@
from pathlib import Path
from typing import Any

if sys.platform != "win32":
import grp as _grp
else:
_grp = None # type: ignore[assignment]

from koru.ide_runtime import build_host_setup_report
from koru.runtime import runtime_dir

Expand Down Expand Up @@ -69,7 +73,7 @@ def _uinput_snapshot() -> dict[str, Any]:
except OSError as exc:
return {"present": True, "stat_error": str(exc)}
try:
group_name = grp.getgrgid(st.st_gid).gr_name
group_name = _grp.getgrgid(st.st_gid).gr_name if _grp is not None else str(st.st_gid)
except (KeyError, OSError):
group_name = str(st.st_gid)
return {
Expand Down
20 changes: 19 additions & 1 deletion tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
refresh_init_agent_lane,
resolve_project_agent_lane,
)
from koru.init_host_environment import _parse_os_release_line
import koru.init_host_environment as _ihe_mod
from koru.init_host_environment import _parse_os_release_line, _uinput_snapshot
from koru.policy import load_policy
from koru.runtime import planfile_dir, runtime_dir

Expand All @@ -42,6 +43,23 @@ def test_parse_os_release_line(self) -> None:
self.assertIsNone(_parse_os_release_line("MALFORMED"))
self.assertIsNone(_parse_os_release_line("=missing-key"))

def test_grp_sentinel_matches_platform(self) -> None:
"""_grp must be None on Windows and the real grp module elsewhere."""
import sys

if sys.platform == "win32":
self.assertIsNone(_ihe_mod._grp)
else:
import grp

self.assertIs(_ihe_mod._grp, grp)

def test_uinput_snapshot_absent_device(self) -> None:
"""_uinput_snapshot returns present=False when /dev/uinput does not exist."""
result = _uinput_snapshot()
# On CI / Windows / macOS /dev/uinput is absent; the function must not raise.
self.assertIn("present", result)


def _detach_ci_env() -> dict[str, str]:
"""Remove CI markers so IDE folder detection is deterministic in tests."""
Expand Down
Loading