Re-arm the no-library warning before install_game's early return

The one-shot latch that stops the "Steam library not initialised" warning
repeating every 3s was only cleared *after* the is_game_installed() early
return. So once Steam was signed in and a game was installed, the latch
stayed set: if the library later vanished the warning would never fire
again, and the outage would be silent.

Clear it at the top instead, before any return. Found by writing the test
for the latch's debug branch, which was the last uncovered code in the
package.

Coverage is now 100.00% (1347 tests) under .ci-mirror-venv, which is the
gate CI actually runs -- system python3 has mcp 2.0 against a pinned mcp<2,
so test_mcp*.py cannot collect there and coverage reads low.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016A1EYiv7e7HGhET84oa9M3
This commit is contained in:
Krzysztof Rudnicki 2026-08-24 14:04:54 +02:00
parent 21fe2f7742
commit 919ecdfd62
2 changed files with 49 additions and 2 deletions

View File

@ -130,6 +130,11 @@ def install_game(
"""
label = game_name or f"AppID={app_id}"
# Re-arm the one-shot warning before any early return, so a library that
# comes back (Steam finally signed in) is reported again if it vanishes.
if steam_library_ready():
_LIBRARY_WARNED.discard("missing")
if is_game_installed(app_id):
logger.info("Game already installed: %s", label)
return True
@ -149,8 +154,6 @@ def install_game(
logger.debug("Skipping install of %s: no Steam library.", label)
return False
_LIBRARY_WARNED.discard("missing")
if use_steam_protocol:
_ensure_steam_running()
if _trigger_steam_install(app_id, label):

View File

@ -5,6 +5,7 @@ Split from test_game_install_part3.py to keep both files under the 250-line cap.
from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from unittest.mock import MagicMock, patch
@ -13,6 +14,8 @@ from steam_backlog_enforcer.game_install import install_game
if TYPE_CHECKING:
from pathlib import Path
import pytest
class TestInstallGameLibraryGuard:
"""install_game must not retry when Steam has no library at all.
@ -84,3 +87,44 @@ class TestReinstallMissingAllowedGuard:
_reinstall_missing_allowed(MagicMock(), MagicMock())
mock_install.assert_called_once()
class TestLibraryWarningLatch:
"""The "no library" warning must fire once, not once per game per pass.
At the observed 3s cadence an unlatched warning replaces a traceback storm
with a log storm, which is the same bug in a different costume.
"""
_PKG = "steam_backlog_enforcer.game_install"
def test_warns_once_then_debugs(self, caplog: pytest.LogCaptureFixture) -> None:
from steam_backlog_enforcer.game_install import _LIBRARY_WARNED
_LIBRARY_WARNED.discard("missing")
with (
patch(f"{self._PKG}.steam_library_ready", return_value=False),
caplog.at_level(
logging.DEBUG, logger="steam_backlog_enforcer.game_install"
),
):
for _ in range(3):
install_game(440, "TF2", "steam123")
warnings = [r for r in caplog.records if r.levelno == logging.WARNING]
debugs = [r for r in caplog.records if r.levelno == logging.DEBUG]
assert len(warnings) == 1
assert len(debugs) == 2
def test_latch_resets_when_library_returns(self) -> None:
"""Signing in to Steam must re-arm the warning for a later outage."""
from steam_backlog_enforcer.game_install import _LIBRARY_WARNED
_LIBRARY_WARNED.add("missing")
with (
patch(f"{self._PKG}.steam_library_ready", return_value=True),
patch(f"{self._PKG}.is_game_installed", return_value=True),
):
install_game(440, "TF2", "steam123")
assert "missing" not in _LIBRARY_WARNED