Skip to content
Closed
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
38 changes: 38 additions & 0 deletions hermes_cli/_subprocess_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
__all__ = [
"IS_WINDOWS",
"resolve_node_command",
"suppress_platform_ver_console",
"windows_detach_flags",
"windows_detach_flags_without_breakaway",
"windows_hide_flags",
Expand Down Expand Up @@ -201,6 +202,43 @@ def windows_hide_flags() -> int:
return _CREATE_NO_WINDOW


def suppress_platform_ver_console() -> None:
"""Stub out ``platform._syscmd_ver`` on Windows so it can never flash a
console window. No-op on non-Windows.

CPython's ``platform.win32_ver()`` — reached by ``platform.uname()``,
``platform.version()``, and ``platform.platform()`` — unconditionally
shells out ``cmd /c ver`` via ``subprocess.check_output(..., shell=True)``
with no ``CREATE_NO_WINDOW``. From a windowless parent (the pythonw
gateway and every kanban worker it spawns) that allocates a fresh
*visible* console: one flashing ``cmd`` window per process, triggered by
any dependency that merely touches ``platform.uname()`` at import time.

With ``_syscmd_ver`` stubbed to return its inputs, ``win32_ver()`` hits
the documented ``ValueError`` fallback and reads the version from
``sys.getwindowsversion().platform_version`` — same information, queried
in-process, no subprocess, no window. Verified equivalent on
CPython 3.11 (``platform()`` → ``Windows-10-10.0.xxxxx-SP0`` either way).

Call early, before heavyweight imports — the flash typically happens
during a dependency's import, not from Hermes' own code.
"""
if not IS_WINDOWS:
return
try:
import platform

if hasattr(platform, "_syscmd_ver"):
def _quiet_syscmd_ver(system="", release="", version="",
supported_platforms=("win32", "win16", "dos")):
return system, release, version

platform._syscmd_ver = _quiet_syscmd_ver
except Exception:
# Purely cosmetic hardening — never let it break startup.
pass


def windows_detach_popen_kwargs() -> dict:
"""Return a dict of Popen kwargs that detach a child on Windows and
fall back to the POSIX equivalent (``start_new_session=True``) on
Expand Down
9 changes: 9 additions & 0 deletions hermes_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@
except ModuleNotFoundError:
pass

# Windows: neutralize CPython's ``platform._syscmd_ver`` before anything else
# imports — it shells out ``cmd /c ver`` (shell=True, no CREATE_NO_WINDOW), so
# any dependency touching ``platform.uname()`` at import time flashes a
# visible console when this process is windowless (pythonw gateway + every
# kanban worker). No-op on POSIX; never raises.
from hermes_cli._subprocess_compat import suppress_platform_ver_console

suppress_platform_ver_console()

import os
import sys

Expand Down
7 changes: 7 additions & 0 deletions tools/env_probe.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import threading
from typing import Optional

from hermes_cli._subprocess_compat import windows_hide_flags

logger = logging.getLogger(__name__)

# Module-level cache. The probe result is deterministic for the
Expand Down Expand Up @@ -66,6 +68,11 @@ def _run(cmd: list[str], timeout: float = 3.0) -> tuple[int, str, str]:
timeout=timeout,
check=False,
stdin=subprocess.DEVNULL,
# CREATE_NO_WINDOW (0 on POSIX): the probe runs in windowless
# processes (pythonw gateway / kanban workers) where a console
# child would otherwise flash a visible window per probe —
# ~5 flashes at every worker startup.
creationflags=windows_hide_flags(),
)
return result.returncode, (result.stdout or "").strip(), (result.stderr or "").strip()
except FileNotFoundError:
Expand Down
6 changes: 6 additions & 0 deletions tools/lazy_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
from pathlib import Path
from typing import Any, Callable, Optional

from hermes_cli._subprocess_compat import windows_hide_flags

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -668,6 +670,7 @@ def _venv_pip_install(specs: tuple[str, ...], *, timeout: int = 300) -> _Install
[uv_bin, "pip", "install", *target_args, *constraint_args, *specs],
capture_output=True, text=True, timeout=timeout, env=uv_env,
stdin=subprocess.DEVNULL,
creationflags=windows_hide_flags(),
)
if r.returncode == 0:
if target is not None:
Expand All @@ -684,6 +687,7 @@ def _venv_pip_install(specs: tuple[str, ...], *, timeout: int = 300) -> _Install
pip_cmd + ["--version"],
capture_output=True, text=True, timeout=15,
stdin=subprocess.DEVNULL,
creationflags=windows_hide_flags(),
)
if probe.returncode != 0:
raise FileNotFoundError("pip not in venv")
Expand All @@ -693,6 +697,7 @@ def _venv_pip_install(specs: tuple[str, ...], *, timeout: int = 300) -> _Install
[sys.executable, "-m", "ensurepip", "--upgrade", "--default-pip"],
capture_output=True, text=True, timeout=120, check=True,
stdin=subprocess.DEVNULL,
creationflags=windows_hide_flags(),
)
except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e:
return _InstallResult(False, "",
Expand All @@ -703,6 +708,7 @@ def _venv_pip_install(specs: tuple[str, ...], *, timeout: int = 300) -> _Install
pip_cmd + ["install", *target_args, *constraint_args, *specs],
capture_output=True, text=True, timeout=timeout,
stdin=subprocess.DEVNULL,
creationflags=windows_hide_flags(),
)
if r.returncode == 0 and target is not None:
_activate_target_on_syspath(target)
Expand Down