From b9b5e6607f1d844c260e0eca3e2d3da49b94c9da Mon Sep 17 00:00:00 2001 From: Daniel Meppiel Date: Mon, 11 May 2026 15:25:14 +0200 Subject: [PATCH 1/2] fix(tests): wrap Path.expanduser() to never raise on Windows runner Companion to #1272. After the Path.home() override landed, the windows-2025-vs2026 runner still red-marked two tests: tests/unit/install/test_user_scope_rejection_reason.py ::test_user_scope_accepts_tilde_local_path[~/pkg] ::test_user_scope_accepts_tilde_local_path[~/sub/pkg] These hit a different code path: production code in install.package_resolution.user_scope_rejection_reason calls Path('~/pkg').expanduser() to detect that the path is absolute. ntpath.expanduser raises RuntimeError('Could not determine home directory.') when both USERPROFILE and HOMEPATH are absent -- exactly the windows-2025-vs2026 worker env state. Fix in tests/conftest.py (root, loaded by every xdist worker before any test): - Wrap Path.expanduser. On RuntimeError, fall back to _TMP_HOME (the same hermetic dir Path.home() uses). The expanded path is still absolute, so production code's .is_absolute() check keeps behaving correctly. Regression trap added in tests/unit/test_path_home_override.py: clears HOME/USERPROFILE/HOMEDRIVE/HOMEPATH and asserts Path('~/pkg').expanduser() returns an absolute path without raising. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 1 + tests/conftest.py | 23 +++++++++++++++++++++++ tests/unit/test_path_home_override.py | 17 +++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e85c30c90..e723020bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Set the unit-test hermetic HOME at conftest import time so a single xdist worker on the `windows-2025-vs2026` runner can no longer race fixture setup and re-trigger the 53 `Path.home()` failures the session-scoped autouse fixture was supposed to prevent. (#1271) - Override `Path.home()` itself in the root test conftest so the 46 remaining Windows `RuntimeError: Could not determine home directory` failures on xdist worker `gw2` cannot recur regardless of which conftest the worker imports first; per-test `monkeypatch.setenv("HOME", ...)` continues to work because the override consults env vars before falling back to the hermetic tmp dir. (#1272) - Retry the `apm mcp search` and `apm mcp show` integration tests on the documented "Could not reach MCP registry" transient (with backoff and a final skip) so a brief `api.mcp.github.com` outage no longer red-marks the Windows integration job. (#1274) +- Also wrap `Path.expanduser()` in the root test conftest so the `windows-2025-vs2026` runner cannot raise `RuntimeError("Could not determine home directory.")` from `ntpath.expanduser` when production code (e.g. `install.package_resolution.user_scope_rejection_reason`) calls `Path("~/pkg").expanduser()`. Falls back to the hermetic tmp dir; assertions about `~/pkg` being absolute still hold. (#1275) ## [0.13.0] - 2026-05-11 diff --git a/tests/conftest.py b/tests/conftest.py index 1f498da66..df22375b3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -70,6 +70,29 @@ def _hermetic_home(_cls=Path) -> Path: Path.home = classmethod(_hermetic_home) # type: ignore[method-assign] +# Same problem, different code path: Path("~/pkg").expanduser() goes through +# ntpath.expanduser, which raises RuntimeError("Could not determine home +# directory.") on the windows-2025-vs2026 runner when USERPROFILE and +# HOMEPATH are both absent. Production code (e.g. install.package_resolution +# user_scope_rejection_reason) relies on expanduser to detect that ~/pkg is +# absolute. Wrap Path.expanduser so the RuntimeError can never surface. +_ORIGINAL_EXPANDUSER = Path.expanduser + + +def _hermetic_expanduser(self): + try: + return _ORIGINAL_EXPANDUSER(self) + except RuntimeError: + parts = self.parts + if not parts or not parts[0].startswith("~"): + return self + remainder = parts[1:] + return _TMP_HOME.joinpath(*remainder) if remainder else _TMP_HOME + + +Path.expanduser = _hermetic_expanduser # type: ignore[method-assign] + + @pytest.fixture(autouse=True, scope="session") def _validate_primitive_coverage(): """Fail fast if KNOWN_TARGETS has primitives without dispatch handlers.""" diff --git a/tests/unit/test_path_home_override.py b/tests/unit/test_path_home_override.py index 5e07bd897..dcc910d5d 100644 --- a/tests/unit/test_path_home_override.py +++ b/tests/unit/test_path_home_override.py @@ -31,3 +31,20 @@ def test_path_home_honors_per_test_home_setenv(monkeypatch, tmp_path): monkeypatch.setenv("HOME", str(target)) assert Path.home() == target + + +def test_path_expanduser_does_not_raise_with_cleared_env(monkeypatch): + """Path('~/pkg').expanduser() must not raise on the windows-2025-vs2026 runner. + + ntpath.expanduser raises RuntimeError when USERPROFILE and HOMEPATH are + both absent. Production code in install.package_resolution depends on + expanduser to detect that `~/pkg` is absolute. The root conftest wraps + Path.expanduser so this case falls back to the hermetic tmp dir. + """ + for key in ("HOME", "USERPROFILE", "HOMEDRIVE", "HOMEPATH"): + monkeypatch.delenv(key, raising=False) + + expanded = Path("~/pkg").expanduser() + + assert expanded.is_absolute() + assert expanded.name == "pkg" From 03d6a1b7883e60413f97daeb380bd306ea698da3 Mon Sep 17 00:00:00 2001 From: Daniel Meppiel Date: Mon, 11 May 2026 15:25:39 +0200 Subject: [PATCH 2/2] chore: correct PR number in CHANGELOG entry Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e723020bc..f16280684 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Set the unit-test hermetic HOME at conftest import time so a single xdist worker on the `windows-2025-vs2026` runner can no longer race fixture setup and re-trigger the 53 `Path.home()` failures the session-scoped autouse fixture was supposed to prevent. (#1271) - Override `Path.home()` itself in the root test conftest so the 46 remaining Windows `RuntimeError: Could not determine home directory` failures on xdist worker `gw2` cannot recur regardless of which conftest the worker imports first; per-test `monkeypatch.setenv("HOME", ...)` continues to work because the override consults env vars before falling back to the hermetic tmp dir. (#1272) - Retry the `apm mcp search` and `apm mcp show` integration tests on the documented "Could not reach MCP registry" transient (with backoff and a final skip) so a brief `api.mcp.github.com` outage no longer red-marks the Windows integration job. (#1274) -- Also wrap `Path.expanduser()` in the root test conftest so the `windows-2025-vs2026` runner cannot raise `RuntimeError("Could not determine home directory.")` from `ntpath.expanduser` when production code (e.g. `install.package_resolution.user_scope_rejection_reason`) calls `Path("~/pkg").expanduser()`. Falls back to the hermetic tmp dir; assertions about `~/pkg` being absolute still hold. (#1275) +- Also wrap `Path.expanduser()` in the root test conftest so the `windows-2025-vs2026` runner cannot raise `RuntimeError("Could not determine home directory.")` from `ntpath.expanduser` when production code (e.g. `install.package_resolution.user_scope_rejection_reason`) calls `Path("~/pkg").expanduser()`. Falls back to the hermetic tmp dir; assertions about `~/pkg` being absolute still hold. (#1276) ## [0.13.0] - 2026-05-11