mirror of
https://github.com/kuhyx/steam-backlog-enforcer.git
synced 2026-11-10 19:27:04 +01:00
Import split-out names from the modules that own them; drop the four lazy facades
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:
parent
4783753b3f
commit
7323c896f6
@ -115,7 +115,7 @@ repos:
|
|||||||
# PYLINT
|
# PYLINT
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
- repo: https://github.com/pylint-dev/pylint
|
- repo: https://github.com/pylint-dev/pylint
|
||||||
rev: v3.3.2
|
rev: v4.0.8
|
||||||
hooks:
|
hooks:
|
||||||
- id: pylint
|
- id: pylint
|
||||||
exclude: ^scripts/file_length/
|
exclude: ^scripts/file_length/
|
||||||
@ -128,9 +128,12 @@ repos:
|
|||||||
# drags the score under --fail-under. `mcp` is a real runtime import
|
# drags the score under --fail-under. `mcp` is a real runtime import
|
||||||
# (steam_backlog_enforcer._mcp_server).
|
# (steam_backlog_enforcer._mcp_server).
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
- mcp==2.1.1
|
- aiohttp==3.14.3
|
||||||
|
- howlongtobeatpy==1.0.23
|
||||||
|
- mcp==2.2.0
|
||||||
- pytest
|
- pytest
|
||||||
- requests
|
- requests
|
||||||
|
- websockets==17.1
|
||||||
|
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# BANDIT - Security linter
|
# BANDIT - Security linter
|
||||||
|
|||||||
@ -119,16 +119,44 @@ exclude = [".venv/"]
|
|||||||
# PYLINT
|
# PYLINT
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
[tool.pylint.main]
|
[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
|
analyse-fallback-blocks = true
|
||||||
persistent = true
|
persistent = true
|
||||||
jobs = 0
|
jobs = 0
|
||||||
py-version = "3.14"
|
py-version = "3.14"
|
||||||
ignore = [".venv", "__pycache__"]
|
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$"]
|
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]
|
[tool.pylint.messages_control]
|
||||||
enable = "all"
|
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]
|
[tool.pylint.design]
|
||||||
min-public-methods = 0
|
min-public-methods = 0
|
||||||
|
|||||||
@ -10,7 +10,6 @@ there is a single tested implementation of the underlying behaviour.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import UTC, datetime
|
from datetime import UTC, datetime
|
||||||
import importlib
|
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from steam_backlog_enforcer._allowed_games import (
|
from steam_backlog_enforcer._allowed_games import (
|
||||||
@ -147,32 +146,3 @@ def apply_manual_pick(
|
|||||||
state.enforcement_started_at = now
|
state.enforcement_started_at = now
|
||||||
state.save()
|
state.save()
|
||||||
return None
|
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)
|
|
||||||
|
|||||||
@ -2,22 +2,21 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import importlib
|
|
||||||
import logging
|
import logging
|
||||||
import sys
|
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._hltb_cached import fetch_hltb_times_cached
|
||||||
from steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_confidence_cached
|
||||||
_echo,
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
)
|
|
||||||
from steam_backlog_enforcer.hltb import (
|
|
||||||
fetch_hltb_confidence_cached,
|
|
||||||
fetch_hltb_times_cached,
|
|
||||||
load_hltb_cache,
|
load_hltb_cache,
|
||||||
load_hltb_polls_cache,
|
load_hltb_polls_cache,
|
||||||
save_hltb_cache,
|
save_hltb_cache,
|
||||||
)
|
)
|
||||||
|
from steam_backlog_enforcer._snapshot import load_snapshot
|
||||||
|
from steam_backlog_enforcer.game_install import (
|
||||||
|
_echo,
|
||||||
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from steam_backlog_enforcer.config import State
|
from steam_backlog_enforcer.config import State
|
||||||
@ -173,30 +172,3 @@ def _refresh_uncached_shortlist_hours(
|
|||||||
if shorter_uncached:
|
if shorter_uncached:
|
||||||
refreshed = fetch_hltb_times_cached(shorter_uncached)
|
refreshed = fetch_hltb_times_cached(shorter_uncached)
|
||||||
hltb_cache.update(refreshed)
|
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)
|
|
||||||
|
|||||||
@ -17,6 +17,8 @@ from steam_backlog_enforcer._cmd_done import (
|
|||||||
_report_assigned_confidence,
|
_report_assigned_confidence,
|
||||||
)
|
)
|
||||||
from steam_backlog_enforcer._enforce_loop import get_all_owned_app_ids
|
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._pick_completion import mark_finished
|
||||||
from steam_backlog_enforcer._snapshot import load_snapshot
|
from steam_backlog_enforcer._snapshot import load_snapshot
|
||||||
from steam_backlog_enforcer.enforcer import (
|
from steam_backlog_enforcer.enforcer import (
|
||||||
@ -29,10 +31,6 @@ from steam_backlog_enforcer.game_install import (
|
|||||||
is_game_installed,
|
is_game_installed,
|
||||||
uninstall_other_games,
|
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.library_hider import try_hide_other_games
|
||||||
from steam_backlog_enforcer.scanning import pick_next_game
|
from steam_backlog_enforcer.scanning import pick_next_game
|
||||||
from steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient
|
from steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient
|
||||||
|
|||||||
@ -29,9 +29,7 @@ from steam_backlog_enforcer._total_block import (
|
|||||||
is_total_block_active,
|
is_total_block_active,
|
||||||
total_block_needs_cleanup,
|
total_block_needs_cleanup,
|
||||||
)
|
)
|
||||||
from steam_backlog_enforcer._whitelist import (
|
from steam_backlog_enforcer._whitelist_locking import lock_enforcement_files
|
||||||
lock_enforcement_files,
|
|
||||||
)
|
|
||||||
from steam_backlog_enforcer.config import (
|
from steam_backlog_enforcer.config import (
|
||||||
CONFIG_FILE,
|
CONFIG_FILE,
|
||||||
Config,
|
Config,
|
||||||
|
|||||||
@ -11,13 +11,15 @@ from typing import Any
|
|||||||
|
|
||||||
from steam_backlog_enforcer._actions import (
|
from steam_backlog_enforcer._actions import (
|
||||||
ABANDON_COOLDOWN_DAYS,
|
ABANDON_COOLDOWN_DAYS,
|
||||||
abandon_manual_pick,
|
|
||||||
active_manual_picks,
|
active_manual_picks,
|
||||||
apply_manual_pick,
|
apply_manual_pick,
|
||||||
find_manual_pick,
|
find_manual_pick,
|
||||||
manual_pick_age_days,
|
|
||||||
)
|
)
|
||||||
from steam_backlog_enforcer._allowed_games import MANUAL_LOCK_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 (
|
from steam_backlog_enforcer._mcp_server import (
|
||||||
_resolve_game_name,
|
_resolve_game_name,
|
||||||
logger,
|
logger,
|
||||||
|
|||||||
@ -9,9 +9,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from steam_backlog_enforcer._actions import (
|
from steam_backlog_enforcer._manual_pick_lifecycle import status_payload
|
||||||
status_payload,
|
|
||||||
)
|
|
||||||
from steam_backlog_enforcer._mcp_server import (
|
from steam_backlog_enforcer._mcp_server import (
|
||||||
_DEFAULT_LIST_LIMIT,
|
_DEFAULT_LIST_LIMIT,
|
||||||
_backlog_sort_key,
|
_backlog_sort_key,
|
||||||
|
|||||||
@ -14,7 +14,10 @@ import logging
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from steam_backlog_enforcer._budget_resolve import resolve_budget
|
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
|
from steam_backlog_enforcer.config import CONFIG_DIR, _atomic_write
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|||||||
@ -9,12 +9,12 @@ import logging
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from steam_backlog_enforcer._echo import _echo
|
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 (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
load_hltb_cache,
|
load_hltb_cache,
|
||||||
load_hltb_polls_cache,
|
load_hltb_polls_cache,
|
||||||
save_hltb_cache,
|
save_hltb_cache,
|
||||||
)
|
)
|
||||||
from steam_backlog_enforcer.hltb import fetch_hltb_confidence_cached
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from steam_backlog_enforcer._steam_models import GameInfo
|
from steam_backlog_enforcer._steam_models import GameInfo
|
||||||
|
|||||||
@ -5,6 +5,7 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_confidence_cached
|
||||||
from steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
_HLTBExtras,
|
_HLTBExtras,
|
||||||
load_hltb_cache,
|
load_hltb_cache,
|
||||||
@ -13,7 +14,6 @@ from steam_backlog_enforcer._hltb_types import (
|
|||||||
save_hltb_cache,
|
save_hltb_cache,
|
||||||
)
|
)
|
||||||
from steam_backlog_enforcer.game_install import _echo
|
from steam_backlog_enforcer.game_install import _echo
|
||||||
from steam_backlog_enforcer.hltb import fetch_hltb_confidence_cached
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|||||||
@ -11,13 +11,13 @@ import secrets
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from urllib.parse import quote_plus
|
from urllib.parse import quote_plus
|
||||||
|
|
||||||
|
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_detail_missing
|
||||||
from steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
HLTB_BASE_URL,
|
HLTB_BASE_URL,
|
||||||
load_hltb_game_id_cache,
|
load_hltb_game_id_cache,
|
||||||
)
|
)
|
||||||
from steam_backlog_enforcer._stats_types import _HLTB_SEARCH_BASE, _GameTimes
|
from steam_backlog_enforcer._stats_types import _HLTB_SEARCH_BASE, _GameTimes
|
||||||
from steam_backlog_enforcer.game_install import _echo
|
from steam_backlog_enforcer.game_install import _echo
|
||||||
from steam_backlog_enforcer.hltb import fetch_hltb_detail_missing
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from steam_backlog_enforcer.config import State
|
from steam_backlog_enforcer.config import State
|
||||||
|
|||||||
@ -10,6 +10,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
|
|||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_detail_missing
|
||||||
from steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
load_hltb_cache,
|
load_hltb_cache,
|
||||||
load_hltb_game_id_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._stats_types import _GameTimes
|
||||||
from steam_backlog_enforcer.config import SNAPSHOT_FILE
|
from steam_backlog_enforcer.config import SNAPSHOT_FILE
|
||||||
from steam_backlog_enforcer.game_install import _echo
|
from steam_backlog_enforcer.game_install import _echo
|
||||||
from steam_backlog_enforcer.hltb import fetch_hltb_detail_missing
|
|
||||||
from steam_backlog_enforcer.protondb import (
|
from steam_backlog_enforcer.protondb import (
|
||||||
ProtonDBRating,
|
ProtonDBRating,
|
||||||
fetch_protondb_ratings,
|
fetch_protondb_ratings,
|
||||||
|
|||||||
@ -3,11 +3,10 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
import importlib
|
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from steam_backlog_enforcer.config import CONFIG_DIR
|
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.
|
# long); FS_IMMUTABLE_FL is the "immutable" bit that `chattr +i` sets.
|
||||||
_FS_IOC_GETFLAGS = 0x80086601
|
_FS_IOC_GETFLAGS = 0x80086601
|
||||||
_FS_IMMUTABLE_FL = 0x00000010
|
_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)
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ from typing import TYPE_CHECKING
|
|||||||
from steam_backlog_enforcer._game_names import _is_protected_name
|
from steam_backlog_enforcer._game_names import _is_protected_name
|
||||||
from steam_backlog_enforcer._protected_apps import PROTECTED_APP_IDS
|
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._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:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|||||||
@ -13,9 +13,7 @@ Fetches leisure completionist hour estimates from howlongtobeat.com with:
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import importlib
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
@ -167,41 +165,3 @@ def fetch_hltb_confidence(
|
|||||||
count_comp=count_comp,
|
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)
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ from typing import TYPE_CHECKING
|
|||||||
from steam_backlog_enforcer._allowed_games import (
|
from steam_backlog_enforcer._allowed_games import (
|
||||||
MANUAL_LOCK_DAYS as _MANUAL_LOCK_DAYS,
|
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 (
|
from steam_backlog_enforcer._cmd_playtime import (
|
||||||
cmd_enforce,
|
cmd_enforce,
|
||||||
cmd_gaming_reset,
|
cmd_gaming_reset,
|
||||||
|
|||||||
@ -11,16 +11,14 @@ from datetime import UTC, datetime, timedelta
|
|||||||
import sys
|
import sys
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from steam_backlog_enforcer._actions import (
|
from steam_backlog_enforcer._actions import active_manual_picks
|
||||||
active_manual_picks,
|
|
||||||
manual_pick_age_days,
|
|
||||||
)
|
|
||||||
from steam_backlog_enforcer._actions import (
|
from steam_backlog_enforcer._actions import (
|
||||||
is_manual_pick_locked as _is_manual_pick_locked,
|
is_manual_pick_locked as _is_manual_pick_locked,
|
||||||
)
|
)
|
||||||
from steam_backlog_enforcer._allowed_games import (
|
from steam_backlog_enforcer._allowed_games import (
|
||||||
MANUAL_LOCK_DAYS as _MANUAL_LOCK_DAYS,
|
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 (
|
from steam_backlog_enforcer._total_block import (
|
||||||
TotalBlockStatus,
|
TotalBlockStatus,
|
||||||
get_total_block_status,
|
get_total_block_status,
|
||||||
|
|||||||
@ -9,10 +9,10 @@ from steam_backlog_enforcer._actions import (
|
|||||||
ABANDON_COOLDOWN_DAYS as _ABANDON_COOLDOWN_DAYS,
|
ABANDON_COOLDOWN_DAYS as _ABANDON_COOLDOWN_DAYS,
|
||||||
)
|
)
|
||||||
from steam_backlog_enforcer._actions import (
|
from steam_backlog_enforcer._actions import (
|
||||||
abandon_manual_pick,
|
|
||||||
active_manual_picks,
|
active_manual_picks,
|
||||||
find_manual_pick,
|
find_manual_pick,
|
||||||
)
|
)
|
||||||
|
from steam_backlog_enforcer._manual_pick_lifecycle import abandon_manual_pick
|
||||||
from steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer.game_install import (
|
||||||
_echo,
|
_echo,
|
||||||
is_game_installed,
|
is_game_installed,
|
||||||
|
|||||||
@ -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._total_block import start_total_block
|
||||||
from steam_backlog_enforcer._web_build import build_frontend, frontend_is_stale
|
from steam_backlog_enforcer._web_build import build_frontend, frontend_is_stale
|
||||||
from steam_backlog_enforcer._web_server import serve
|
from steam_backlog_enforcer._web_server import serve
|
||||||
from steam_backlog_enforcer._whitelist import (
|
from steam_backlog_enforcer._whitelist import validate_reason
|
||||||
add_pending_exception,
|
from steam_backlog_enforcer._whitelist_locking import add_pending_exception
|
||||||
validate_reason,
|
|
||||||
)
|
|
||||||
from steam_backlog_enforcer.game_install import _echo
|
from steam_backlog_enforcer.game_install import _echo
|
||||||
from steam_backlog_enforcer.library_hider import restart_steam, unhide_all_games
|
from steam_backlog_enforcer.library_hider import restart_steam, unhide_all_games
|
||||||
from steam_backlog_enforcer.store_blocker import block_store, unblock_store
|
from steam_backlog_enforcer.store_blocker import block_store, unblock_store
|
||||||
|
|||||||
@ -4,10 +4,8 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from steam_backlog_enforcer._actions import (
|
from steam_backlog_enforcer._actions import active_manual_picks
|
||||||
active_manual_picks,
|
from steam_backlog_enforcer._manual_pick_lifecycle import manual_pick_age_days
|
||||||
manual_pick_age_days,
|
|
||||||
)
|
|
||||||
from steam_backlog_enforcer._pick_completion import report_completion
|
from steam_backlog_enforcer._pick_completion import report_completion
|
||||||
from steam_backlog_enforcer._snapshot import load_snapshot
|
from steam_backlog_enforcer._snapshot import load_snapshot
|
||||||
from steam_backlog_enforcer._total_block import get_total_block_status
|
from steam_backlog_enforcer._total_block import get_total_block_status
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import logging
|
|||||||
import time
|
import time
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from steam_backlog_enforcer._hltb_cached import fetch_hltb_times_cached
|
||||||
from steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
load_hltb_count_comp_cache,
|
load_hltb_count_comp_cache,
|
||||||
load_hltb_polls_cache,
|
load_hltb_polls_cache,
|
||||||
@ -39,9 +40,6 @@ from steam_backlog_enforcer.enforcer import (
|
|||||||
from steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer.game_install import (
|
||||||
_echo,
|
_echo,
|
||||||
)
|
)
|
||||||
from steam_backlog_enforcer.hltb import (
|
|
||||||
fetch_hltb_times_cached,
|
|
||||||
)
|
|
||||||
from steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient
|
from steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|||||||
@ -10,8 +10,8 @@ from steam_backlog_enforcer import _allowed_games
|
|||||||
from steam_backlog_enforcer._actions import (
|
from steam_backlog_enforcer._actions import (
|
||||||
apply_manual_pick,
|
apply_manual_pick,
|
||||||
is_manual_pick_locked,
|
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
|
from steam_backlog_enforcer.config import State
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,6 @@ from datetime import UTC, datetime, timedelta
|
|||||||
|
|
||||||
from steam_backlog_enforcer import _actions, _allowed_games
|
from steam_backlog_enforcer import _actions, _allowed_games
|
||||||
from steam_backlog_enforcer._actions import (
|
from steam_backlog_enforcer._actions import (
|
||||||
abandon_manual_pick,
|
|
||||||
active_manual_picks,
|
active_manual_picks,
|
||||||
allowed_app_ids,
|
allowed_app_ids,
|
||||||
allowed_games,
|
allowed_games,
|
||||||
@ -15,6 +14,7 @@ from steam_backlog_enforcer._actions import (
|
|||||||
is_manual_pick_locked,
|
is_manual_pick_locked,
|
||||||
manual_pick_slots_left,
|
manual_pick_slots_left,
|
||||||
)
|
)
|
||||||
|
from steam_backlog_enforcer._manual_pick_lifecycle import abandon_manual_pick
|
||||||
from steam_backlog_enforcer.config import State
|
from steam_backlog_enforcer.config import State
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,9 +5,7 @@ from __future__ import annotations
|
|||||||
from datetime import UTC, datetime, timedelta
|
from datetime import UTC, datetime, timedelta
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from steam_backlog_enforcer._actions import (
|
from steam_backlog_enforcer._manual_pick_lifecycle import status_payload
|
||||||
status_payload,
|
|
||||||
)
|
|
||||||
from steam_backlog_enforcer._total_block import TotalBlockStatus
|
from steam_backlog_enforcer._total_block import TotalBlockStatus
|
||||||
from steam_backlog_enforcer.config import State
|
from steam_backlog_enforcer.config import State
|
||||||
|
|
||||||
|
|||||||
@ -12,11 +12,11 @@ import aiohttp
|
|||||||
from steam_backlog_enforcer._hltb_matching import _similarity
|
from steam_backlog_enforcer._hltb_matching import _similarity
|
||||||
from steam_backlog_enforcer._hltb_search import _AuthInfo
|
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_search_api import _get_hltb_search_url
|
||||||
from steam_backlog_enforcer.hltb import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
_get_auth_info,
|
|
||||||
load_hltb_cache,
|
load_hltb_cache,
|
||||||
save_hltb_cache,
|
save_hltb_cache,
|
||||||
)
|
)
|
||||||
|
from steam_backlog_enforcer.hltb import _get_auth_info
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|||||||
@ -6,11 +6,11 @@ import asyncio
|
|||||||
from typing import Self
|
from typing import Self
|
||||||
from unittest.mock import patch
|
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_search import _AuthInfo
|
||||||
from steam_backlog_enforcer.hltb import (
|
from steam_backlog_enforcer.hltb import (
|
||||||
_fetch_batch_confidence_only,
|
_fetch_batch_confidence_only,
|
||||||
fetch_hltb_confidence,
|
fetch_hltb_confidence,
|
||||||
fetch_hltb_confidence_cached,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
PKG = "steam_backlog_enforcer.hltb"
|
PKG = "steam_backlog_enforcer.hltb"
|
||||||
|
|||||||
@ -5,9 +5,7 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING, Self
|
from typing import TYPE_CHECKING, Self
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from steam_backlog_enforcer.hltb import (
|
from steam_backlog_enforcer._hltb_confidence import fetch_hltb_detail_missing
|
||||||
fetch_hltb_detail_missing,
|
|
||||||
)
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from steam_backlog_enforcer._hltb_types import _HLTBExtras
|
from steam_backlog_enforcer._hltb_types import _HLTBExtras
|
||||||
|
|||||||
@ -5,11 +5,11 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING, Self
|
from typing import TYPE_CHECKING, Self
|
||||||
from unittest.mock import MagicMock, patch
|
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,
|
HLTB_BASE_URL,
|
||||||
HLTBResult,
|
HLTBResult,
|
||||||
fetch_hltb_times_cached,
|
|
||||||
get_hltb_submit_url,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|||||||
@ -4,10 +4,8 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from steam_backlog_enforcer.hltb import (
|
from steam_backlog_enforcer._hltb_types import HLTBResult
|
||||||
HLTBResult,
|
from steam_backlog_enforcer.hltb import fetch_hltb_times
|
||||||
fetch_hltb_times,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TestFetchHltbTimes:
|
class TestFetchHltbTimes:
|
||||||
|
|||||||
@ -5,9 +5,7 @@ from unittest.mock import (
|
|||||||
patch,
|
patch,
|
||||||
)
|
)
|
||||||
|
|
||||||
from steam_backlog_enforcer._cmd_done import (
|
from steam_backlog_enforcer._cmd_done_finalize import _finalize_completion
|
||||||
_finalize_completion,
|
|
||||||
)
|
|
||||||
from steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
|
|
||||||
CMD_DONE_PKG = "steam_backlog_enforcer._cmd_done_finalize"
|
CMD_DONE_PKG = "steam_backlog_enforcer._cmd_done_finalize"
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from steam_backlog_enforcer._cmd_done import (
|
from steam_backlog_enforcer._cmd_done_finalize import (
|
||||||
_enforce_on_done,
|
_enforce_on_done,
|
||||||
cmd_done,
|
cmd_done,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -5,9 +5,7 @@ from unittest.mock import (
|
|||||||
patch,
|
patch,
|
||||||
)
|
)
|
||||||
|
|
||||||
from steam_backlog_enforcer._cmd_done import (
|
from steam_backlog_enforcer._cmd_done_finalize import _finalize_completion
|
||||||
_finalize_completion,
|
|
||||||
)
|
|
||||||
from steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|||||||
@ -7,9 +7,9 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
from steam_backlog_enforcer._whitelist import (
|
from steam_backlog_enforcer._whitelist import (
|
||||||
_shannon_entropy,
|
_shannon_entropy,
|
||||||
_try_set_immutable,
|
|
||||||
validate_reason,
|
validate_reason,
|
||||||
)
|
)
|
||||||
|
from steam_backlog_enforcer._whitelist_locking import _try_set_immutable
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|||||||
@ -6,12 +6,12 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
import pytest
|
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,
|
_load_approved,
|
||||||
_save_approved,
|
_save_approved,
|
||||||
add_pending_exception,
|
add_pending_exception,
|
||||||
get_approved_exception_ids,
|
get_approved_exception_ids,
|
||||||
validate_reason,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from steam_backlog_enforcer._whitelist import (
|
from steam_backlog_enforcer._whitelist_locking import (
|
||||||
_immutable_flag_is,
|
_immutable_flag_is,
|
||||||
_load_approved,
|
_load_approved,
|
||||||
_save_approved,
|
_save_approved,
|
||||||
|
|||||||
@ -5,9 +5,7 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from steam_backlog_enforcer._whitelist import (
|
from steam_backlog_enforcer._whitelist_locking import _append_audit_log
|
||||||
_append_audit_log,
|
|
||||||
)
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user