Import split-out names from the modules that own them; drop the four lazy facades
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (push) Waiting to run
Tests / test (push) Waiting to run

hltb, _cmd_done, _whitelist and _actions each kept a module __getattr__
that served names moved out in the 250-line split, via importlib to
dodge the resulting import cycle. pylint cannot see through that, and
graded every such import as no-name-in-module (26 of them). The 32
import statements now name the real module; with nothing left going
through the facades, they are gone.

Also the pylint hook on 4.0.8 with the source-only scope config, the
three implicit-booleaness disables the reference repos carry, the
http.server do_GET admission, and the third-party pins the hook was
missing (aiohttp, websockets, howlongtobeatpy). Gate still 8.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHCbkJWXHjtTUaqvnHRAqA
This commit is contained in:
Krzysztof Rudnicki 2026-09-12 20:22:44 +02:00
parent 4783753b3f
commit 7323c896f6
37 changed files with 89 additions and 210 deletions

View File

@ -115,7 +115,7 @@ repos:
# PYLINT
# ===========================================================================
- repo: https://github.com/pylint-dev/pylint
rev: v3.3.2
rev: v4.0.8
hooks:
- id: pylint
exclude: ^scripts/file_length/
@ -128,9 +128,12 @@ repos:
# drags the score under --fail-under. `mcp` is a real runtime import
# (steam_backlog_enforcer._mcp_server).
additional_dependencies:
- mcp==2.1.1
- aiohttp==3.14.3
- howlongtobeatpy==1.0.23
- mcp==2.2.0
- pytest
- requests
- websockets==17.1
# ===========================================================================
# BANDIT - Security linter

View File

@ -119,16 +119,44 @@ exclude = [".venv/"]
# PYLINT
# ============================================================================
[tool.pylint.main]
# The repo root on the path, so pylint resolves the package's own imports the
# same way pytest does instead of reporting import-error for them.
init-hook = "import sys; sys.path.insert(0, '.')"
analyse-fallback-blocks = true
persistent = true
jobs = 0
py-version = "3.14"
ignore = [".venv", "__pycache__"]
# Test suites intentionally use patterns (protected-access, fixture-arg
# shadowing) that don't apply to source code; ruff's per-file-ignores carry
# the equivalent exemptions, so tests stay linted -- by ruff. This is the same
# source-only pylint scope wake-alarm / diet-guard / testsAndMisc use. It has
# to be `ignore-paths`, not `ignore = ["tests"]`: `ignore` only matches the
# basename of what pylint is *given*, and pre-commit hands it explicit file
# paths, so a directory name in `ignore` never fires under the hook.
ignore-paths = ["^(.*/)?tests/.*$"]
ignore-patterns = [".*\\.pyi$"]
[tool.pylint.basic]
# snake_case, plus the ``do_<METHOD>`` names http.server dispatches on: the
# stdlib looks handlers up as ``"do_" + command``, so ``do_GET`` is the only
# spelling that works and cannot be renamed to satisfy the style.
method-rgx = "([^\\W\\dA-Z][^\\WA-Z]{2,}|_[^\\WA-Z]*|__[^\\W\\dA-Z][^\\WA-Z]+__|do_[A-Z]+)$"
[tool.pylint.messages_control]
enable = "all"
disable = []
# Globally disabled checks, matching wake-alarm / diet-guard: each is a
# stylistic preference that conflicts with deliberate, clearer code.
# Everything else stays at max strictness.
disable = [
# use-implicit-booleaness family (C1803/C1804/C1805): pylint wants
# `not x` / `not s` instead of `x == 0` / `s == ""`. Explicit comparisons
# against 0 and "" state numeric/string intent more clearly than truthiness
# (and are not equivalent when the value may be None), so we keep them.
"use-implicit-booleaness-not-comparison",
"use-implicit-booleaness-not-comparison-to-string",
"use-implicit-booleaness-not-comparison-to-zero",
]
[tool.pylint.design]
min-public-methods = 0

View File

@ -10,7 +10,6 @@ there is a single tested implementation of the underlying behaviour.
from __future__ import annotations
from datetime import UTC, datetime
import importlib
from typing import TYPE_CHECKING, Any
from steam_backlog_enforcer._allowed_games import (
@ -147,32 +146,3 @@ def apply_manual_pick(
state.enforcement_started_at = now
state.save()
return None
_MOVED_TO_MANUAL_PICK_LIFECYCLE = frozenset(
{
"abandon_manual_pick",
"manual_pick_age_days",
"status_payload",
}
)
# Whatever the re-exported name turns out to be -- a function, a class or
# a constant. Aliased so the annotation is a name rather than a bare Any.
type _Reexport = Any
def __getattr__(name: str) -> _Reexport:
"""Re-export the names that moved to :mod:`_manual_pick_lifecycle`.
Deferred rather than imported at the top because _manual_pick_lifecycle imports
back from this module, so a module-level import would be circular.
"""
if name in _MOVED_TO_MANUAL_PICK_LIFECYCLE:
module = importlib.import_module(
"steam_backlog_enforcer._manual_pick_lifecycle",
)
return getattr(module, name)
msg = f"module {__name__!r} has no attribute {name!r}"
raise AttributeError(msg)

View File

@ -2,22 +2,21 @@
from __future__ import annotations
import importlib
import logging
import sys
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING
from steam_backlog_enforcer._snapshot import load_snapshot
from steam_backlog_enforcer.game_install import (
_echo,
)
from steam_backlog_enforcer.hltb import (
fetch_hltb_confidence_cached,
fetch_hltb_times_cached,
from steam_backlog_enforcer._hltb_cached import fetch_hltb_times_cached
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_confidence_cached
from steam_backlog_enforcer._hltb_types import (
load_hltb_cache,
load_hltb_polls_cache,
save_hltb_cache,
)
from steam_backlog_enforcer._snapshot import load_snapshot
from steam_backlog_enforcer.game_install import (
_echo,
)
if TYPE_CHECKING:
from steam_backlog_enforcer.config import State
@ -173,30 +172,3 @@ def _refresh_uncached_shortlist_hours(
if shorter_uncached:
refreshed = fetch_hltb_times_cached(shorter_uncached)
hltb_cache.update(refreshed)
_MOVED_TO_CMD_DONE_FINALIZE = frozenset(
{
"_enforce_on_done",
"_finalize_completion",
"cmd_done",
}
)
# Whatever the re-exported name turns out to be -- a function, a class or
# a constant. Aliased so the annotation is a name rather than a bare Any.
type _Reexport = Any
def __getattr__(name: str) -> _Reexport:
"""Re-export the names that moved to :mod:`_cmd_done_finalize`.
Deferred rather than imported at the top because _cmd_done_finalize imports
back from this module, so a module-level import would be circular.
"""
if name in _MOVED_TO_CMD_DONE_FINALIZE:
module = importlib.import_module("steam_backlog_enforcer._cmd_done_finalize")
return getattr(module, name)
msg = f"module {__name__!r} has no attribute {name!r}"
raise AttributeError(msg)

View File

@ -17,6 +17,8 @@ from steam_backlog_enforcer._cmd_done import (
_report_assigned_confidence,
)
from steam_backlog_enforcer._enforce_loop import get_all_owned_app_ids
from steam_backlog_enforcer._hltb_cached import fetch_hltb_times_cached
from steam_backlog_enforcer._hltb_types import load_hltb_cache
from steam_backlog_enforcer._pick_completion import mark_finished
from steam_backlog_enforcer._snapshot import load_snapshot
from steam_backlog_enforcer.enforcer import (
@ -29,10 +31,6 @@ from steam_backlog_enforcer.game_install import (
is_game_installed,
uninstall_other_games,
)
from steam_backlog_enforcer.hltb import (
fetch_hltb_times_cached,
load_hltb_cache,
)
from steam_backlog_enforcer.library_hider import try_hide_other_games
from steam_backlog_enforcer.scanning import pick_next_game
from steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient

View File

@ -29,9 +29,7 @@ from steam_backlog_enforcer._total_block import (
is_total_block_active,
total_block_needs_cleanup,
)
from steam_backlog_enforcer._whitelist import (
lock_enforcement_files,
)
from steam_backlog_enforcer._whitelist_locking import lock_enforcement_files
from steam_backlog_enforcer.config import (
CONFIG_FILE,
Config,

View File

@ -11,13 +11,15 @@ from typing import Any
from steam_backlog_enforcer._actions import (
ABANDON_COOLDOWN_DAYS,
abandon_manual_pick,
active_manual_picks,
apply_manual_pick,
find_manual_pick,
manual_pick_age_days,
)
from steam_backlog_enforcer._allowed_games import MANUAL_LOCK_DAYS
from steam_backlog_enforcer._manual_pick_lifecycle import (
abandon_manual_pick,
manual_pick_age_days,
)
from steam_backlog_enforcer._mcp_server import (
_resolve_game_name,
logger,

View File

@ -9,9 +9,7 @@ from __future__ import annotations
from typing import Any
from steam_backlog_enforcer._actions import (
status_payload,
)
from steam_backlog_enforcer._manual_pick_lifecycle import status_payload
from steam_backlog_enforcer._mcp_server import (
_DEFAULT_LIST_LIMIT,
_backlog_sort_key,

View File

@ -14,7 +14,10 @@ import logging
from typing import TYPE_CHECKING
from steam_backlog_enforcer._budget_resolve import resolve_budget
from steam_backlog_enforcer._whitelist import _try_set_immutable, unlock_for_write
from steam_backlog_enforcer._whitelist_locking import (
_try_set_immutable,
unlock_for_write,
)
from steam_backlog_enforcer.config import CONFIG_DIR, _atomic_write
if TYPE_CHECKING:

View File

@ -9,12 +9,12 @@ import logging
from typing import TYPE_CHECKING
from steam_backlog_enforcer._echo import _echo
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_confidence_cached
from steam_backlog_enforcer._hltb_types import (
load_hltb_cache,
load_hltb_polls_cache,
save_hltb_cache,
)
from steam_backlog_enforcer.hltb import fetch_hltb_confidence_cached
if TYPE_CHECKING:
from steam_backlog_enforcer._steam_models import GameInfo

View File

@ -5,6 +5,7 @@ from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_confidence_cached
from steam_backlog_enforcer._hltb_types import (
_HLTBExtras,
load_hltb_cache,
@ -13,7 +14,6 @@ from steam_backlog_enforcer._hltb_types import (
save_hltb_cache,
)
from steam_backlog_enforcer.game_install import _echo
from steam_backlog_enforcer.hltb import fetch_hltb_confidence_cached
if TYPE_CHECKING:
from steam_backlog_enforcer.steam_api import GameInfo

View File

@ -11,13 +11,13 @@ import secrets
from typing import TYPE_CHECKING
from urllib.parse import quote_plus
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_detail_missing
from steam_backlog_enforcer._hltb_types import (
HLTB_BASE_URL,
load_hltb_game_id_cache,
)
from steam_backlog_enforcer._stats_types import _HLTB_SEARCH_BASE, _GameTimes
from steam_backlog_enforcer.game_install import _echo
from steam_backlog_enforcer.hltb import fetch_hltb_detail_missing
if TYPE_CHECKING:
from steam_backlog_enforcer.config import State

View File

@ -10,6 +10,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
import logging
from typing import TYPE_CHECKING
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_detail_missing
from steam_backlog_enforcer._hltb_types import (
load_hltb_cache,
load_hltb_game_id_cache,
@ -24,7 +25,6 @@ from steam_backlog_enforcer._scanning_confidence import (
from steam_backlog_enforcer._stats_types import _GameTimes
from steam_backlog_enforcer.config import SNAPSHOT_FILE
from steam_backlog_enforcer.game_install import _echo
from steam_backlog_enforcer.hltb import fetch_hltb_detail_missing
from steam_backlog_enforcer.protondb import (
ProtonDBRating,
fetch_protondb_ratings,

View File

@ -3,11 +3,10 @@
from __future__ import annotations
from collections import Counter
import importlib
import logging
import math
import re
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING
from steam_backlog_enforcer.config import CONFIG_DIR
@ -112,35 +111,3 @@ def validate_reason(reason: str) -> str | None:
# long); FS_IMMUTABLE_FL is the "immutable" bit that `chattr +i` sets.
_FS_IOC_GETFLAGS = 0x80086601
_FS_IMMUTABLE_FL = 0x00000010
_MOVED_TO_WHITELIST_LOCKING = frozenset(
{
"_append_audit_log",
"_immutable_flag_is",
"_load_approved",
"_save_approved",
"_try_set_immutable",
"add_pending_exception",
"get_approved_exception_ids",
"lock_enforcement_files",
"unlock_for_write",
}
)
# Whatever the re-exported name turns out to be -- a function, a class or
# a constant. Aliased so the annotation is a name rather than a bare Any.
type _Reexport = Any
def __getattr__(name: str) -> _Reexport:
"""Re-export the names that moved to :mod:`_whitelist_locking`.
Deferred rather than imported at the top because _whitelist_locking imports
back from this module, so a module-level import would be circular.
"""
if name in _MOVED_TO_WHITELIST_LOCKING:
module = importlib.import_module("steam_backlog_enforcer._whitelist_locking")
return getattr(module, name)
msg = f"module {__name__!r} has no attribute {name!r}"
raise AttributeError(msg)

View File

@ -16,7 +16,7 @@ from typing import TYPE_CHECKING
from steam_backlog_enforcer._game_names import _is_protected_name
from steam_backlog_enforcer._protected_apps import PROTECTED_APP_IDS
from steam_backlog_enforcer._steam_state import STEAMAPPS_PATH, _assert_not_real_steam
from steam_backlog_enforcer._whitelist import get_approved_exception_ids
from steam_backlog_enforcer._whitelist_locking import get_approved_exception_ids
if TYPE_CHECKING:
from pathlib import Path

View File

@ -13,9 +13,7 @@ Fetches leisure completionist hour estimates from howlongtobeat.com with:
from __future__ import annotations
import asyncio
import importlib
import logging
from typing import Any
import aiohttp
@ -167,41 +165,3 @@ def fetch_hltb_confidence(
count_comp=count_comp,
)
)
_REEXPORTED = {
"HLTB_BASE_URL": "steam_backlog_enforcer._hltb_types",
"MAX_CONCURRENT": "steam_backlog_enforcer._hltb_types",
"HLTBResult": "steam_backlog_enforcer._hltb_types",
"ProgressCb": "steam_backlog_enforcer._hltb_types",
"_HLTBExtras": "steam_backlog_enforcer._hltb_types",
"load_hltb_cache": "steam_backlog_enforcer._hltb_types",
"load_hltb_count_comp_cache": "steam_backlog_enforcer._hltb_types",
"load_hltb_game_id_cache": "steam_backlog_enforcer._hltb_types",
"load_hltb_leisure_100h_cache": "steam_backlog_enforcer._hltb_types",
"load_hltb_polls_cache": "steam_backlog_enforcer._hltb_types",
"load_hltb_rush_cache": "steam_backlog_enforcer._hltb_types",
"save_hltb_cache": "steam_backlog_enforcer._hltb_types",
"fetch_hltb_times_cached": "steam_backlog_enforcer._hltb_cached",
"fetch_hltb_confidence_cached": "steam_backlog_enforcer._hltb_confidence",
"fetch_hltb_detail_missing": "steam_backlog_enforcer._hltb_confidence",
"get_hltb_submit_url": "steam_backlog_enforcer._hltb_confidence",
}
# Whatever the re-exported name turns out to be -- a function, a class or
# a constant. Aliased so the annotation is a name rather than a bare Any.
type _Reexport = Any
def __getattr__(name: str) -> _Reexport:
"""Serve names that moved out of this module when it was split.
Deferred via importlib rather than imported at the top: the modules below
import back from here, so a module-level import would be circular.
"""
home = _REEXPORTED.get(name)
if home is not None:
return getattr(importlib.import_module(home), name)
msg = f"module {__name__!r} has no attribute {name!r}"
raise AttributeError(msg)

View File

@ -16,7 +16,7 @@ from typing import TYPE_CHECKING
from steam_backlog_enforcer._allowed_games import (
MANUAL_LOCK_DAYS as _MANUAL_LOCK_DAYS,
)
from steam_backlog_enforcer._cmd_done import cmd_done
from steam_backlog_enforcer._cmd_done_finalize import cmd_done
from steam_backlog_enforcer._cmd_playtime import (
cmd_enforce,
cmd_gaming_reset,

View File

@ -11,16 +11,14 @@ from datetime import UTC, datetime, timedelta
import sys
from typing import TYPE_CHECKING
from steam_backlog_enforcer._actions import (
active_manual_picks,
manual_pick_age_days,
)
from steam_backlog_enforcer._actions import active_manual_picks
from steam_backlog_enforcer._actions import (
is_manual_pick_locked as _is_manual_pick_locked,
)
from steam_backlog_enforcer._allowed_games import (
MANUAL_LOCK_DAYS as _MANUAL_LOCK_DAYS,
)
from steam_backlog_enforcer._manual_pick_lifecycle import manual_pick_age_days
from steam_backlog_enforcer._total_block import (
TotalBlockStatus,
get_total_block_status,

View File

@ -9,10 +9,10 @@ from steam_backlog_enforcer._actions import (
ABANDON_COOLDOWN_DAYS as _ABANDON_COOLDOWN_DAYS,
)
from steam_backlog_enforcer._actions import (
abandon_manual_pick,
active_manual_picks,
find_manual_pick,
)
from steam_backlog_enforcer._manual_pick_lifecycle import abandon_manual_pick
from steam_backlog_enforcer.game_install import (
_echo,
is_game_installed,

View File

@ -19,10 +19,8 @@ from steam_backlog_enforcer._serve_startup import (
from steam_backlog_enforcer._total_block import start_total_block
from steam_backlog_enforcer._web_build import build_frontend, frontend_is_stale
from steam_backlog_enforcer._web_server import serve
from steam_backlog_enforcer._whitelist import (
add_pending_exception,
validate_reason,
)
from steam_backlog_enforcer._whitelist import validate_reason
from steam_backlog_enforcer._whitelist_locking import add_pending_exception
from steam_backlog_enforcer.game_install import _echo
from steam_backlog_enforcer.library_hider import restart_steam, unhide_all_games
from steam_backlog_enforcer.store_blocker import block_store, unblock_store

View File

@ -4,10 +4,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from steam_backlog_enforcer._actions import (
active_manual_picks,
manual_pick_age_days,
)
from steam_backlog_enforcer._actions import active_manual_picks
from steam_backlog_enforcer._manual_pick_lifecycle import manual_pick_age_days
from steam_backlog_enforcer._pick_completion import report_completion
from steam_backlog_enforcer._snapshot import load_snapshot
from steam_backlog_enforcer._total_block import get_total_block_status

View File

@ -6,6 +6,7 @@ import logging
import time
from typing import TYPE_CHECKING
from steam_backlog_enforcer._hltb_cached import fetch_hltb_times_cached
from steam_backlog_enforcer._hltb_types import (
load_hltb_count_comp_cache,
load_hltb_polls_cache,
@ -39,9 +40,6 @@ from steam_backlog_enforcer.enforcer import (
from steam_backlog_enforcer.game_install import (
_echo,
)
from steam_backlog_enforcer.hltb import (
fetch_hltb_times_cached,
)
from steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient
if TYPE_CHECKING:

View File

@ -10,8 +10,8 @@ from steam_backlog_enforcer import _allowed_games
from steam_backlog_enforcer._actions import (
apply_manual_pick,
is_manual_pick_locked,
manual_pick_age_days,
)
from steam_backlog_enforcer._manual_pick_lifecycle import manual_pick_age_days
from steam_backlog_enforcer.config import State

View File

@ -6,7 +6,6 @@ from datetime import UTC, datetime, timedelta
from steam_backlog_enforcer import _actions, _allowed_games
from steam_backlog_enforcer._actions import (
abandon_manual_pick,
active_manual_picks,
allowed_app_ids,
allowed_games,
@ -15,6 +14,7 @@ from steam_backlog_enforcer._actions import (
is_manual_pick_locked,
manual_pick_slots_left,
)
from steam_backlog_enforcer._manual_pick_lifecycle import abandon_manual_pick
from steam_backlog_enforcer.config import State

View File

@ -5,9 +5,7 @@ from __future__ import annotations
from datetime import UTC, datetime, timedelta
from unittest.mock import patch
from steam_backlog_enforcer._actions import (
status_payload,
)
from steam_backlog_enforcer._manual_pick_lifecycle import status_payload
from steam_backlog_enforcer._total_block import TotalBlockStatus
from steam_backlog_enforcer.config import State

View File

@ -12,11 +12,11 @@ import aiohttp
from steam_backlog_enforcer._hltb_matching import _similarity
from steam_backlog_enforcer._hltb_search import _AuthInfo
from steam_backlog_enforcer._hltb_search_api import _get_hltb_search_url
from steam_backlog_enforcer.hltb import (
_get_auth_info,
from steam_backlog_enforcer._hltb_types import (
load_hltb_cache,
save_hltb_cache,
)
from steam_backlog_enforcer.hltb import _get_auth_info
if TYPE_CHECKING:
from pathlib import Path

View File

@ -6,11 +6,11 @@ import asyncio
from typing import Self
from unittest.mock import patch
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_confidence_cached
from steam_backlog_enforcer._hltb_search import _AuthInfo
from steam_backlog_enforcer.hltb import (
_fetch_batch_confidence_only,
fetch_hltb_confidence,
fetch_hltb_confidence_cached,
)
PKG = "steam_backlog_enforcer.hltb"

View File

@ -5,9 +5,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Self
from unittest.mock import patch
from steam_backlog_enforcer.hltb import (
fetch_hltb_detail_missing,
)
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_detail_missing
if TYPE_CHECKING:
from steam_backlog_enforcer._hltb_types import _HLTBExtras

View File

@ -5,11 +5,11 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Self
from unittest.mock import MagicMock, patch
from steam_backlog_enforcer.hltb import (
from steam_backlog_enforcer._hltb_cached import fetch_hltb_times_cached
from steam_backlog_enforcer._hltb_confidence import get_hltb_submit_url
from steam_backlog_enforcer._hltb_types import (
HLTB_BASE_URL,
HLTBResult,
fetch_hltb_times_cached,
get_hltb_submit_url,
)
if TYPE_CHECKING:

View File

@ -4,10 +4,8 @@ from __future__ import annotations
from unittest.mock import patch
from steam_backlog_enforcer.hltb import (
HLTBResult,
fetch_hltb_times,
)
from steam_backlog_enforcer._hltb_types import HLTBResult
from steam_backlog_enforcer.hltb import fetch_hltb_times
class TestFetchHltbTimes:

View File

@ -5,9 +5,7 @@ from unittest.mock import (
patch,
)
from steam_backlog_enforcer._cmd_done import (
_finalize_completion,
)
from steam_backlog_enforcer._cmd_done_finalize import _finalize_completion
from steam_backlog_enforcer.config import Config, State
CMD_DONE_PKG = "steam_backlog_enforcer._cmd_done_finalize"

View File

@ -3,7 +3,7 @@
from typing import Any
from unittest.mock import MagicMock, patch
from steam_backlog_enforcer._cmd_done import (
from steam_backlog_enforcer._cmd_done_finalize import (
_enforce_on_done,
cmd_done,
)

View File

@ -5,9 +5,7 @@ from unittest.mock import (
patch,
)
from steam_backlog_enforcer._cmd_done import (
_finalize_completion,
)
from steam_backlog_enforcer._cmd_done_finalize import _finalize_completion
from steam_backlog_enforcer.config import Config, State
if TYPE_CHECKING:

View File

@ -7,9 +7,9 @@ from unittest.mock import patch
from steam_backlog_enforcer._whitelist import (
_shannon_entropy,
_try_set_immutable,
validate_reason,
)
from steam_backlog_enforcer._whitelist_locking import _try_set_immutable
if TYPE_CHECKING:
from pathlib import Path

View File

@ -6,12 +6,12 @@ from unittest.mock import patch
import pytest
from steam_backlog_enforcer._whitelist import (
from steam_backlog_enforcer._whitelist import validate_reason
from steam_backlog_enforcer._whitelist_locking import (
_load_approved,
_save_approved,
add_pending_exception,
get_approved_exception_ids,
validate_reason,
)
# ──────────────────────────────────────────────────────────────

View File

@ -5,7 +5,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from unittest.mock import patch
from steam_backlog_enforcer._whitelist import (
from steam_backlog_enforcer._whitelist_locking import (
_immutable_flag_is,
_load_approved,
_save_approved,

View File

@ -5,9 +5,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from unittest.mock import patch
from steam_backlog_enforcer._whitelist import (
_append_audit_log,
)
from steam_backlog_enforcer._whitelist_locking import _append_audit_log
if TYPE_CHECKING:
from pathlib import Path