""" Every test runs with its own home, and never touches the developer's own. Redirecting HOME alone isolates nothing on Windows — `Path.home()` reads USERPROFILE there, and the CLI's directories come from LOCALAPPDATA — so all of them are pointed at a throwaway directory. The OS key storage is replaced by keyring's refusing backend: a test must never write into the developer's real credential store, and the store's file fallback is what a headless machine uses anyway. A test that needs a working key storage installs its own backend. """ import logging import pytest @pytest.fixture(autouse=True) def isolated_home(tmp_path, monkeypatch): home = tmp_path / "home" home.mkdir() for var in ("HOME", "USERPROFILE"): monkeypatch.setenv(var, str(home)) for var, sub in (("APPDATA", "AppData/Roaming"), ("LOCALAPPDATA", "AppData/Local"), ("XDG_CONFIG_HOME", ".config"), ("XDG_DATA_HOME", ".local/share")): monkeypatch.setenv(var, str(home / sub)) for var in ("MESHBAY_CLI_HOME", "MESHBAY_HUB", "MESHBAY_USER", "MESHBAY_PASSWORD"): monkeypatch.delenv(var, raising=False) monkeypatch.setenv("PYTHON_KEYRING_BACKEND", "keyring.backends.fail.Keyring") return home @pytest.fixture(autouse=True) def restored_logging(): """`main()` configures logging, as an entry point does; a test that calls it in-process must not leave that configuration to the next package's tests.""" root = logging.getLogger() names = ("meshbay_cli", "aiortc", "aioice", "httpx", "httpcore") saved = (list(root.handlers), root.level, root.disabled, {n: logging.getLogger(n).level for n in names}) yield handlers, level, disabled, levels = saved for h in root.handlers: if h not in handlers: h.close() root.handlers[:] = handlers root.setLevel(level) root.disabled = disabled for n, lv in levels.items(): logging.getLogger(n).setLevel(lv)