From beee46709c0f2868af738e22789fea295c46249e Mon Sep 17 00:00:00 2001 From: YuYigeng <165616139+YuYigeng@users.noreply.github.com> Date: Tue, 21 Jul 2026 16:41:11 +0800 Subject: [PATCH 1/3] fix(doctor): detect wheel-installed entry points Signed-off-by: andrexibiza <84248988+andrexibiza@users.noreply.github.com> # Conflicts: # tests/hermes_cli/test_doctor_command_install.py --- hermes_cli/doctor.py | 66 ++++++++++++--- .../hermes_cli/test_doctor_command_install.py | 84 +++++++++++++++++++ 2 files changed, 139 insertions(+), 11 deletions(-) diff --git a/hermes_cli/doctor.py b/hermes_cli/doctor.py index 18ea422f3e24..02d30804c6be 100644 --- a/hermes_cli/doctor.py +++ b/hermes_cli/doctor.py @@ -6,6 +6,7 @@ import os import sys +import sysconfig import subprocess import shutil import importlib.util @@ -1627,12 +1628,35 @@ def run_doctor(args): _section("Command Installation") # Determine the venv entry point location _venv_bin = None + _uses_environment_entry_point = False for _venv_name in ("venv", ".venv"): _candidate = PROJECT_ROOT / _venv_name / "bin" / "hermes" if _candidate.exists(): _venv_bin = _candidate break + # A wheel-installed virtualenv keeps the console script under the + # environment's scripts directory while PROJECT_ROOT points inside + # site-packages. The source-checkout candidates above cannot describe + # that layout, so consult Python's platform-aware install scheme before + # reporting a missing entry point (#49529). + _active_venv = sys.prefix != getattr(sys, "base_prefix", sys.prefix) + _environment_scripts_dir = None + if _active_venv: + try: + _scripts_path = sysconfig.get_path("scripts") + if _scripts_path: + _environment_scripts_dir = Path(_scripts_path) + except (KeyError, TypeError, ValueError): + pass + if _venv_bin is None and _environment_scripts_dir is not None: + _candidate = _environment_scripts_dir / "hermes" + if _candidate.exists(): + _venv_bin = _candidate + _uses_environment_entry_point = True + + _source_checkout = (PROJECT_ROOT / "pyproject.toml").is_file() + # Determine the expected command link directory (mirrors install.sh logic) _prefix = os.environ.get("PREFIX", "") _is_termux_env = bool(os.environ.get("TERMUX_VERSION")) or "com.termux/files/usr" in _prefix @@ -1645,18 +1669,38 @@ def run_doctor(args): _cmd_link = _cmd_link_dir / "hermes" if _venv_bin is None: - check_warn( - "Venv entry point not found", - "(hermes not in venv/bin/ or .venv/bin/ — reinstall with pip install -e '.[all]')" - ) - manual_issues.append( - f"Reinstall entry point: cd {PROJECT_ROOT} && source venv/bin/activate && pip install -e '.[all]'" - ) + if _active_venv and not _source_checkout: + _expected_dir = _environment_scripts_dir or Path(sys.prefix) / "bin" + _reinstall_cmd = ( + f"{sys.executable} -m pip install --force-reinstall hermes-agent" + ) + check_warn( + "Venv entry point not found", + f"(hermes not in {_expected_dir} — reinstall with {_reinstall_cmd})", + ) + manual_issues.append(f"Reinstall entry point: {_reinstall_cmd}") + else: + check_warn( + "Venv entry point not found", + "(hermes not in venv/bin/ or .venv/bin/ — reinstall with pip install -e '.[all]')" + ) + manual_issues.append( + f"Reinstall entry point: cd {PROJECT_ROOT} && source venv/bin/activate && pip install -e '.[all]'" + ) else: - check_ok(f"Venv entry point exists ({_venv_bin.relative_to(PROJECT_ROOT)})") - - # Check the symlink at the command link location - if _cmd_link.is_symlink(): + try: + _venv_bin_display = _venv_bin.relative_to(PROJECT_ROOT) + except ValueError: + _venv_bin_display = _venv_bin + check_ok(f"Venv entry point exists ({_venv_bin_display})") + + # A wheel's console script is already installed in the active + # environment. Requiring a second global link would turn a + # healthy isolated venv into a false failure and make --fix leak + # that environment into the user's global command path. + if _uses_environment_entry_point and not _source_checkout: + check_ok("Active environment entry point needs no global symlink") + elif _cmd_link.is_symlink(): _target = _cmd_link.resolve() _expected = _venv_bin.resolve() if _target == _expected: diff --git a/tests/hermes_cli/test_doctor_command_install.py b/tests/hermes_cli/test_doctor_command_install.py index c6b2da7d1503..278048041042 100644 --- a/tests/hermes_cli/test_doctor_command_install.py +++ b/tests/hermes_cli/test_doctor_command_install.py @@ -1,6 +1,7 @@ """Tests for the Command Installation check in hermes doctor.""" import sys +import sysconfig import types from argparse import Namespace from pathlib import Path @@ -108,6 +109,8 @@ def test_missing_venv_entry_point_shows_warn(self, monkeypatch, tmp_path): monkeypatch.setattr(doctor_mod, "PROJECT_ROOT", project) monkeypatch.setattr(doctor_mod, "_DHH", str(home)) monkeypatch.setattr(Path, "home", lambda: tmp_path) + monkeypatch.setattr(sys, "prefix", str(tmp_path / "system-python")) + monkeypatch.setattr(sys, "base_prefix", str(tmp_path / "system-python")) fake_model_tools = types.SimpleNamespace( check_tool_availability=lambda *a, **kw: ([], []), @@ -130,7 +133,88 @@ def test_missing_venv_entry_point_shows_warn(self, monkeypatch, tmp_path): assert "Command Installation" in out assert "Venv entry point not found" in out + @pytest.mark.skipif(sys.platform == "win32", reason="Symlink check is Unix-only") + @pytest.mark.parametrize("fix", [False, True]) + def test_wheel_virtualenv_entry_point_needs_no_global_symlink( + self, monkeypatch, tmp_path, fix + ): + """A wheel venv is healthy without a global command symlink.""" + _setup_doctor_env(monkeypatch, tmp_path) + venv = tmp_path / "wheel-venv" + scripts = venv / "bin" + scripts.mkdir(parents=True) + hermes_bin = scripts / "hermes" + hermes_bin.write_text("#!/usr/bin/env python\n# wheel entry point\n") + hermes_bin.chmod(0o755) + + site_packages = venv / "lib" / "python3.11" / "site-packages" + site_packages.mkdir(parents=True) + monkeypatch.setattr(doctor_mod, "PROJECT_ROOT", site_packages) + monkeypatch.setattr(sys, "prefix", str(venv)) + monkeypatch.setattr(sys, "base_prefix", str(tmp_path / "base-python")) + real_get_path = sysconfig.get_path + monkeypatch.setattr( + sysconfig, + "get_path", + lambda name, *args, **kwargs: ( + str(scripts) + if name == "scripts" + else real_get_path(name, *args, **kwargs) + ), + ) + + monkeypatch.setattr(Path, "home", lambda: tmp_path) + out = _run_doctor(fix=fix) + + assert "Venv entry point exists" in out + assert str(hermes_bin) in out + assert "Venv entry point not found" not in out + assert "Active environment entry point needs no global symlink" in out + assert "~/.local/bin/hermes not found" not in out + assert "Missing ~/.local/bin/hermes symlink" not in out + command_link = tmp_path / ".local" / "bin" / "hermes" + assert not command_link.exists() + assert not command_link.is_symlink() + + @pytest.mark.skipif(sys.platform == "win32", reason="Symlink check is Unix-only") + def test_wheel_virtualenv_missing_entry_point_avoids_editable_fix( + self, monkeypatch, tmp_path + ): + """Wheel installs must not be repaired as source checkouts.""" + _setup_doctor_env(monkeypatch, tmp_path) + venv = tmp_path / "wheel-venv" + scripts = venv / "bin" + scripts.mkdir(parents=True) + site_packages = venv / "lib" / "python3.11" / "site-packages" + site_packages.mkdir(parents=True) + + monkeypatch.setattr(doctor_mod, "PROJECT_ROOT", site_packages) + monkeypatch.setattr(sys, "prefix", str(venv)) + monkeypatch.setattr(sys, "base_prefix", str(tmp_path / "base-python")) + monkeypatch.setattr(sys, "executable", str(scripts / "python")) + real_get_path = sysconfig.get_path + monkeypatch.setattr( + sysconfig, + "get_path", + lambda name, *args, **kwargs: ( + str(scripts) + if name == "scripts" + else real_get_path(name, *args, **kwargs) + ), + ) + monkeypatch.setattr(Path, "home", lambda: tmp_path) + + out = _run_doctor(fix=True) + + assert "Venv entry point not found" in out + assert "pip install -e" not in out + assert "-m pip install --force-reinstall hermes-agent" in out + + @pytest.mark.skipif(sys.platform == "win32", reason="Symlink check is Unix-only") + def test_dot_venv_dir_is_found(self, monkeypatch, tmp_path): + """The check finds entry points in .venv/ as well as venv/.""" + home, project, _ = _setup_doctor_env(monkeypatch, tmp_path, venv_name=".venv") @pytest.mark.skipif(sys.platform == "win32", reason="Symlink check is Unix-only") def test_termux_uses_prefix_bin(self, monkeypatch, tmp_path): From 7238551c81ea0ec49af643621a9bdefc9b0e97b3 Mon Sep 17 00:00:00 2001 From: andrexibiza <84248988+andrexibiza@users.noreply.github.com> Date: Mon, 3 Aug 2026 15:43:53 -0500 Subject: [PATCH 2/3] fix(doctor): detect Windows console-script entry points (hermes.exe) The environment-scripts-dir detection only checked bare 'hermes', which misses the actual console script on Windows (venv\Scripts\hermes.exe, verified on Win11). Scan all platform name variants so an environment-installed entry point is not reported missing, and add regression tests for the Windows layout and the still-warns-when-missing case. Addresses reviewer finding on #77428. --- hermes_cli/doctor.py | 15 ++- .../hermes_cli/test_doctor_command_install.py | 95 +++++++++++++++++++ 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/hermes_cli/doctor.py b/hermes_cli/doctor.py index 02d30804c6be..3267c57b4f3d 100644 --- a/hermes_cli/doctor.py +++ b/hermes_cli/doctor.py @@ -1650,10 +1650,17 @@ def run_doctor(args): except (KeyError, TypeError, ValueError): pass if _venv_bin is None and _environment_scripts_dir is not None: - _candidate = _environment_scripts_dir / "hermes" - if _candidate.exists(): - _venv_bin = _candidate - _uses_environment_entry_point = True + # Windows console scripts are installed as .exe (plus .cmd/.bat + # shims); POSIX installs a bare . Check all platform variants so + # an environment-installed entry point is not reported missing on + # Windows (verified on Win11: venv\Scripts\hermes.exe, bare "hermes" + # absent) or in cross-layout venvs. + for _script_name in ("hermes", "hermes.exe", "hermes.cmd", "hermes.bat"): + _candidate = _environment_scripts_dir / _script_name + if _candidate.exists(): + _venv_bin = _candidate + _uses_environment_entry_point = True + break _source_checkout = (PROJECT_ROOT / "pyproject.toml").is_file() diff --git a/tests/hermes_cli/test_doctor_command_install.py b/tests/hermes_cli/test_doctor_command_install.py index 278048041042..d3f9a78a1f69 100644 --- a/tests/hermes_cli/test_doctor_command_install.py +++ b/tests/hermes_cli/test_doctor_command_install.py @@ -67,6 +67,26 @@ def _run_doctor(fix=False): return buf.getvalue() +def _stub_posix_stdlib(monkeypatch): + """Provide minimal POSIX-only stdlib stubs (fcntl) so a win32 host can + exercise the POSIX-guarded doctor section after sys.platform is mocked.""" + import types as _types + try: + import fcntl # noqa: F401 + except ImportError: + monkeypatch.setitem( + sys.modules, + "fcntl", + _types.SimpleNamespace( + flock=lambda *a, **k: None, + LOCK_EX=2, + LOCK_UN=8, + LOCK_SH=1, + LOCK_NB=4, + ), + ) + + class TestDoctorCommandInstallation: """Tests for the ◆ Command Installation section.""" @@ -233,3 +253,78 @@ def test_termux_uses_prefix_bin(self, monkeypatch, tmp_path): assert "Command Installation" in out assert "$PREFIX/bin" in out + def test_wheel_virtualenv_windows_console_script_entry_point( + self, monkeypatch, tmp_path + ): + """Windows console-script layout (hermes.exe in the env Scripts dir) + must be detected, not reported as a missing entry point (#49529, + verified on Win11: venv\\Scripts\\hermes.exe, bare \"hermes\" absent).""" + _setup_doctor_env(monkeypatch, tmp_path) + # Reach the POSIX-guarded section on a win32 host without cascading + # POSIX-only stdlib imports (fcntl) through the doctor call chain. + _stub_posix_stdlib(monkeypatch) + monkeypatch.setattr(sys, "platform", "linux") + venv = tmp_path / "wheel-venv" + scripts = venv / "Scripts" + scripts.mkdir(parents=True) + hermes_exe = scripts / "hermes.exe" + hermes_exe.write_bytes(b"MZ\x90\x00") # minimal PE header stub + + site_packages = venv / "Lib" / "site-packages" + site_packages.mkdir(parents=True) + monkeypatch.setattr(doctor_mod, "PROJECT_ROOT", site_packages) + monkeypatch.setattr(sys, "prefix", str(venv)) + monkeypatch.setattr(sys, "base_prefix", str(tmp_path / "base-python")) + real_get_path = sysconfig.get_path + monkeypatch.setattr( + sysconfig, + "get_path", + lambda name, *args, **kwargs: ( + str(scripts) + if name == "scripts" + else real_get_path(name, *args, **kwargs) + ), + ) + monkeypatch.setattr(Path, "home", lambda: tmp_path) + + out = _run_doctor(fix=False) + + assert "Venv entry point exists" in out + assert "hermes.exe" in out + assert "Venv entry point not found" not in out + assert "Active environment entry point needs no global symlink" in out + + def test_wheel_virtualenv_windows_console_script_missing_still_warns( + self, monkeypatch, tmp_path + ): + """Windows layout with no console script at all must still warn (no + false all-clear from the .exe/.cmd/.bat name scan).""" + _setup_doctor_env(monkeypatch, tmp_path) + _stub_posix_stdlib(monkeypatch) + monkeypatch.setattr(sys, "platform", "linux") # reach the POSIX-guarded section + venv = tmp_path / "wheel-venv" + scripts = venv / "Scripts" + scripts.mkdir(parents=True) + + site_packages = venv / "Lib" / "site-packages" + site_packages.mkdir(parents=True) + monkeypatch.setattr(doctor_mod, "PROJECT_ROOT", site_packages) + monkeypatch.setattr(sys, "prefix", str(venv)) + monkeypatch.setattr(sys, "base_prefix", str(tmp_path / "base-python")) + real_get_path = sysconfig.get_path + monkeypatch.setattr( + sysconfig, + "get_path", + lambda name, *args, **kwargs: ( + str(scripts) + if name == "scripts" + else real_get_path(name, *args, **kwargs) + ), + ) + monkeypatch.setattr(Path, "home", lambda: tmp_path) + + out = _run_doctor(fix=False) + + assert "Venv entry point not found" in out + assert "Active environment entry point needs no global symlink" not in out + From e6c862d9f3683aef3f46dcf2c0f43e373541d55d Mon Sep 17 00:00:00 2001 From: andrexibiza <84248988+andrexibiza@users.noreply.github.com> Date: Tue, 4 Aug 2026 11:24:48 -0500 Subject: [PATCH 3/3] fix(doctor): run entry-point detection on all platforms; Windows console scripts reachable Blind verifier caught that the Windows console-script detection (hermes.exe/ .cmd/.bat) sat inside 'if sys.platform != win32', making it unreachable on the exact platform that produces hermes.exe. Restructure: entry-point detection (venv/ + sysconfig scripts dir + platform name variants) now runs on all platforms; only ~/.local/bin symlink management stays POSIX-guarded. Windows-layout tests now run natively on win32 with no platform fake, and assert the Command Installation section actually executes. Signed-off-by: andrexibiza <84248988+andrexibiza@users.noreply.github.com> --- hermes_cli/doctor.py | 145 ++++++++++-------- .../hermes_cli/test_doctor_command_install.py | 15 +- 2 files changed, 84 insertions(+), 76 deletions(-) diff --git a/hermes_cli/doctor.py b/hermes_cli/doctor.py index 3267c57b4f3d..437a54e2c2ee 100644 --- a/hermes_cli/doctor.py +++ b/hermes_cli/doctor.py @@ -1624,46 +1624,86 @@ def run_doctor(args): _check_gateway_service_linger(issues) _check_s6_supervision(issues) - if sys.platform != "win32": - _section("Command Installation") - # Determine the venv entry point location - _venv_bin = None - _uses_environment_entry_point = False - for _venv_name in ("venv", ".venv"): - _candidate = PROJECT_ROOT / _venv_name / "bin" / "hermes" + # Entry-point detection runs on ALL platforms. The environment's scripts + # directory is platform-aware via sysconfig: on Windows it is + # venv\Scripts (console scripts installed as hermes.exe/.cmd/.bat), on + # POSIX venv/bin (bare "hermes"). Only the *symlink* management below is + # POSIX-specific, so that part stays guarded. + _section("Command Installation") + # Determine the venv entry point location + _venv_bin = None + _uses_environment_entry_point = False + for _venv_name in ("venv", ".venv"): + _candidate = PROJECT_ROOT / _venv_name / "bin" / "hermes" + if _candidate.exists(): + _venv_bin = _candidate + break + + # A wheel-installed virtualenv keeps the console script under the + # environment's scripts directory while PROJECT_ROOT points inside + # site-packages. The source-checkout candidates above cannot describe + # that layout, so consult Python's platform-aware install scheme before + # reporting a missing entry point (#49529). + _active_venv = sys.prefix != getattr(sys, "base_prefix", sys.prefix) + _environment_scripts_dir = None + if _active_venv: + try: + _scripts_path = sysconfig.get_path("scripts") + if _scripts_path: + _environment_scripts_dir = Path(_scripts_path) + except (KeyError, TypeError, ValueError): + pass + if _venv_bin is None and _environment_scripts_dir is not None: + # Windows console scripts are installed as .exe (plus .cmd/.bat + # shims); POSIX installs a bare . Check all platform variants so + # an environment-installed entry point is not reported missing on + # Windows (verified on Win11: venv\Scripts\hermes.exe, bare "hermes" + # absent) or in cross-layout venvs. + for _script_name in ("hermes", "hermes.exe", "hermes.cmd", "hermes.bat"): + _candidate = _environment_scripts_dir / _script_name if _candidate.exists(): _venv_bin = _candidate + _uses_environment_entry_point = True break - # A wheel-installed virtualenv keeps the console script under the - # environment's scripts directory while PROJECT_ROOT points inside - # site-packages. The source-checkout candidates above cannot describe - # that layout, so consult Python's platform-aware install scheme before - # reporting a missing entry point (#49529). - _active_venv = sys.prefix != getattr(sys, "base_prefix", sys.prefix) - _environment_scripts_dir = None - if _active_venv: - try: - _scripts_path = sysconfig.get_path("scripts") - if _scripts_path: - _environment_scripts_dir = Path(_scripts_path) - except (KeyError, TypeError, ValueError): - pass - if _venv_bin is None and _environment_scripts_dir is not None: - # Windows console scripts are installed as .exe (plus .cmd/.bat - # shims); POSIX installs a bare . Check all platform variants so - # an environment-installed entry point is not reported missing on - # Windows (verified on Win11: venv\Scripts\hermes.exe, bare "hermes" - # absent) or in cross-layout venvs. - for _script_name in ("hermes", "hermes.exe", "hermes.cmd", "hermes.bat"): - _candidate = _environment_scripts_dir / _script_name - if _candidate.exists(): - _venv_bin = _candidate - _uses_environment_entry_point = True - break - - _source_checkout = (PROJECT_ROOT / "pyproject.toml").is_file() + _source_checkout = (PROJECT_ROOT / "pyproject.toml").is_file() + if _venv_bin is None: + if _active_venv and not _source_checkout: + _expected_dir = _environment_scripts_dir or Path(sys.prefix) / "bin" + _reinstall_cmd = ( + f"{sys.executable} -m pip install --force-reinstall hermes-agent" + ) + check_warn( + "Venv entry point not found", + f"(hermes not in {_expected_dir} — reinstall with {_reinstall_cmd})", + ) + manual_issues.append(f"Reinstall entry point: {_reinstall_cmd}") + else: + check_warn( + "Venv entry point not found", + "(hermes not in venv/bin/ or .venv/bin/ — reinstall with pip install -e '.[all]')" + ) + manual_issues.append( + f"Reinstall entry point: cd {PROJECT_ROOT} && source venv/bin/activate && pip install -e '.[all]'" + ) + else: + try: + _venv_bin_display = _venv_bin.relative_to(PROJECT_ROOT) + except ValueError: + _venv_bin_display = _venv_bin + check_ok(f"Venv entry point exists ({_venv_bin_display})") + + # A wheel's console script is already installed in the active + # environment. Requiring a second global link would turn a + # healthy isolated venv into a false failure and make --fix leak + # that environment into the user's global command path. + if _uses_environment_entry_point and not _source_checkout: + check_ok("Active environment entry point needs no global symlink") + + # POSIX-only: the ~/.local/bin symlink management does not apply on + # Windows (command resolution goes through the console script + PATH). + if sys.platform != "win32": # Determine the expected command link directory (mirrors install.sh logic) _prefix = os.environ.get("PREFIX", "") _is_termux_env = bool(os.environ.get("TERMUX_VERSION")) or "com.termux/files/usr" in _prefix @@ -1675,39 +1715,8 @@ def run_doctor(args): _cmd_link_display = "~/.local/bin" _cmd_link = _cmd_link_dir / "hermes" - if _venv_bin is None: - if _active_venv and not _source_checkout: - _expected_dir = _environment_scripts_dir or Path(sys.prefix) / "bin" - _reinstall_cmd = ( - f"{sys.executable} -m pip install --force-reinstall hermes-agent" - ) - check_warn( - "Venv entry point not found", - f"(hermes not in {_expected_dir} — reinstall with {_reinstall_cmd})", - ) - manual_issues.append(f"Reinstall entry point: {_reinstall_cmd}") - else: - check_warn( - "Venv entry point not found", - "(hermes not in venv/bin/ or .venv/bin/ — reinstall with pip install -e '.[all]')" - ) - manual_issues.append( - f"Reinstall entry point: cd {PROJECT_ROOT} && source venv/bin/activate && pip install -e '.[all]'" - ) - else: - try: - _venv_bin_display = _venv_bin.relative_to(PROJECT_ROOT) - except ValueError: - _venv_bin_display = _venv_bin - check_ok(f"Venv entry point exists ({_venv_bin_display})") - - # A wheel's console script is already installed in the active - # environment. Requiring a second global link would turn a - # healthy isolated venv into a false failure and make --fix leak - # that environment into the user's global command path. - if _uses_environment_entry_point and not _source_checkout: - check_ok("Active environment entry point needs no global symlink") - elif _cmd_link.is_symlink(): + if _venv_bin is not None and not (_uses_environment_entry_point and not _source_checkout): + if _cmd_link.is_symlink(): _target = _cmd_link.resolve() _expected = _venv_bin.resolve() if _target == _expected: diff --git a/tests/hermes_cli/test_doctor_command_install.py b/tests/hermes_cli/test_doctor_command_install.py index d3f9a78a1f69..fc213235a2c8 100644 --- a/tests/hermes_cli/test_doctor_command_install.py +++ b/tests/hermes_cli/test_doctor_command_install.py @@ -253,17 +253,16 @@ def test_termux_uses_prefix_bin(self, monkeypatch, tmp_path): assert "Command Installation" in out assert "$PREFIX/bin" in out + @pytest.mark.skipif(sys.platform != "win32", reason="Tests the native Windows console-script layout") def test_wheel_virtualenv_windows_console_script_entry_point( self, monkeypatch, tmp_path ): """Windows console-script layout (hermes.exe in the env Scripts dir) - must be detected, not reported as a missing entry point (#49529, - verified on Win11: venv\\Scripts\\hermes.exe, bare \"hermes\" absent).""" + must be detected on a real win32 host — no platform fake. The + entry-point detection runs on all platforms; only symlink + management is POSIX-guarded (#49529, verified on Win11: + venv\\Scripts\\hermes.exe, bare \"hermes\" absent).""" _setup_doctor_env(monkeypatch, tmp_path) - # Reach the POSIX-guarded section on a win32 host without cascading - # POSIX-only stdlib imports (fcntl) through the doctor call chain. - _stub_posix_stdlib(monkeypatch) - monkeypatch.setattr(sys, "platform", "linux") venv = tmp_path / "wheel-venv" scripts = venv / "Scripts" scripts.mkdir(parents=True) @@ -289,19 +288,19 @@ def test_wheel_virtualenv_windows_console_script_entry_point( out = _run_doctor(fix=False) + assert "Command Installation" in out assert "Venv entry point exists" in out assert "hermes.exe" in out assert "Venv entry point not found" not in out assert "Active environment entry point needs no global symlink" in out + @pytest.mark.skipif(sys.platform != "win32", reason="Tests the native Windows console-script layout") def test_wheel_virtualenv_windows_console_script_missing_still_warns( self, monkeypatch, tmp_path ): """Windows layout with no console script at all must still warn (no false all-clear from the .exe/.cmd/.bat name scan).""" _setup_doctor_env(monkeypatch, tmp_path) - _stub_posix_stdlib(monkeypatch) - monkeypatch.setattr(sys, "platform", "linux") # reach the POSIX-guarded section venv = tmp_path / "wheel-venv" scripts = venv / "Scripts" scripts.mkdir(parents=True)