mirror of
https://github.com/kuhyx/steam-backlog-enforcer.git
synced 2026-07-04 15:43:09 +02:00
chore: set up as standalone repo
Extracted from testsAndMisc monorepo. Changes: - Rewrote imports from python_pkg.steam_backlog_enforcer.* → steam_backlog_enforcer.* - Moved run.sh, install.sh, README.md, service file to repo root - Added standalone pyproject.toml, requirements.txt, .pre-commit-config.yaml, .gitignore - Added GitHub Actions CI workflows (tests + pre-commit) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
48b609e1a3
commit
551b8a4f95
19
.github/workflows/pre-commit.yml
vendored
Normal file
19
.github/workflows/pre-commit.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: pre-commit
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pre-commit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pip install -r requirements.txt
|
||||||
|
- uses: pre-commit/action@v3.0.1
|
||||||
33
.github/workflows/python-tests.yml
vendored
Normal file
33
.github/workflows/python-tests.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ["3.10", "3.11", "3.12"]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pip install -r requirements.txt
|
||||||
|
|
||||||
|
- name: Run tests with coverage
|
||||||
|
run: |
|
||||||
|
python -m pytest steam_backlog_enforcer/tests/ \
|
||||||
|
--cov=steam_backlog_enforcer \
|
||||||
|
--cov-branch \
|
||||||
|
--cov-fail-under=100 \
|
||||||
|
-v
|
||||||
22
.gitignore
vendored
Normal file
22
.gitignore
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
*.egg-info/
|
||||||
|
.eggs/
|
||||||
|
.env
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
.pytest_cache/
|
||||||
|
.mypy_cache/
|
||||||
|
.ruff_cache/
|
||||||
|
coverage.xml
|
||||||
|
*.lcov
|
||||||
|
.coverage
|
||||||
|
htmlcov/
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
164
.pre-commit-config.yaml
Normal file
164
.pre-commit-config.yaml
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
# Pre-commit Configuration for steam-backlog-enforcer
|
||||||
|
# Install: pre-commit install && pre-commit install --hook-type pre-push
|
||||||
|
# Run: pre-commit run --all-files
|
||||||
|
# Update: pre-commit autoupdate
|
||||||
|
|
||||||
|
default_language_version:
|
||||||
|
python: python3
|
||||||
|
default_stages: [pre-commit]
|
||||||
|
fail_fast: false
|
||||||
|
|
||||||
|
repos:
|
||||||
|
# ===========================================================================
|
||||||
|
# GENERAL HOOKS
|
||||||
|
# ===========================================================================
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.6.0
|
||||||
|
hooks:
|
||||||
|
- id: trailing-whitespace
|
||||||
|
args: [--markdown-linebreak-ext=md]
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: check-yaml
|
||||||
|
- id: check-json
|
||||||
|
- id: check-toml
|
||||||
|
- id: check-added-large-files
|
||||||
|
args: [--maxkb=2000]
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-case-conflict
|
||||||
|
- id: detect-private-key
|
||||||
|
- id: debug-statements
|
||||||
|
- id: name-tests-test
|
||||||
|
args: [--pytest-test-first]
|
||||||
|
- id: check-ast
|
||||||
|
- id: check-builtin-literals
|
||||||
|
- id: check-docstring-first
|
||||||
|
- id: mixed-line-ending
|
||||||
|
args: [--fix=lf]
|
||||||
|
- id: requirements-txt-fixer
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# NOQA BLOCKER
|
||||||
|
# ===========================================================================
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: no-noqa
|
||||||
|
name: Block noqa comments
|
||||||
|
entry: '(?i)#\s*(noqa|type:\s*ignore)'
|
||||||
|
language: pygrep
|
||||||
|
types: [python]
|
||||||
|
- id: no-ruff-noqa
|
||||||
|
name: Block ruff noqa file-level comments
|
||||||
|
entry: '(?i)#\s*ruff:\s*noqa'
|
||||||
|
language: pygrep
|
||||||
|
types: [python]
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# RUFF - Linter + formatter
|
||||||
|
# ===========================================================================
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.15.2
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
args: [--fix, --unsafe-fixes, --exit-non-zero-on-fix, --show-fixes]
|
||||||
|
types_or: [python, pyi]
|
||||||
|
- id: ruff-format
|
||||||
|
types_or: [python, pyi]
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# MYPY - Type checking
|
||||||
|
# ===========================================================================
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
|
rev: v1.13.0
|
||||||
|
hooks:
|
||||||
|
- id: mypy
|
||||||
|
args:
|
||||||
|
- --ignore-missing-imports
|
||||||
|
- --no-error-summary
|
||||||
|
- --disable-error-code=no-untyped-def
|
||||||
|
- --disable-error-code=no-untyped-call
|
||||||
|
- --disable-error-code=var-annotated
|
||||||
|
- --disable-error-code=no-any-unimported
|
||||||
|
- --disable-error-code=type-arg
|
||||||
|
- --disable-error-code=no-any-return
|
||||||
|
- --disable-error-code=misc
|
||||||
|
- --disable-error-code=unused-ignore
|
||||||
|
- --disable-error-code=unreachable
|
||||||
|
- --disable-error-code=assignment
|
||||||
|
- --disable-error-code=no-redef
|
||||||
|
- --disable-error-code=attr-defined
|
||||||
|
- --disable-error-code=arg-type
|
||||||
|
- --disable-error-code=union-attr
|
||||||
|
- --disable-error-code=call-overload
|
||||||
|
- --disable-error-code=return-value
|
||||||
|
- --disable-error-code=redundant-cast
|
||||||
|
- --disable-error-code=empty-body
|
||||||
|
- --disable-error-code=list-item
|
||||||
|
additional_dependencies:
|
||||||
|
- types-requests
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# PYLINT
|
||||||
|
# ===========================================================================
|
||||||
|
- repo: https://github.com/pylint-dev/pylint
|
||||||
|
rev: v3.3.2
|
||||||
|
hooks:
|
||||||
|
- id: pylint
|
||||||
|
args:
|
||||||
|
- --rcfile=pyproject.toml
|
||||||
|
- --fail-under=8.0
|
||||||
|
- --jobs=4
|
||||||
|
additional_dependencies:
|
||||||
|
- pytest
|
||||||
|
- requests
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# BANDIT - Security linter
|
||||||
|
# ===========================================================================
|
||||||
|
- repo: https://github.com/PyCQA/bandit
|
||||||
|
rev: 1.7.10
|
||||||
|
hooks:
|
||||||
|
- id: bandit
|
||||||
|
args:
|
||||||
|
- -c
|
||||||
|
- pyproject.toml
|
||||||
|
- --severity-level=high
|
||||||
|
- --confidence-level=medium
|
||||||
|
- --skip=B113
|
||||||
|
additional_dependencies: ["bandit[toml]"]
|
||||||
|
exclude: ^(tests/|.*test.*\.py$)
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# PYTEST + COVERAGE (push stage)
|
||||||
|
# ===========================================================================
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: pytest-coverage
|
||||||
|
name: pytest with coverage enforcement
|
||||||
|
entry: python -m pytest steam_backlog_enforcer/tests/ --cov=steam_backlog_enforcer --cov-branch --cov-fail-under=100
|
||||||
|
language: system
|
||||||
|
types: [python]
|
||||||
|
pass_filenames: false
|
||||||
|
require_serial: true
|
||||||
|
stages: [pre-push]
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# CODESPELL - Spell checking
|
||||||
|
# ===========================================================================
|
||||||
|
- repo: https://github.com/codespell-project/codespell
|
||||||
|
rev: v2.3.0
|
||||||
|
hooks:
|
||||||
|
- id: codespell
|
||||||
|
args:
|
||||||
|
- --skip=*.json,*.lock,.git,__pycache__,.venv
|
||||||
|
- --ignore-words-list=als,ans,ect,nd,som,sur,te,nam,numer,lew,sie,wil,postion,clen,ther,folow,derrive,ony,tje,noe,theses,crate,doubleclick,wile,tabel,pary,blok,bloc,proces,serwer,parametr,adres,hart,dout,metod,tekst,synonim,grup,mosty,lokal,skalar,milion,nowe,tre,hel,alph
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# SHELLCHECK - Shell script linting
|
||||||
|
# ===========================================================================
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: shellcheck
|
||||||
|
name: shellcheck
|
||||||
|
entry: bash -c 'printf "%s\0" "$@" | xargs -0 -n 40 shellcheck --severity=warning' --
|
||||||
|
language: system
|
||||||
|
types: [shell]
|
||||||
@ -3,7 +3,6 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
||||||
|
|
||||||
echo "=== Steam Backlog Enforcer Installer ==="
|
echo "=== Steam Backlog Enforcer Installer ==="
|
||||||
echo
|
echo
|
||||||
@ -24,9 +23,9 @@ if [[ "${ans,,}" == "y" ]]; then
|
|||||||
SERVICE_SRC="$SCRIPT_DIR/steam-backlog-enforcer.service"
|
SERVICE_SRC="$SCRIPT_DIR/steam-backlog-enforcer.service"
|
||||||
SERVICE_DST="/etc/systemd/system/steam-backlog-enforcer.service"
|
SERVICE_DST="/etc/systemd/system/steam-backlog-enforcer.service"
|
||||||
|
|
||||||
# Set the correct working directory in the service file.
|
# Set the correct working directory and PYTHONPATH in the service file.
|
||||||
sed "s|WorkingDirectory=.*|WorkingDirectory=$REPO_ROOT|" "$SERVICE_SRC" \
|
sed "s|WorkingDirectory=.*|WorkingDirectory=$SCRIPT_DIR|; s|PYTHONPATH=.*|PYTHONPATH=$SCRIPT_DIR|" \
|
||||||
> "$SERVICE_DST"
|
"$SERVICE_SRC" > "$SERVICE_DST"
|
||||||
|
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable steam-backlog-enforcer
|
systemctl enable steam-backlog-enforcer
|
||||||
@ -38,4 +37,4 @@ fi
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Done! Run manually with:"
|
echo "Done! Run manually with:"
|
||||||
echo " sudo python3 -m python_pkg.steam_backlog_enforcer.main enforce"
|
echo " python3 -m steam_backlog_enforcer.main enforce"
|
||||||
166
pyproject.toml
Normal file
166
pyproject.toml
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
[project]
|
||||||
|
name = "steam-backlog-enforcer"
|
||||||
|
version = "1.0.0"
|
||||||
|
description = "Enforce your Steam backlog: one game at a time, tracked with HowLongToBeat data"
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
dependencies = [
|
||||||
|
"requests>=2.0",
|
||||||
|
"howlongtobeatpy>=1.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# RUFF - Fast Python linter and formatter
|
||||||
|
# ============================================================================
|
||||||
|
[tool.ruff]
|
||||||
|
target-version = "py310"
|
||||||
|
include = ["*.py", "**/*.py"]
|
||||||
|
exclude = [".git", ".venv", "__pycache__", "build", "dist", ".eggs"]
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["ALL"]
|
||||||
|
ignore = [
|
||||||
|
"D203", # conflicts with D211
|
||||||
|
"D213", # conflicts with D212
|
||||||
|
"COM812", # formatter handles this
|
||||||
|
"ISC001", # formatter may create these
|
||||||
|
"S603", # prone to false positives
|
||||||
|
]
|
||||||
|
fixable = ["ALL"]
|
||||||
|
unfixable = []
|
||||||
|
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
"**/tests/**/*.py" = ["ARG", "D", "PLC0415", "PLR2004", "S101", "SLF001"]
|
||||||
|
"**/test_*.py" = ["ARG", "D", "PLC0415", "PLR2004", "S101", "SLF001"]
|
||||||
|
|
||||||
|
[tool.ruff.lint.pydocstyle]
|
||||||
|
convention = "google"
|
||||||
|
|
||||||
|
[tool.ruff.lint.isort]
|
||||||
|
force-single-line = false
|
||||||
|
force-sort-within-sections = true
|
||||||
|
known-first-party = ["steam_backlog_enforcer"]
|
||||||
|
|
||||||
|
[tool.ruff.lint.flake8-quotes]
|
||||||
|
docstring-quotes = "double"
|
||||||
|
inline-quotes = "double"
|
||||||
|
|
||||||
|
[tool.ruff.lint.flake8-tidy-imports]
|
||||||
|
ban-relative-imports = "all"
|
||||||
|
|
||||||
|
[tool.ruff.format]
|
||||||
|
quote-style = "double"
|
||||||
|
indent-style = "space"
|
||||||
|
skip-magic-trailing-comma = false
|
||||||
|
line-ending = "auto"
|
||||||
|
docstring-code-format = true
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# MYPY - Static type checker
|
||||||
|
# ============================================================================
|
||||||
|
[tool.mypy]
|
||||||
|
python_version = "3.10"
|
||||||
|
strict = true
|
||||||
|
warn_return_any = true
|
||||||
|
warn_unused_configs = true
|
||||||
|
disallow_untyped_defs = true
|
||||||
|
disallow_incomplete_defs = true
|
||||||
|
check_untyped_defs = true
|
||||||
|
disallow_untyped_decorators = true
|
||||||
|
no_implicit_optional = true
|
||||||
|
warn_redundant_casts = true
|
||||||
|
warn_unused_ignores = true
|
||||||
|
warn_no_return = true
|
||||||
|
warn_unreachable = true
|
||||||
|
disallow_any_unimported = true
|
||||||
|
disallow_any_explicit = false
|
||||||
|
disallow_any_generics = true
|
||||||
|
disallow_subclassing_any = true
|
||||||
|
strict_equality = true
|
||||||
|
extra_checks = true
|
||||||
|
ignore_missing_imports = true
|
||||||
|
show_error_codes = true
|
||||||
|
color_output = true
|
||||||
|
exclude = [".venv/"]
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# PYLINT
|
||||||
|
# ============================================================================
|
||||||
|
[tool.pylint.main]
|
||||||
|
analyse-fallback-blocks = true
|
||||||
|
persistent = true
|
||||||
|
jobs = 0
|
||||||
|
py-version = "3.10"
|
||||||
|
ignore = [".venv", "__pycache__"]
|
||||||
|
ignore-patterns = [".*\\.pyi$"]
|
||||||
|
|
||||||
|
[tool.pylint.messages_control]
|
||||||
|
enable = "all"
|
||||||
|
disable = []
|
||||||
|
|
||||||
|
[tool.pylint.design]
|
||||||
|
min-public-methods = 0
|
||||||
|
max-module-lines = 1000
|
||||||
|
max-attributes = 10
|
||||||
|
|
||||||
|
[tool.pylint.typecheck]
|
||||||
|
generated-members = [
|
||||||
|
".*\\.assert_called_once_with",
|
||||||
|
".*\\.assert_called_once",
|
||||||
|
".*\\.assert_called",
|
||||||
|
".*\\.assert_not_called",
|
||||||
|
".*\\.assert_any_call",
|
||||||
|
".*\\.call_args",
|
||||||
|
".*\\.call_args_list",
|
||||||
|
".*\\.call_count",
|
||||||
|
]
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# BANDIT - Security linter
|
||||||
|
# ============================================================================
|
||||||
|
[tool.bandit]
|
||||||
|
exclude_dirs = ["tests", ".venv"]
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# PYTEST
|
||||||
|
# ============================================================================
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
testpaths = ["steam_backlog_enforcer/tests"]
|
||||||
|
python_files = ["test_*.py", "*_test.py"]
|
||||||
|
python_classes = ["Test*"]
|
||||||
|
python_functions = ["test_*"]
|
||||||
|
addopts = [
|
||||||
|
"-v",
|
||||||
|
"--strict-markers",
|
||||||
|
"--strict-config",
|
||||||
|
"-ra",
|
||||||
|
"--cov=steam_backlog_enforcer",
|
||||||
|
"--cov-branch",
|
||||||
|
"--cov-report=term-missing",
|
||||||
|
"--cov-report=lcov",
|
||||||
|
]
|
||||||
|
filterwarnings = [
|
||||||
|
"error",
|
||||||
|
"ignore::DeprecationWarning",
|
||||||
|
"default::pytest.PytestUnraisableExceptionWarning",
|
||||||
|
]
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# COVERAGE
|
||||||
|
# ============================================================================
|
||||||
|
[tool.coverage.run]
|
||||||
|
source = ["steam_backlog_enforcer"]
|
||||||
|
branch = true
|
||||||
|
omit = ["*/__pycache__/*", "*/tests/*", "*/.venv/*"]
|
||||||
|
|
||||||
|
[tool.coverage.report]
|
||||||
|
fail_under = 100
|
||||||
|
show_missing = true
|
||||||
|
skip_covered = false
|
||||||
|
exclude_lines = [
|
||||||
|
"pragma: no cover",
|
||||||
|
"raise NotImplementedError",
|
||||||
|
"raise AssertionError",
|
||||||
|
"if TYPE_CHECKING:",
|
||||||
|
'if __name__ == "__main__":',
|
||||||
|
]
|
||||||
|
partial_branches = ["pragma: no branch"]
|
||||||
19
requirements.txt
Normal file
19
requirements.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Steam Backlog Enforcer — runtime + development dependencies
|
||||||
|
# Install with: pip install -r requirements.txt
|
||||||
|
|
||||||
|
bandit>=1.7.0
|
||||||
|
codespell>=2.2.0
|
||||||
|
coverage>=7.4.0
|
||||||
|
howlongtobeatpy>=1.0
|
||||||
|
mypy>=1.8.0
|
||||||
|
pre-commit>=3.6.0
|
||||||
|
pylint>=3.0.0
|
||||||
|
pytest>=8.0.0
|
||||||
|
pytest-cov>=4.1.0
|
||||||
|
pytest-randomly>=3.15.0
|
||||||
|
pytest-sugar>=1.0.0
|
||||||
|
pytest-timeout>=2.2.0
|
||||||
|
pytest-xdist>=3.5.0
|
||||||
|
requests>=2.0
|
||||||
|
ruff>=0.8.0
|
||||||
|
types-requests>=2.31.0
|
||||||
@ -3,5 +3,5 @@
|
|||||||
# Usage: ./run.sh [command] (defaults to "done" if no command given)
|
# Usage: ./run.sh [command] (defaults to "done" if no command given)
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
cd "$(dirname "$0")/../.."
|
cd "$(dirname "$0")"
|
||||||
exec python -m python_pkg.steam_backlog_enforcer.main "${1:-done}"
|
exec python -m steam_backlog_enforcer.main "${1:-done}"
|
||||||
@ -5,12 +5,12 @@ Wants=network-online.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
WorkingDirectory=/home/kuhy/testsAndMisc
|
WorkingDirectory=/opt/steam-backlog-enforcer
|
||||||
ExecStart=/usr/bin/python3 -m python_pkg.steam_backlog_enforcer.main enforce
|
ExecStart=/usr/bin/python3 -m steam_backlog_enforcer.main enforce
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
Environment=PYTHONUNBUFFERED=1
|
Environment=PYTHONUNBUFFERED=1
|
||||||
Environment=PYTHONPATH=/home/kuhy/testsAndMisc:/home/kuhy/.local/lib/python3.14/site-packages
|
Environment=PYTHONPATH=/opt/steam-backlog-enforcer
|
||||||
Environment=HOME=/home/kuhy
|
Environment=HOME=/home/kuhy
|
||||||
# Hardening: enforcer must not be easily killed.
|
# Hardening: enforcer must not be easily killed.
|
||||||
OOMScoreAdjust=-900
|
OOMScoreAdjust=-900
|
||||||
@ -5,28 +5,28 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._enforce_loop import get_all_owned_app_ids
|
from steam_backlog_enforcer._enforce_loop import get_all_owned_app_ids
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State, load_snapshot
|
from steam_backlog_enforcer.config import Config, State, load_snapshot
|
||||||
from python_pkg.steam_backlog_enforcer.enforcer import (
|
from steam_backlog_enforcer.enforcer import (
|
||||||
enforce_allowed_game,
|
enforce_allowed_game,
|
||||||
send_notification,
|
send_notification,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer.game_install import (
|
||||||
_echo,
|
_echo,
|
||||||
install_game,
|
install_game,
|
||||||
is_game_installed,
|
is_game_installed,
|
||||||
uninstall_other_games,
|
uninstall_other_games,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.hltb import (
|
from steam_backlog_enforcer.hltb import (
|
||||||
fetch_hltb_confidence_cached,
|
fetch_hltb_confidence_cached,
|
||||||
fetch_hltb_times_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 python_pkg.steam_backlog_enforcer.library_hider import hide_other_games
|
from steam_backlog_enforcer.library_hider import hide_other_games
|
||||||
from python_pkg.steam_backlog_enforcer.scanning import pick_next_game
|
from steam_backlog_enforcer.scanning import pick_next_game
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient
|
from steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient
|
||||||
|
|
||||||
_REASSIGN_REFRESH_LIMIT = 50
|
_REASSIGN_REFRESH_LIMIT = 50
|
||||||
_SKIP_DAYS = 7
|
_SKIP_DAYS = 7
|
||||||
|
|||||||
@ -7,11 +7,11 @@ import logging
|
|||||||
import time
|
import time
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._whitelist import (
|
from steam_backlog_enforcer._whitelist import (
|
||||||
lock_enforcement_files,
|
lock_enforcement_files,
|
||||||
promote_pending_exceptions,
|
promote_pending_exceptions,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import (
|
from steam_backlog_enforcer.config import (
|
||||||
CONFIG_DIR,
|
CONFIG_DIR,
|
||||||
CONFIG_FILE,
|
CONFIG_FILE,
|
||||||
Config,
|
Config,
|
||||||
@ -19,11 +19,11 @@ from python_pkg.steam_backlog_enforcer.config import (
|
|||||||
_atomic_write,
|
_atomic_write,
|
||||||
load_snapshot,
|
load_snapshot,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.enforcer import (
|
from steam_backlog_enforcer.enforcer import (
|
||||||
enforce_allowed_game,
|
enforce_allowed_game,
|
||||||
send_notification,
|
send_notification,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer.game_install import (
|
||||||
_echo,
|
_echo,
|
||||||
get_installed_games,
|
get_installed_games,
|
||||||
install_game,
|
install_game,
|
||||||
@ -32,9 +32,9 @@ from python_pkg.steam_backlog_enforcer.game_install import (
|
|||||||
uninstall_game,
|
uninstall_game,
|
||||||
uninstall_other_games,
|
uninstall_other_games,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.library_hider import hide_other_games
|
from steam_backlog_enforcer.library_hider import hide_other_games
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import SteamAPIClient
|
from steam_backlog_enforcer.steam_api import SteamAPIClient
|
||||||
from python_pkg.steam_backlog_enforcer.store_blocker import block_store
|
from steam_backlog_enforcer.store_blocker import block_store
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
_OWNED_IDS_CACHE_FILE = CONFIG_DIR / "owned_app_ids_cache.json"
|
_OWNED_IDS_CACHE_FILE = CONFIG_DIR / "owned_app_ids_cache.json"
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from typing import Any
|
|||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
_SAVE_INTERVAL,
|
_SAVE_INTERVAL,
|
||||||
HLTB_BASE_URL,
|
HLTB_BASE_URL,
|
||||||
MAX_CONCURRENT,
|
MAX_CONCURRENT,
|
||||||
|
|||||||
@ -15,10 +15,10 @@ from typing import Any
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
from howlongtobeatpy.HTMLRequests import HTMLRequests
|
from howlongtobeatpy.HTMLRequests import HTMLRequests
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_detail import (
|
from steam_backlog_enforcer._hltb_detail import (
|
||||||
_fetch_leisure_times,
|
_fetch_leisure_times,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
_SAVE_INTERVAL,
|
_SAVE_INTERVAL,
|
||||||
_SUBSET_SUFFIXES,
|
_SUBSET_SUFFIXES,
|
||||||
MAX_CONCURRENT,
|
MAX_CONCURRENT,
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.config import CONFIG_DIR, _atomic_write
|
from steam_backlog_enforcer.config import CONFIG_DIR, _atomic_write
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@ -5,19 +5,19 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
_HLTBExtras,
|
_HLTBExtras,
|
||||||
load_hltb_cache,
|
load_hltb_cache,
|
||||||
load_hltb_count_comp_cache,
|
load_hltb_count_comp_cache,
|
||||||
load_hltb_polls_cache,
|
load_hltb_polls_cache,
|
||||||
save_hltb_cache,
|
save_hltb_cache,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.game_install import _echo
|
from steam_backlog_enforcer.game_install import _echo
|
||||||
from python_pkg.steam_backlog_enforcer.hltb import fetch_hltb_confidence_cached
|
from steam_backlog_enforcer.hltb import fetch_hltb_confidence_cached
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from python_pkg.steam_backlog_enforcer.config import State
|
from steam_backlog_enforcer.config import State
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@ -9,29 +9,29 @@ 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 python_pkg.steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
HLTB_BASE_URL,
|
HLTB_BASE_URL,
|
||||||
load_hltb_cache,
|
load_hltb_cache,
|
||||||
load_hltb_game_id_cache,
|
load_hltb_game_id_cache,
|
||||||
load_hltb_leisure_100h_cache,
|
load_hltb_leisure_100h_cache,
|
||||||
load_hltb_rush_cache,
|
load_hltb_rush_cache,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer._scanning_confidence import (
|
from steam_backlog_enforcer._scanning_confidence import (
|
||||||
_apply_cached_confidence_to_candidates,
|
_apply_cached_confidence_to_candidates,
|
||||||
_confidence_fail_reasons,
|
_confidence_fail_reasons,
|
||||||
_refresh_candidate_confidence_batch,
|
_refresh_candidate_confidence_batch,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import load_snapshot
|
from steam_backlog_enforcer.config import load_snapshot
|
||||||
from python_pkg.steam_backlog_enforcer.game_install import _echo
|
from steam_backlog_enforcer.game_install import _echo
|
||||||
from python_pkg.steam_backlog_enforcer.hltb import fetch_hltb_detail_missing
|
from steam_backlog_enforcer.hltb import fetch_hltb_detail_missing
|
||||||
from python_pkg.steam_backlog_enforcer.protondb import (
|
from steam_backlog_enforcer.protondb import (
|
||||||
ProtonDBRating,
|
ProtonDBRating,
|
||||||
fetch_protondb_ratings,
|
fetch_protondb_ratings,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import subprocess
|
|||||||
import time
|
import time
|
||||||
from typing import TYPE_CHECKING, cast
|
from typing import TYPE_CHECKING, cast
|
||||||
|
|
||||||
from python_pkg.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:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import shutil
|
|||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer.game_install import (
|
||||||
is_protected_app,
|
is_protected_app,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._whitelist import get_approved_exception_ids
|
from steam_backlog_enforcer._whitelist import get_approved_exception_ids
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@ -18,14 +18,14 @@ import time
|
|||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_search import (
|
from steam_backlog_enforcer._hltb_search import (
|
||||||
_fetch_batch,
|
_fetch_batch,
|
||||||
_get_auth_info,
|
_get_auth_info,
|
||||||
_get_hltb_search_url,
|
_get_hltb_search_url,
|
||||||
_search_one,
|
_search_one,
|
||||||
_SearchCtx,
|
_SearchCtx,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
HLTB_BASE_URL,
|
HLTB_BASE_URL,
|
||||||
MAX_CONCURRENT,
|
MAX_CONCURRENT,
|
||||||
HLTBResult,
|
HLTBResult,
|
||||||
|
|||||||
@ -7,26 +7,26 @@ import sys
|
|||||||
import time
|
import time
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._cmd_done import cmd_done
|
from steam_backlog_enforcer._cmd_done import cmd_done
|
||||||
from python_pkg.steam_backlog_enforcer._enforce_loop import (
|
from steam_backlog_enforcer._enforce_loop import (
|
||||||
do_enforce,
|
do_enforce,
|
||||||
get_all_owned_app_ids,
|
get_all_owned_app_ids,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_types import load_hltb_cache
|
from steam_backlog_enforcer._hltb_types import load_hltb_cache
|
||||||
from python_pkg.steam_backlog_enforcer._stats import cmd_stats
|
from steam_backlog_enforcer._stats import cmd_stats
|
||||||
from python_pkg.steam_backlog_enforcer._whitelist import (
|
from steam_backlog_enforcer._whitelist import (
|
||||||
WHITELIST_COOLDOWN_SECONDS,
|
WHITELIST_COOLDOWN_SECONDS,
|
||||||
add_pending_exception,
|
add_pending_exception,
|
||||||
list_pending_exceptions,
|
list_pending_exceptions,
|
||||||
validate_reason,
|
validate_reason,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import (
|
from steam_backlog_enforcer.config import (
|
||||||
Config,
|
Config,
|
||||||
State,
|
State,
|
||||||
interactive_setup,
|
interactive_setup,
|
||||||
load_snapshot,
|
load_snapshot,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer.game_install import (
|
||||||
_echo,
|
_echo,
|
||||||
get_installed_games,
|
get_installed_games,
|
||||||
install_game,
|
install_game,
|
||||||
@ -34,18 +34,18 @@ from python_pkg.steam_backlog_enforcer.game_install import (
|
|||||||
is_protected_app,
|
is_protected_app,
|
||||||
uninstall_other_games,
|
uninstall_other_games,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.library_hider import (
|
from steam_backlog_enforcer.library_hider import (
|
||||||
hide_other_games,
|
hide_other_games,
|
||||||
restart_steam,
|
restart_steam,
|
||||||
unhide_all_games,
|
unhide_all_games,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.scanning import (
|
from steam_backlog_enforcer.scanning import (
|
||||||
do_check,
|
do_check,
|
||||||
do_scan,
|
do_scan,
|
||||||
pick_next_game,
|
pick_next_game,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
from python_pkg.steam_backlog_enforcer.store_blocker import (
|
from steam_backlog_enforcer.store_blocker import (
|
||||||
block_store,
|
block_store,
|
||||||
is_store_blocked,
|
is_store_blocked,
|
||||||
unblock_store,
|
unblock_store,
|
||||||
@ -415,7 +415,7 @@ def main() -> None:
|
|||||||
"""CLI entry point."""
|
"""CLI entry point."""
|
||||||
if len(sys.argv) < _MIN_CLI_ARGS or sys.argv[1] not in _ALL_COMMANDS:
|
if len(sys.argv) < _MIN_CLI_ARGS or sys.argv[1] not in _ALL_COMMANDS:
|
||||||
_echo("Steam Backlog Enforcer\n")
|
_echo("Steam Backlog Enforcer\n")
|
||||||
_echo("Usage: python -m python_pkg.steam_backlog_enforcer.main <command>\n")
|
_echo("Usage: python -m steam_backlog_enforcer.main <command>\n")
|
||||||
_echo("Commands:")
|
_echo("Commands:")
|
||||||
for name, desc in _ALL_COMMANDS.items():
|
for name, desc in _ALL_COMMANDS.items():
|
||||||
_echo(f" {name:<14s} {desc}")
|
_echo(f" {name:<14s} {desc}")
|
||||||
|
|||||||
@ -17,7 +17,7 @@ from typing import Any
|
|||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.config import CONFIG_DIR, _atomic_write
|
from steam_backlog_enforcer.config import CONFIG_DIR, _atomic_write
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@ -7,38 +7,38 @@ import logging
|
|||||||
import time
|
import time
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from python_pkg.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,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer._scanning_confidence import (
|
from steam_backlog_enforcer._scanning_confidence import (
|
||||||
_apply_cached_confidence_to_candidates,
|
_apply_cached_confidence_to_candidates,
|
||||||
_candidate_passes_hltb_confidence,
|
_candidate_passes_hltb_confidence,
|
||||||
_report_poll_confidence,
|
_report_poll_confidence,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import (
|
from steam_backlog_enforcer.config import (
|
||||||
Config,
|
Config,
|
||||||
State,
|
State,
|
||||||
load_snapshot,
|
load_snapshot,
|
||||||
save_snapshot,
|
save_snapshot,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.enforcer import (
|
from steam_backlog_enforcer.enforcer import (
|
||||||
send_notification,
|
send_notification,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer.game_install import (
|
||||||
_echo,
|
_echo,
|
||||||
install_game,
|
install_game,
|
||||||
is_game_installed,
|
is_game_installed,
|
||||||
uninstall_other_games,
|
uninstall_other_games,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.hltb import (
|
from steam_backlog_enforcer.hltb import (
|
||||||
fetch_hltb_times_cached,
|
fetch_hltb_times_cached,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.protondb import (
|
from steam_backlog_enforcer.protondb import (
|
||||||
ProtonDBRating,
|
ProtonDBRating,
|
||||||
fetch_protondb_ratings,
|
fetch_protondb_ratings,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient
|
from steam_backlog_enforcer.steam_api import GameInfo, SteamAPIClient
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import shutil
|
|||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.config import (
|
from steam_backlog_enforcer.config import (
|
||||||
BLOCKED_DOMAINS,
|
BLOCKED_DOMAINS,
|
||||||
HOSTS_FILE,
|
HOSTS_FILE,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -39,58 +39,58 @@ def _isolate_filesystem(tmp_path: Path) -> Iterator[None]:
|
|||||||
with (
|
with (
|
||||||
# Config / state / snapshot paths (used by State.save, Config.save, etc.)
|
# Config / state / snapshot paths (used by State.save, Config.save, etc.)
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.config.CONFIG_DIR",
|
"steam_backlog_enforcer.config.CONFIG_DIR",
|
||||||
fake_config,
|
fake_config,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.config.CONFIG_FILE",
|
"steam_backlog_enforcer.config.CONFIG_FILE",
|
||||||
fake_config / "config.json",
|
fake_config / "config.json",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.config.STATE_FILE",
|
"steam_backlog_enforcer.config.STATE_FILE",
|
||||||
fake_config / "state.json",
|
fake_config / "state.json",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.config.SNAPSHOT_FILE",
|
"steam_backlog_enforcer.config.SNAPSHOT_FILE",
|
||||||
fake_config / "snapshot.json",
|
fake_config / "snapshot.json",
|
||||||
),
|
),
|
||||||
# Steam game manifests / install dirs
|
# Steam game manifests / install dirs
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
||||||
fake_steamapps,
|
fake_steamapps,
|
||||||
),
|
),
|
||||||
# HLTB cache file (computed at import time from CONFIG_DIR, so
|
# HLTB cache file (computed at import time from CONFIG_DIR, so
|
||||||
# patching CONFIG_DIR alone does not redirect it)
|
# patching CONFIG_DIR alone does not redirect it)
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE",
|
"steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE",
|
||||||
fake_config / "hltb_cache.json",
|
fake_config / "hltb_cache.json",
|
||||||
),
|
),
|
||||||
# /etc/hosts (store blocker)
|
# /etc/hosts (store blocker)
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
"steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
||||||
fake_hosts,
|
fake_hosts,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.config.HOSTS_FILE",
|
"steam_backlog_enforcer.config.HOSTS_FILE",
|
||||||
fake_hosts,
|
fake_hosts,
|
||||||
),
|
),
|
||||||
# Whitelist exception files (_whitelist module-level constants)
|
# Whitelist exception files (_whitelist module-level constants)
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._whitelist.PENDING_EXCEPTIONS_FILE",
|
"steam_backlog_enforcer._whitelist.PENDING_EXCEPTIONS_FILE",
|
||||||
fake_config / "pending_exceptions.json",
|
fake_config / "pending_exceptions.json",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._whitelist.APPROVED_EXCEPTIONS_FILE",
|
"steam_backlog_enforcer._whitelist.APPROVED_EXCEPTIONS_FILE",
|
||||||
fake_config / "approved_exceptions.json",
|
fake_config / "approved_exceptions.json",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._whitelist.EXCEPTION_AUDIT_LOG",
|
"steam_backlog_enforcer._whitelist.EXCEPTION_AUDIT_LOG",
|
||||||
fake_config / "exception_audit.log",
|
fake_config / "exception_audit.log",
|
||||||
),
|
),
|
||||||
# _enforce_loop imports CONFIG_FILE directly; patch the local binding so
|
# _enforce_loop imports CONFIG_FILE directly; patch the local binding so
|
||||||
# lock_enforcement_files() uses the tmp path instead of the real one.
|
# lock_enforcement_files() uses the tmp path instead of the real one.
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._enforce_loop.CONFIG_FILE",
|
"steam_backlog_enforcer._enforce_loop.CONFIG_FILE",
|
||||||
fake_config / "config.json",
|
fake_config / "config.json",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -110,27 +110,27 @@ def _block_real_subprocesses() -> Iterator[None]:
|
|||||||
|
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.run",
|
"steam_backlog_enforcer.game_install.subprocess.run",
|
||||||
noop_run,
|
noop_run,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.Popen",
|
"steam_backlog_enforcer.game_install.subprocess.Popen",
|
||||||
noop_popen,
|
noop_popen,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.subprocess.run",
|
"steam_backlog_enforcer.enforcer.subprocess.run",
|
||||||
noop_run,
|
noop_run,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
noop_run,
|
noop_run,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.subprocess.run",
|
"steam_backlog_enforcer.library_hider.subprocess.run",
|
||||||
noop_run,
|
noop_run,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.subprocess.Popen",
|
"steam_backlog_enforcer.library_hider.subprocess.Popen",
|
||||||
noop_popen,
|
noop_popen,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -147,9 +147,9 @@ def _no_real_sleep() -> Iterator[None]:
|
|||||||
"""
|
"""
|
||||||
noop = MagicMock()
|
noop = MagicMock()
|
||||||
with (
|
with (
|
||||||
patch("python_pkg.steam_backlog_enforcer.game_install.time.sleep", noop),
|
patch("steam_backlog_enforcer.game_install.time.sleep", noop),
|
||||||
patch("python_pkg.steam_backlog_enforcer.library_hider.time.sleep", noop),
|
patch("steam_backlog_enforcer.library_hider.time.sleep", noop),
|
||||||
patch("python_pkg.steam_backlog_enforcer.steam_api.time.sleep", noop),
|
patch("steam_backlog_enforcer.steam_api.time.sleep", noop),
|
||||||
patch("python_pkg.steam_backlog_enforcer._enforce_loop.time.sleep", noop),
|
patch("steam_backlog_enforcer._enforce_loop.time.sleep", noop),
|
||||||
):
|
):
|
||||||
yield
|
yield
|
||||||
|
|||||||
@ -4,10 +4,10 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._cmd_done import _prompt_keep_or_skip
|
from steam_backlog_enforcer._cmd_done import _prompt_keep_or_skip
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
CMD_DONE_PKG = "python_pkg.steam_backlog_enforcer._cmd_done"
|
CMD_DONE_PKG = "steam_backlog_enforcer._cmd_done"
|
||||||
|
|
||||||
|
|
||||||
class TestPromptKeepOrSkip:
|
class TestPromptKeepOrSkip:
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.config import (
|
from steam_backlog_enforcer.config import (
|
||||||
Config,
|
Config,
|
||||||
State,
|
State,
|
||||||
_atomic_write,
|
_atomic_write,
|
||||||
@ -38,7 +38,7 @@ class TestAtomicWrite:
|
|||||||
target = tmp_path / "out.json"
|
target = tmp_path / "out.json"
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.config.os.write",
|
"steam_backlog_enforcer.config.os.write",
|
||||||
side_effect=OSError("disk full"),
|
side_effect=OSError("disk full"),
|
||||||
),
|
),
|
||||||
pytest.raises(OSError, match="disk full"),
|
pytest.raises(OSError, match="disk full"),
|
||||||
@ -81,8 +81,8 @@ class TestConfig:
|
|||||||
config_dir = tmp_path / "cfg"
|
config_dir = tmp_path / "cfg"
|
||||||
config_file = config_dir / "config.json"
|
config_file = config_dir / "config.json"
|
||||||
with (
|
with (
|
||||||
patch("python_pkg.steam_backlog_enforcer.config.CONFIG_DIR", config_dir),
|
patch("steam_backlog_enforcer.config.CONFIG_DIR", config_dir),
|
||||||
patch("python_pkg.steam_backlog_enforcer.config.CONFIG_FILE", config_file),
|
patch("steam_backlog_enforcer.config.CONFIG_FILE", config_file),
|
||||||
):
|
):
|
||||||
cfg.save()
|
cfg.save()
|
||||||
data = json.loads(config_file.read_text(encoding="utf-8"))
|
data = json.loads(config_file.read_text(encoding="utf-8"))
|
||||||
@ -95,14 +95,14 @@ class TestConfig:
|
|||||||
json.dumps({"steam_api_key": "key1", "steam_id": "id1"}) + "\n",
|
json.dumps({"steam_api_key": "key1", "steam_id": "id1"}) + "\n",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
with patch("python_pkg.steam_backlog_enforcer.config.CONFIG_FILE", config_file):
|
with patch("steam_backlog_enforcer.config.CONFIG_FILE", config_file):
|
||||||
cfg = Config.load()
|
cfg = Config.load()
|
||||||
assert cfg.steam_api_key == "key1"
|
assert cfg.steam_api_key == "key1"
|
||||||
assert cfg.steam_id == "id1"
|
assert cfg.steam_id == "id1"
|
||||||
|
|
||||||
def test_load_missing(self, tmp_path: Path) -> None:
|
def test_load_missing(self, tmp_path: Path) -> None:
|
||||||
config_file = tmp_path / "nonexistent.json"
|
config_file = tmp_path / "nonexistent.json"
|
||||||
with patch("python_pkg.steam_backlog_enforcer.config.CONFIG_FILE", config_file):
|
with patch("steam_backlog_enforcer.config.CONFIG_FILE", config_file):
|
||||||
cfg = Config.load()
|
cfg = Config.load()
|
||||||
assert cfg.steam_api_key == ""
|
assert cfg.steam_api_key == ""
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ class TestConfig:
|
|||||||
json.dumps({"steam_api_key": "k", "unknown_field": 42}) + "\n",
|
json.dumps({"steam_api_key": "k", "unknown_field": 42}) + "\n",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
with patch("python_pkg.steam_backlog_enforcer.config.CONFIG_FILE", config_file):
|
with patch("steam_backlog_enforcer.config.CONFIG_FILE", config_file):
|
||||||
cfg = Config.load()
|
cfg = Config.load()
|
||||||
assert cfg.steam_api_key == "k"
|
assert cfg.steam_api_key == "k"
|
||||||
|
|
||||||
@ -131,8 +131,8 @@ class TestState:
|
|||||||
config_dir = tmp_path / "cfg"
|
config_dir = tmp_path / "cfg"
|
||||||
state_file = config_dir / "state.json"
|
state_file = config_dir / "state.json"
|
||||||
with (
|
with (
|
||||||
patch("python_pkg.steam_backlog_enforcer.config.CONFIG_DIR", config_dir),
|
patch("steam_backlog_enforcer.config.CONFIG_DIR", config_dir),
|
||||||
patch("python_pkg.steam_backlog_enforcer.config.STATE_FILE", state_file),
|
patch("steam_backlog_enforcer.config.STATE_FILE", state_file),
|
||||||
):
|
):
|
||||||
state.save()
|
state.save()
|
||||||
data = json.loads(state_file.read_text(encoding="utf-8"))
|
data = json.loads(state_file.read_text(encoding="utf-8"))
|
||||||
@ -152,21 +152,21 @@ class TestState:
|
|||||||
+ "\n",
|
+ "\n",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
with patch("python_pkg.steam_backlog_enforcer.config.STATE_FILE", state_file):
|
with patch("steam_backlog_enforcer.config.STATE_FILE", state_file):
|
||||||
st = State.load()
|
st = State.load()
|
||||||
assert st.current_app_id == 50
|
assert st.current_app_id == 50
|
||||||
assert st.finished_app_ids == [1, 2]
|
assert st.finished_app_ids == [1, 2]
|
||||||
|
|
||||||
def test_load_missing(self, tmp_path: Path) -> None:
|
def test_load_missing(self, tmp_path: Path) -> None:
|
||||||
state_file = tmp_path / "nonexistent.json"
|
state_file = tmp_path / "nonexistent.json"
|
||||||
with patch("python_pkg.steam_backlog_enforcer.config.STATE_FILE", state_file):
|
with patch("steam_backlog_enforcer.config.STATE_FILE", state_file):
|
||||||
st = State.load()
|
st = State.load()
|
||||||
assert st.current_app_id is None
|
assert st.current_app_id is None
|
||||||
|
|
||||||
def test_load_corrupt(self, tmp_path: Path) -> None:
|
def test_load_corrupt(self, tmp_path: Path) -> None:
|
||||||
state_file = tmp_path / "state.json"
|
state_file = tmp_path / "state.json"
|
||||||
state_file.write_text("not valid json{{", encoding="utf-8")
|
state_file.write_text("not valid json{{", encoding="utf-8")
|
||||||
with patch("python_pkg.steam_backlog_enforcer.config.STATE_FILE", state_file):
|
with patch("steam_backlog_enforcer.config.STATE_FILE", state_file):
|
||||||
st = State.load()
|
st = State.load()
|
||||||
assert st.current_app_id is None
|
assert st.current_app_id is None
|
||||||
assert st.current_game_name == ""
|
assert st.current_game_name == ""
|
||||||
@ -215,8 +215,8 @@ class TestSnapshot:
|
|||||||
config_dir = tmp_path / "cfg"
|
config_dir = tmp_path / "cfg"
|
||||||
snap_file = config_dir / "snapshot.json"
|
snap_file = config_dir / "snapshot.json"
|
||||||
with (
|
with (
|
||||||
patch("python_pkg.steam_backlog_enforcer.config.CONFIG_DIR", config_dir),
|
patch("steam_backlog_enforcer.config.CONFIG_DIR", config_dir),
|
||||||
patch("python_pkg.steam_backlog_enforcer.config.SNAPSHOT_FILE", snap_file),
|
patch("steam_backlog_enforcer.config.SNAPSHOT_FILE", snap_file),
|
||||||
):
|
):
|
||||||
data: list[dict[str, Any]] = [{"app_id": 1, "name": "G1"}]
|
data: list[dict[str, Any]] = [{"app_id": 1, "name": "G1"}]
|
||||||
save_snapshot(data)
|
save_snapshot(data)
|
||||||
@ -225,7 +225,7 @@ class TestSnapshot:
|
|||||||
|
|
||||||
def test_load_none(self, tmp_path: Path) -> None:
|
def test_load_none(self, tmp_path: Path) -> None:
|
||||||
snap_file = tmp_path / "nonexistent.json"
|
snap_file = tmp_path / "nonexistent.json"
|
||||||
with patch("python_pkg.steam_backlog_enforcer.config.SNAPSHOT_FILE", snap_file):
|
with patch("steam_backlog_enforcer.config.SNAPSHOT_FILE", snap_file):
|
||||||
assert load_snapshot() is None
|
assert load_snapshot() is None
|
||||||
|
|
||||||
|
|
||||||
@ -236,8 +236,8 @@ class TestInteractiveSetup:
|
|||||||
config_dir = tmp_path / "cfg"
|
config_dir = tmp_path / "cfg"
|
||||||
config_file = config_dir / "config.json"
|
config_file = config_dir / "config.json"
|
||||||
with (
|
with (
|
||||||
patch("python_pkg.steam_backlog_enforcer.config.CONFIG_DIR", config_dir),
|
patch("steam_backlog_enforcer.config.CONFIG_DIR", config_dir),
|
||||||
patch("python_pkg.steam_backlog_enforcer.config.CONFIG_FILE", config_file),
|
patch("steam_backlog_enforcer.config.CONFIG_FILE", config_file),
|
||||||
patch("builtins.input", side_effect=["mykey", "myid"]),
|
patch("builtins.input", side_effect=["mykey", "myid"]),
|
||||||
):
|
):
|
||||||
cfg = interactive_setup()
|
cfg = interactive_setup()
|
||||||
@ -256,8 +256,8 @@ class TestInteractiveSetup:
|
|||||||
config_dir = tmp_path / "cfg"
|
config_dir = tmp_path / "cfg"
|
||||||
config_file = config_dir / "config.json"
|
config_file = config_dir / "config.json"
|
||||||
with (
|
with (
|
||||||
patch("python_pkg.steam_backlog_enforcer.config.CONFIG_DIR", config_dir),
|
patch("steam_backlog_enforcer.config.CONFIG_DIR", config_dir),
|
||||||
patch("python_pkg.steam_backlog_enforcer.config.CONFIG_FILE", config_file),
|
patch("steam_backlog_enforcer.config.CONFIG_FILE", config_file),
|
||||||
patch("builtins.input", side_effect=["key", ""]),
|
patch("builtins.input", side_effect=["key", ""]),
|
||||||
pytest.raises(SystemExit),
|
pytest.raises(SystemExit),
|
||||||
):
|
):
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import json
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._enforce_loop import (
|
from steam_backlog_enforcer._enforce_loop import (
|
||||||
_enforce_auto_install,
|
_enforce_auto_install,
|
||||||
_enforce_hide_games,
|
_enforce_hide_games,
|
||||||
_enforce_setup,
|
_enforce_setup,
|
||||||
@ -15,12 +15,12 @@ from python_pkg.steam_backlog_enforcer._enforce_loop import (
|
|||||||
_save_owned_app_ids_cache,
|
_save_owned_app_ids_cache,
|
||||||
get_all_owned_app_ids,
|
get_all_owned_app_ids,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
PKG = "python_pkg.steam_backlog_enforcer._enforce_loop"
|
PKG = "steam_backlog_enforcer._enforce_loop"
|
||||||
|
|
||||||
|
|
||||||
class TestGetAllOwnedAppIds:
|
class TestGetAllOwnedAppIds:
|
||||||
|
|||||||
@ -4,13 +4,13 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._enforce_loop import (
|
from steam_backlog_enforcer._enforce_loop import (
|
||||||
_enforce_loop_iteration,
|
_enforce_loop_iteration,
|
||||||
do_enforce,
|
do_enforce,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
|
|
||||||
PKG = "python_pkg.steam_backlog_enforcer._enforce_loop"
|
PKG = "steam_backlog_enforcer._enforce_loop"
|
||||||
|
|
||||||
|
|
||||||
class TestEnforceLoopIteration:
|
class TestEnforceLoopIteration:
|
||||||
|
|||||||
@ -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 python_pkg.steam_backlog_enforcer.enforcer import (
|
from steam_backlog_enforcer.enforcer import (
|
||||||
enforce_allowed_game,
|
enforce_allowed_game,
|
||||||
get_running_steam_game_pids,
|
get_running_steam_game_pids,
|
||||||
kill_process,
|
kill_process,
|
||||||
@ -27,7 +27,7 @@ class TestGetRunningPids:
|
|||||||
(pid_dir / "environ").write_bytes(environ)
|
(pid_dir / "environ").write_bytes(environ)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.Path",
|
"steam_backlog_enforcer.enforcer.Path",
|
||||||
return_value=proc_dir,
|
return_value=proc_dir,
|
||||||
):
|
):
|
||||||
result = get_running_steam_game_pids()
|
result = get_running_steam_game_pids()
|
||||||
@ -40,7 +40,7 @@ class TestGetRunningPids:
|
|||||||
(proc_dir / "cpuinfo").touch()
|
(proc_dir / "cpuinfo").touch()
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.Path",
|
"steam_backlog_enforcer.enforcer.Path",
|
||||||
return_value=proc_dir,
|
return_value=proc_dir,
|
||||||
):
|
):
|
||||||
result = get_running_steam_game_pids()
|
result = get_running_steam_game_pids()
|
||||||
@ -53,7 +53,7 @@ class TestGetRunningPids:
|
|||||||
# No environ file -> OSError when reading
|
# No environ file -> OSError when reading
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.Path",
|
"steam_backlog_enforcer.enforcer.Path",
|
||||||
return_value=proc_dir,
|
return_value=proc_dir,
|
||||||
):
|
):
|
||||||
result = get_running_steam_game_pids()
|
result = get_running_steam_game_pids()
|
||||||
@ -67,7 +67,7 @@ class TestGetRunningPids:
|
|||||||
(pid_dir / "environ").write_bytes(environ)
|
(pid_dir / "environ").write_bytes(environ)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.Path",
|
"steam_backlog_enforcer.enforcer.Path",
|
||||||
return_value=proc_dir,
|
return_value=proc_dir,
|
||||||
):
|
):
|
||||||
result = get_running_steam_game_pids()
|
result = get_running_steam_game_pids()
|
||||||
@ -81,7 +81,7 @@ class TestGetRunningPids:
|
|||||||
(pid_dir / "environ").write_bytes(environ)
|
(pid_dir / "environ").write_bytes(environ)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.Path",
|
"steam_backlog_enforcer.enforcer.Path",
|
||||||
return_value=proc_dir,
|
return_value=proc_dir,
|
||||||
):
|
):
|
||||||
result = get_running_steam_game_pids()
|
result = get_running_steam_game_pids()
|
||||||
@ -93,7 +93,7 @@ class TestEnforceAllowedGame:
|
|||||||
|
|
||||||
def test_no_violations(self) -> None:
|
def test_no_violations(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.get_running_steam_game_pids",
|
"steam_backlog_enforcer.enforcer.get_running_steam_game_pids",
|
||||||
return_value={100: 440},
|
return_value={100: 440},
|
||||||
):
|
):
|
||||||
result = enforce_allowed_game(440)
|
result = enforce_allowed_game(440)
|
||||||
@ -102,11 +102,11 @@ class TestEnforceAllowedGame:
|
|||||||
def test_kills_unauthorized(self) -> None:
|
def test_kills_unauthorized(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.get_running_steam_game_pids",
|
"steam_backlog_enforcer.enforcer.get_running_steam_game_pids",
|
||||||
return_value={100: 570, 200: 440},
|
return_value={100: 570, 200: 440},
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.kill_process"
|
"steam_backlog_enforcer.enforcer.kill_process"
|
||||||
) as mock_kill,
|
) as mock_kill,
|
||||||
):
|
):
|
||||||
result = enforce_allowed_game(440, kill_unauthorized=True)
|
result = enforce_allowed_game(440, kill_unauthorized=True)
|
||||||
@ -115,7 +115,7 @@ class TestEnforceAllowedGame:
|
|||||||
|
|
||||||
def test_skips_app_id_zero(self) -> None:
|
def test_skips_app_id_zero(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.get_running_steam_game_pids",
|
"steam_backlog_enforcer.enforcer.get_running_steam_game_pids",
|
||||||
return_value={100: 0},
|
return_value={100: 0},
|
||||||
):
|
):
|
||||||
result = enforce_allowed_game(440)
|
result = enforce_allowed_game(440)
|
||||||
@ -123,7 +123,7 @@ class TestEnforceAllowedGame:
|
|||||||
|
|
||||||
def test_detects_without_killing(self) -> None:
|
def test_detects_without_killing(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.get_running_steam_game_pids",
|
"steam_backlog_enforcer.enforcer.get_running_steam_game_pids",
|
||||||
return_value={100: 570},
|
return_value={100: 570},
|
||||||
):
|
):
|
||||||
result = enforce_allowed_game(440, kill_unauthorized=False)
|
result = enforce_allowed_game(440, kill_unauthorized=False)
|
||||||
@ -137,15 +137,15 @@ class TestEnforceAllowedGame:
|
|||||||
"""Protected IDs must never be killed even if not the assigned game."""
|
"""Protected IDs must never be killed even if not the assigned game."""
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.get_running_steam_game_pids",
|
"steam_backlog_enforcer.enforcer.get_running_steam_game_pids",
|
||||||
return_value={100: 1331550, 200: 440},
|
return_value={100: 1331550, 200: 440},
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.is_protected_app",
|
"steam_backlog_enforcer.enforcer.is_protected_app",
|
||||||
side_effect=lambda aid: aid == 1331550,
|
side_effect=lambda aid: aid == 1331550,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.kill_process"
|
"steam_backlog_enforcer.enforcer.kill_process"
|
||||||
) as mock_kill,
|
) as mock_kill,
|
||||||
):
|
):
|
||||||
result = enforce_allowed_game(440, kill_unauthorized=True)
|
result = enforce_allowed_game(440, kill_unauthorized=True)
|
||||||
@ -157,20 +157,20 @@ class TestKillProcess:
|
|||||||
"""Tests for kill_process."""
|
"""Tests for kill_process."""
|
||||||
|
|
||||||
def test_kill_success(self) -> None:
|
def test_kill_success(self) -> None:
|
||||||
with patch("python_pkg.steam_backlog_enforcer.enforcer.os.kill") as mock_kill:
|
with patch("steam_backlog_enforcer.enforcer.os.kill") as mock_kill:
|
||||||
kill_process(123, 440)
|
kill_process(123, 440)
|
||||||
mock_kill.assert_called_once()
|
mock_kill.assert_called_once()
|
||||||
|
|
||||||
def test_process_already_gone(self) -> None:
|
def test_process_already_gone(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.os.kill",
|
"steam_backlog_enforcer.enforcer.os.kill",
|
||||||
side_effect=ProcessLookupError,
|
side_effect=ProcessLookupError,
|
||||||
):
|
):
|
||||||
kill_process(123, 440) # Should not raise
|
kill_process(123, 440) # Should not raise
|
||||||
|
|
||||||
def test_permission_error(self) -> None:
|
def test_permission_error(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.os.kill",
|
"steam_backlog_enforcer.enforcer.os.kill",
|
||||||
side_effect=PermissionError,
|
side_effect=PermissionError,
|
||||||
):
|
):
|
||||||
kill_process(123, 440) # Should not raise
|
kill_process(123, 440) # Should not raise
|
||||||
@ -181,21 +181,21 @@ class TestSendNotification:
|
|||||||
|
|
||||||
def test_sends(self) -> None:
|
def test_sends(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.subprocess.run"
|
"steam_backlog_enforcer.enforcer.subprocess.run"
|
||||||
) as mock_run:
|
) as mock_run:
|
||||||
send_notification("Title", "Body")
|
send_notification("Title", "Body")
|
||||||
mock_run.assert_called_once()
|
mock_run.assert_called_once()
|
||||||
|
|
||||||
def test_handles_missing_notify_send(self) -> None:
|
def test_handles_missing_notify_send(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.subprocess.run",
|
"steam_backlog_enforcer.enforcer.subprocess.run",
|
||||||
side_effect=FileNotFoundError,
|
side_effect=FileNotFoundError,
|
||||||
):
|
):
|
||||||
send_notification("Title", "Body") # Should not raise
|
send_notification("Title", "Body") # Should not raise
|
||||||
|
|
||||||
def test_handles_os_error(self) -> None:
|
def test_handles_os_error(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.enforcer.subprocess.run",
|
"steam_backlog_enforcer.enforcer.subprocess.run",
|
||||||
side_effect=OSError,
|
side_effect=OSError,
|
||||||
):
|
):
|
||||||
send_notification("Title", "Body") # Should not raise
|
send_notification("Title", "Body") # Should not raise
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from unittest.mock import MagicMock, patch
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer.game_install import (
|
||||||
_assert_not_real_steam,
|
_assert_not_real_steam,
|
||||||
_echo,
|
_echo,
|
||||||
_ensure_steam_running,
|
_ensure_steam_running,
|
||||||
@ -22,7 +22,7 @@ if TYPE_CHECKING:
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
PKG = "python_pkg.steam_backlog_enforcer.game_install"
|
PKG = "steam_backlog_enforcer.game_install"
|
||||||
|
|
||||||
|
|
||||||
class TestAssertNotRealSteam:
|
class TestAssertNotRealSteam:
|
||||||
@ -99,7 +99,7 @@ class TestTriggerSteamInstall:
|
|||||||
|
|
||||||
def test_success(self) -> None:
|
def test_success(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.run"
|
"steam_backlog_enforcer.game_install.subprocess.run"
|
||||||
) as mock_run:
|
) as mock_run:
|
||||||
result = _trigger_steam_install(440, "TF2")
|
result = _trigger_steam_install(440, "TF2")
|
||||||
assert result is True
|
assert result is True
|
||||||
@ -107,7 +107,7 @@ class TestTriggerSteamInstall:
|
|||||||
|
|
||||||
def test_file_not_found(self) -> None:
|
def test_file_not_found(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.run",
|
"steam_backlog_enforcer.game_install.subprocess.run",
|
||||||
side_effect=FileNotFoundError,
|
side_effect=FileNotFoundError,
|
||||||
):
|
):
|
||||||
result = _trigger_steam_install(440, "TF2")
|
result = _trigger_steam_install(440, "TF2")
|
||||||
@ -115,7 +115,7 @@ class TestTriggerSteamInstall:
|
|||||||
|
|
||||||
def test_os_error(self) -> None:
|
def test_os_error(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.run",
|
"steam_backlog_enforcer.game_install.subprocess.run",
|
||||||
side_effect=OSError,
|
side_effect=OSError,
|
||||||
):
|
):
|
||||||
result = _trigger_steam_install(440, "TF2")
|
result = _trigger_steam_install(440, "TF2")
|
||||||
@ -125,7 +125,7 @@ class TestTriggerSteamInstall:
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.run",
|
"steam_backlog_enforcer.game_install.subprocess.run",
|
||||||
side_effect=subprocess.TimeoutExpired("cmd", 15),
|
side_effect=subprocess.TimeoutExpired("cmd", 15),
|
||||||
):
|
):
|
||||||
result = _trigger_steam_install(440, "TF2")
|
result = _trigger_steam_install(440, "TF2")
|
||||||
@ -155,14 +155,14 @@ class TestGetUidGid:
|
|||||||
mock_pw.pw_uid = 1001
|
mock_pw.pw_uid = 1001
|
||||||
mock_pw.pw_gid = 1001
|
mock_pw.pw_gid = 1001
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.pwd.getpwnam",
|
"steam_backlog_enforcer.game_install.pwd.getpwnam",
|
||||||
return_value=mock_pw,
|
return_value=mock_pw,
|
||||||
):
|
):
|
||||||
assert _get_uid_gid_for_user("alice") == (1001, 1001)
|
assert _get_uid_gid_for_user("alice") == (1001, 1001)
|
||||||
|
|
||||||
def test_unknown_user(self) -> None:
|
def test_unknown_user(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.pwd.getpwnam",
|
"steam_backlog_enforcer.game_install.pwd.getpwnam",
|
||||||
side_effect=KeyError,
|
side_effect=KeyError,
|
||||||
):
|
):
|
||||||
assert _get_uid_gid_for_user("nobody") == (1000, 1000)
|
assert _get_uid_gid_for_user("nobody") == (1000, 1000)
|
||||||
@ -175,13 +175,13 @@ class TestIsGameInstalled:
|
|||||||
manifest = tmp_path / "appmanifest_440.acf"
|
manifest = tmp_path / "appmanifest_440.acf"
|
||||||
manifest.touch()
|
manifest.touch()
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
||||||
):
|
):
|
||||||
assert is_game_installed(440) is True
|
assert is_game_installed(440) is True
|
||||||
|
|
||||||
def test_not_installed(self, tmp_path: Path) -> None:
|
def test_not_installed(self, tmp_path: Path) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
||||||
):
|
):
|
||||||
assert is_game_installed(440) is False
|
assert is_game_installed(440) is False
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ class TestEnsureSteamRunning:
|
|||||||
def test_already_running(self) -> None:
|
def test_already_running(self) -> None:
|
||||||
mock_result = MagicMock(returncode=0)
|
mock_result = MagicMock(returncode=0)
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.run",
|
"steam_backlog_enforcer.game_install.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
):
|
):
|
||||||
_ensure_steam_running()
|
_ensure_steam_running()
|
||||||
@ -201,17 +201,17 @@ class TestEnsureSteamRunning:
|
|||||||
mock_result = MagicMock(returncode=1)
|
mock_result = MagicMock(returncode=1)
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.run",
|
"steam_backlog_enforcer.game_install.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.Popen"
|
"steam_backlog_enforcer.game_install.subprocess.Popen"
|
||||||
) as mock_popen,
|
) as mock_popen,
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.geteuid",
|
"steam_backlog_enforcer.game_install.os.geteuid",
|
||||||
return_value=1000,
|
return_value=1000,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.game_install.time.sleep"),
|
patch("steam_backlog_enforcer.game_install.time.sleep"),
|
||||||
):
|
):
|
||||||
_ensure_steam_running()
|
_ensure_steam_running()
|
||||||
mock_popen.assert_called_once()
|
mock_popen.assert_called_once()
|
||||||
@ -223,25 +223,25 @@ class TestEnsureSteamRunning:
|
|||||||
mock_pw.pw_gid = 1000
|
mock_pw.pw_gid = 1000
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.run",
|
"steam_backlog_enforcer.game_install.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.Popen"
|
"steam_backlog_enforcer.game_install.subprocess.Popen"
|
||||||
) as mock_popen,
|
) as mock_popen,
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.geteuid",
|
"steam_backlog_enforcer.game_install.os.geteuid",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._get_real_user",
|
"steam_backlog_enforcer.game_install._get_real_user",
|
||||||
return_value="alice",
|
return_value="alice",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._get_uid_gid_for_user",
|
"steam_backlog_enforcer.game_install._get_uid_gid_for_user",
|
||||||
return_value=(1000, 1000),
|
return_value=(1000, 1000),
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.game_install.time.sleep"),
|
patch("steam_backlog_enforcer.game_install.time.sleep"),
|
||||||
):
|
):
|
||||||
_ensure_steam_running()
|
_ensure_steam_running()
|
||||||
mock_popen.assert_called_once()
|
mock_popen.assert_called_once()
|
||||||
@ -249,15 +249,15 @@ class TestEnsureSteamRunning:
|
|||||||
def test_pgrep_not_found(self) -> None:
|
def test_pgrep_not_found(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.run",
|
"steam_backlog_enforcer.game_install.subprocess.run",
|
||||||
side_effect=FileNotFoundError,
|
side_effect=FileNotFoundError,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.game_install.subprocess.Popen"),
|
patch("steam_backlog_enforcer.game_install.subprocess.Popen"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.geteuid",
|
"steam_backlog_enforcer.game_install.os.geteuid",
|
||||||
return_value=1000,
|
return_value=1000,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.game_install.time.sleep"),
|
patch("steam_backlog_enforcer.game_install.time.sleep"),
|
||||||
):
|
):
|
||||||
_ensure_steam_running()
|
_ensure_steam_running()
|
||||||
|
|
||||||
@ -265,15 +265,15 @@ class TestEnsureSteamRunning:
|
|||||||
mock_result = MagicMock(returncode=1)
|
mock_result = MagicMock(returncode=1)
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.run",
|
"steam_backlog_enforcer.game_install.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.subprocess.Popen",
|
"steam_backlog_enforcer.game_install.subprocess.Popen",
|
||||||
side_effect=FileNotFoundError,
|
side_effect=FileNotFoundError,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.geteuid",
|
"steam_backlog_enforcer.game_install.os.geteuid",
|
||||||
return_value=1000,
|
return_value=1000,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer.game_install import (
|
||||||
_remove_game_dirs,
|
_remove_game_dirs,
|
||||||
uninstall_game,
|
uninstall_game,
|
||||||
uninstall_other_games,
|
uninstall_other_games,
|
||||||
@ -14,7 +14,7 @@ from python_pkg.steam_backlog_enforcer.game_install import (
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
PKG = "python_pkg.steam_backlog_enforcer.game_install"
|
PKG = "steam_backlog_enforcer.game_install"
|
||||||
|
|
||||||
|
|
||||||
class TestRemoveGameDirs:
|
class TestRemoveGameDirs:
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.game_install import (
|
from steam_backlog_enforcer.game_install import (
|
||||||
_read_install_dir,
|
_read_install_dir,
|
||||||
_remove_manifest,
|
_remove_manifest,
|
||||||
get_installed_games,
|
get_installed_games,
|
||||||
@ -16,7 +16,7 @@ if TYPE_CHECKING:
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
PKG = "python_pkg.steam_backlog_enforcer.game_install"
|
PKG = "steam_backlog_enforcer.game_install"
|
||||||
|
|
||||||
|
|
||||||
class TestInstallGame:
|
class TestInstallGame:
|
||||||
@ -26,21 +26,21 @@ class TestInstallGame:
|
|||||||
manifest = tmp_path / "appmanifest_440.acf"
|
manifest = tmp_path / "appmanifest_440.acf"
|
||||||
manifest.touch()
|
manifest.touch()
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
||||||
):
|
):
|
||||||
assert install_game(440, "TF2", "steam123") is True
|
assert install_game(440, "TF2", "steam123") is True
|
||||||
|
|
||||||
def test_use_steam_protocol_success(self, tmp_path: Path) -> None:
|
def test_use_steam_protocol_success(self, tmp_path: Path) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
||||||
tmp_path,
|
tmp_path,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._ensure_steam_running"
|
"steam_backlog_enforcer.game_install._ensure_steam_running"
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._trigger_steam_install",
|
"steam_backlog_enforcer.game_install._trigger_steam_install",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -49,18 +49,18 @@ class TestInstallGame:
|
|||||||
def test_use_steam_protocol_fallback(self, tmp_path: Path) -> None:
|
def test_use_steam_protocol_fallback(self, tmp_path: Path) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
||||||
tmp_path,
|
tmp_path,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._ensure_steam_running"
|
"steam_backlog_enforcer.game_install._ensure_steam_running"
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._trigger_steam_install",
|
"steam_backlog_enforcer.game_install._trigger_steam_install",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.geteuid",
|
"steam_backlog_enforcer.game_install.os.geteuid",
|
||||||
return_value=1000,
|
return_value=1000,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -70,26 +70,26 @@ class TestInstallGame:
|
|||||||
def test_manifest_write_as_root(self, tmp_path: Path) -> None:
|
def test_manifest_write_as_root(self, tmp_path: Path) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
||||||
tmp_path,
|
tmp_path,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._ensure_steam_running"
|
"steam_backlog_enforcer.game_install._ensure_steam_running"
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.geteuid",
|
"steam_backlog_enforcer.game_install.os.geteuid",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._get_real_user",
|
"steam_backlog_enforcer.game_install._get_real_user",
|
||||||
return_value="alice",
|
return_value="alice",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._get_uid_gid_for_user",
|
"steam_backlog_enforcer.game_install._get_uid_gid_for_user",
|
||||||
return_value=(1001, 1001),
|
return_value=(1001, 1001),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.chown"
|
"steam_backlog_enforcer.game_install.os.chown"
|
||||||
) as mock_chown,
|
) as mock_chown,
|
||||||
):
|
):
|
||||||
assert install_game(440, "TF2", "s1") is True
|
assert install_game(440, "TF2", "s1") is True
|
||||||
@ -99,14 +99,14 @@ class TestInstallGame:
|
|||||||
# Make steamapps path not writable
|
# Make steamapps path not writable
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
||||||
tmp_path / "nonexistent" / "deep",
|
tmp_path / "nonexistent" / "deep",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._ensure_steam_running"
|
"steam_backlog_enforcer.game_install._ensure_steam_running"
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.geteuid",
|
"steam_backlog_enforcer.game_install.os.geteuid",
|
||||||
return_value=1000,
|
return_value=1000,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -115,14 +115,14 @@ class TestInstallGame:
|
|||||||
def test_empty_game_name(self, tmp_path: Path) -> None:
|
def test_empty_game_name(self, tmp_path: Path) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
||||||
tmp_path,
|
tmp_path,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._ensure_steam_running"
|
"steam_backlog_enforcer.game_install._ensure_steam_running"
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.geteuid",
|
"steam_backlog_enforcer.game_install.os.geteuid",
|
||||||
return_value=1000,
|
return_value=1000,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -131,18 +131,18 @@ class TestInstallGame:
|
|||||||
def test_manifest_not_root_no_chown(self, tmp_path: Path) -> None:
|
def test_manifest_not_root_no_chown(self, tmp_path: Path) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
||||||
tmp_path,
|
tmp_path,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._ensure_steam_running"
|
"steam_backlog_enforcer.game_install._ensure_steam_running"
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.geteuid",
|
"steam_backlog_enforcer.game_install.os.geteuid",
|
||||||
return_value=1000,
|
return_value=1000,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.chown"
|
"steam_backlog_enforcer.game_install.os.chown"
|
||||||
) as mock_chown,
|
) as mock_chown,
|
||||||
):
|
):
|
||||||
assert install_game(440, "TF2", "s1") is True
|
assert install_game(440, "TF2", "s1") is True
|
||||||
@ -152,22 +152,22 @@ class TestInstallGame:
|
|||||||
"""When real user IS root, don't chown."""
|
"""When real user IS root, don't chown."""
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
|
||||||
tmp_path,
|
tmp_path,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._ensure_steam_running"
|
"steam_backlog_enforcer.game_install._ensure_steam_running"
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.geteuid",
|
"steam_backlog_enforcer.game_install.os.geteuid",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install._get_real_user",
|
"steam_backlog_enforcer.game_install._get_real_user",
|
||||||
return_value="root",
|
return_value="root",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.os.chown"
|
"steam_backlog_enforcer.game_install.os.chown"
|
||||||
) as mock_chown,
|
) as mock_chown,
|
||||||
):
|
):
|
||||||
assert install_game(440, "TF2", "s1") is True
|
assert install_game(440, "TF2", "s1") is True
|
||||||
@ -181,7 +181,7 @@ class TestGetInstalledGames:
|
|||||||
manifest = tmp_path / "appmanifest_440.acf"
|
manifest = tmp_path / "appmanifest_440.acf"
|
||||||
manifest.write_text('"appid"\t\t"440"\n"name"\t\t"Team Fortress 2"\n')
|
manifest.write_text('"appid"\t\t"440"\n"name"\t\t"Team Fortress 2"\n')
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
||||||
):
|
):
|
||||||
result = get_installed_games()
|
result = get_installed_games()
|
||||||
assert result == [(440, "Team Fortress 2")]
|
assert result == [(440, "Team Fortress 2")]
|
||||||
@ -190,14 +190,14 @@ class TestGetInstalledGames:
|
|||||||
manifest = tmp_path / "appmanifest_440.acf"
|
manifest = tmp_path / "appmanifest_440.acf"
|
||||||
manifest.write_text('"appid"\t\t"440"\n')
|
manifest.write_text('"appid"\t\t"440"\n')
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
||||||
):
|
):
|
||||||
result = get_installed_games()
|
result = get_installed_games()
|
||||||
assert result == [(440, "Unknown (440)")]
|
assert result == [(440, "Unknown (440)")]
|
||||||
|
|
||||||
def test_empty_dir(self, tmp_path: Path) -> None:
|
def test_empty_dir(self, tmp_path: Path) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
||||||
):
|
):
|
||||||
result = get_installed_games()
|
result = get_installed_games()
|
||||||
assert result == []
|
assert result == []
|
||||||
@ -206,7 +206,7 @@ class TestGetInstalledGames:
|
|||||||
manifest = tmp_path / "appmanifest_440.acf"
|
manifest = tmp_path / "appmanifest_440.acf"
|
||||||
manifest.write_text('"name"\t\t"NoAppId"\n')
|
manifest.write_text('"name"\t\t"NoAppId"\n')
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
||||||
):
|
):
|
||||||
result = get_installed_games()
|
result = get_installed_games()
|
||||||
assert result == []
|
assert result == []
|
||||||
@ -219,7 +219,7 @@ class TestReadInstallDir:
|
|||||||
manifest = tmp_path / "appmanifest_440.acf"
|
manifest = tmp_path / "appmanifest_440.acf"
|
||||||
manifest.write_text('"installdir"\t\t"Team Fortress 2"\n')
|
manifest.write_text('"installdir"\t\t"Team Fortress 2"\n')
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
||||||
):
|
):
|
||||||
result = _read_install_dir(manifest)
|
result = _read_install_dir(manifest)
|
||||||
assert result == tmp_path / "common" / "Team Fortress 2"
|
assert result == tmp_path / "common" / "Team Fortress 2"
|
||||||
@ -228,7 +228,7 @@ class TestReadInstallDir:
|
|||||||
manifest = tmp_path / "appmanifest_440.acf"
|
manifest = tmp_path / "appmanifest_440.acf"
|
||||||
manifest.write_text('"appid"\t\t"440"\n')
|
manifest.write_text('"appid"\t\t"440"\n')
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
"steam_backlog_enforcer.game_install.STEAMAPPS_PATH", tmp_path
|
||||||
):
|
):
|
||||||
assert _read_install_dir(manifest) is None
|
assert _read_install_dir(manifest) is None
|
||||||
|
|
||||||
|
|||||||
@ -9,14 +9,14 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_search import (
|
from steam_backlog_enforcer._hltb_search import (
|
||||||
_AuthInfo,
|
_AuthInfo,
|
||||||
_build_search_payload,
|
_build_search_payload,
|
||||||
_get_hltb_search_url,
|
_get_hltb_search_url,
|
||||||
_pick_best_hltb_entry,
|
_pick_best_hltb_entry,
|
||||||
_similarity,
|
_similarity,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.hltb import (
|
from steam_backlog_enforcer.hltb import (
|
||||||
_get_auth_info,
|
_get_auth_info,
|
||||||
load_hltb_cache,
|
load_hltb_cache,
|
||||||
save_hltb_cache,
|
save_hltb_cache,
|
||||||
@ -33,7 +33,7 @@ class TestHltbCache:
|
|||||||
cache_file = tmp_path / "hltb_cache.json"
|
cache_file = tmp_path / "hltb_cache.json"
|
||||||
cache_file.write_text(json.dumps({"440": 10.5}), encoding="utf-8")
|
cache_file.write_text(json.dumps({"440": 10.5}), encoding="utf-8")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file
|
"steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file
|
||||||
):
|
):
|
||||||
result = load_hltb_cache()
|
result = load_hltb_cache()
|
||||||
assert result == {440: 10.5}
|
assert result == {440: 10.5}
|
||||||
@ -41,7 +41,7 @@ class TestHltbCache:
|
|||||||
def test_load_cache_missing(self, tmp_path: Path) -> None:
|
def test_load_cache_missing(self, tmp_path: Path) -> None:
|
||||||
cache_file = tmp_path / "nonexistent.json"
|
cache_file = tmp_path / "nonexistent.json"
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file
|
"steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file
|
||||||
):
|
):
|
||||||
assert load_hltb_cache() == {}
|
assert load_hltb_cache() == {}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ class TestHltbCache:
|
|||||||
cache_file = tmp_path / "hltb_cache.json"
|
cache_file = tmp_path / "hltb_cache.json"
|
||||||
cache_file.write_text("not json", encoding="utf-8")
|
cache_file.write_text("not json", encoding="utf-8")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file
|
"steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE", cache_file
|
||||||
):
|
):
|
||||||
assert load_hltb_cache() == {}
|
assert load_hltb_cache() == {}
|
||||||
|
|
||||||
@ -57,17 +57,17 @@ class TestHltbCache:
|
|||||||
cache_file = tmp_path / "hltb_cache.json"
|
cache_file = tmp_path / "hltb_cache.json"
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE",
|
"steam_backlog_enforcer._hltb_types.HLTB_CACHE_FILE",
|
||||||
cache_file,
|
cache_file,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer._hltb_types.CONFIG_DIR", tmp_path),
|
patch("steam_backlog_enforcer._hltb_types.CONFIG_DIR", tmp_path),
|
||||||
):
|
):
|
||||||
save_hltb_cache({440: 10.5})
|
save_hltb_cache({440: 10.5})
|
||||||
assert cache_file.exists()
|
assert cache_file.exists()
|
||||||
|
|
||||||
def test_save_cache_os_error(self, tmp_path: Path) -> None:
|
def test_save_cache_os_error(self, tmp_path: Path) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_types._atomic_write",
|
"steam_backlog_enforcer._hltb_types._atomic_write",
|
||||||
side_effect=OSError("disk full"),
|
side_effect=OSError("disk full"),
|
||||||
):
|
):
|
||||||
save_hltb_cache({440: 10.5}) # Should not raise
|
save_hltb_cache({440: 10.5}) # Should not raise
|
||||||
@ -80,7 +80,7 @@ class TestGetHltbSearchUrl:
|
|||||||
mock_info = MagicMock()
|
mock_info = MagicMock()
|
||||||
mock_info.search_url = "/api/search/abc"
|
mock_info.search_url = "/api/search/abc"
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search.HTMLRequests"
|
"steam_backlog_enforcer._hltb_search.HTMLRequests"
|
||||||
) as mock_html:
|
) as mock_html:
|
||||||
mock_html.send_website_request_getcode.return_value = mock_info
|
mock_html.send_website_request_getcode.return_value = mock_info
|
||||||
mock_html.BASE_URL = "https://howlongtobeat.com"
|
mock_html.BASE_URL = "https://howlongtobeat.com"
|
||||||
@ -89,7 +89,7 @@ class TestGetHltbSearchUrl:
|
|||||||
|
|
||||||
def test_fallback_url(self) -> None:
|
def test_fallback_url(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search.HTMLRequests"
|
"steam_backlog_enforcer._hltb_search.HTMLRequests"
|
||||||
) as mock_html:
|
) as mock_html:
|
||||||
mock_html.send_website_request_getcode.return_value = None
|
mock_html.send_website_request_getcode.return_value = None
|
||||||
url = _get_hltb_search_url()
|
url = _get_hltb_search_url()
|
||||||
@ -99,7 +99,7 @@ class TestGetHltbSearchUrl:
|
|||||||
mock_info = MagicMock()
|
mock_info = MagicMock()
|
||||||
mock_info.search_url = "/api/search/xyz"
|
mock_info.search_url = "/api/search/xyz"
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search.HTMLRequests"
|
"steam_backlog_enforcer._hltb_search.HTMLRequests"
|
||||||
) as mock_html:
|
) as mock_html:
|
||||||
mock_html.send_website_request_getcode.side_effect = [None, mock_info]
|
mock_html.send_website_request_getcode.side_effect = [None, mock_info]
|
||||||
mock_html.BASE_URL = "https://howlongtobeat.com"
|
mock_html.BASE_URL = "https://howlongtobeat.com"
|
||||||
@ -108,7 +108,7 @@ class TestGetHltbSearchUrl:
|
|||||||
|
|
||||||
def test_exception_fallback(self) -> None:
|
def test_exception_fallback(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search.HTMLRequests"
|
"steam_backlog_enforcer._hltb_search.HTMLRequests"
|
||||||
) as mock_html:
|
) as mock_html:
|
||||||
mock_html.send_website_request_getcode.side_effect = RuntimeError
|
mock_html.send_website_request_getcode.side_effect = RuntimeError
|
||||||
url = _get_hltb_search_url()
|
url = _get_hltb_search_url()
|
||||||
|
|||||||
@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_detail import (
|
from steam_backlog_enforcer._hltb_detail import (
|
||||||
_apply_dlc_leisure_overrides,
|
_apply_dlc_leisure_overrides,
|
||||||
_as_positive_int,
|
_as_positive_int,
|
||||||
_collect_dlc_relationships,
|
_collect_dlc_relationships,
|
||||||
@ -22,7 +22,7 @@ from python_pkg.steam_backlog_enforcer._hltb_detail import (
|
|||||||
_fetch_leisure_times,
|
_fetch_leisure_times,
|
||||||
_process_game_detail,
|
_process_game_detail,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
_SAVE_INTERVAL,
|
_SAVE_INTERVAL,
|
||||||
HLTBResult,
|
HLTBResult,
|
||||||
_HLTBExtras,
|
_HLTBExtras,
|
||||||
@ -155,7 +155,7 @@ class TestInternalHelpers:
|
|||||||
async def _run() -> dict[int, float]:
|
async def _run() -> dict[int, float]:
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=None,
|
return_value=None,
|
||||||
):
|
):
|
||||||
@ -176,7 +176,7 @@ class TestInternalHelpers:
|
|||||||
async def _run() -> dict[int, float]:
|
async def _run() -> dict[int, float]:
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=bad_dlc_data,
|
return_value=bad_dlc_data,
|
||||||
):
|
):
|
||||||
@ -339,7 +339,7 @@ class TestFetchLeisureTimes:
|
|||||||
}
|
}
|
||||||
cache: dict[int, float] = {}
|
cache: dict[int, float] = {}
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=game_data,
|
return_value=game_data,
|
||||||
):
|
):
|
||||||
@ -378,7 +378,7 @@ class TestFetchLeisureTimes:
|
|||||||
]
|
]
|
||||||
cache: dict[int, float] = {}
|
cache: dict[int, float] = {}
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=None,
|
return_value=None,
|
||||||
):
|
):
|
||||||
@ -399,7 +399,7 @@ class TestFetchLeisureTimes:
|
|||||||
game_data: dict[str, Any] = {"game": [], "relationships": []}
|
game_data: dict[str, Any] = {"game": [], "relationships": []}
|
||||||
cache: dict[int, float] = {}
|
cache: dict[int, float] = {}
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=game_data,
|
return_value=game_data,
|
||||||
):
|
):
|
||||||
@ -424,7 +424,7 @@ class TestFetchLeisureTimes:
|
|||||||
cache: dict[int, float] = {}
|
cache: dict[int, float] = {}
|
||||||
cb = MagicMock()
|
cb = MagicMock()
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=game_data,
|
return_value=game_data,
|
||||||
):
|
):
|
||||||
@ -450,12 +450,12 @@ class TestFetchLeisureTimes:
|
|||||||
cache: dict[int, float] = {}
|
cache: dict[int, float] = {}
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=game_data,
|
return_value=game_data,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail.save_hltb_cache"
|
"steam_backlog_enforcer._hltb_detail.save_hltb_cache"
|
||||||
) as mock_save,
|
) as mock_save,
|
||||||
):
|
):
|
||||||
asyncio.run(_fetch_leisure_times(results, cache, {}, None))
|
asyncio.run(_fetch_leisure_times(results, cache, {}, None))
|
||||||
@ -481,7 +481,7 @@ class TestFetchLeisureTimes:
|
|||||||
}
|
}
|
||||||
cache: dict[int, float] = {}
|
cache: dict[int, float] = {}
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
side_effect=[base_data, dlc_data],
|
side_effect=[base_data, dlc_data],
|
||||||
):
|
):
|
||||||
@ -507,7 +507,7 @@ class TestFetchLeisureTimes:
|
|||||||
}
|
}
|
||||||
cache: dict[int, float] = {}
|
cache: dict[int, float] = {}
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
side_effect=[base_data, None],
|
side_effect=[base_data, None],
|
||||||
):
|
):
|
||||||
@ -535,7 +535,7 @@ class TestFetchLeisureTimes:
|
|||||||
cache: dict[int, float] = {}
|
cache: dict[int, float] = {}
|
||||||
extras = _HLTBExtras(count_comp={440: 5})
|
extras = _HLTBExtras(count_comp={440: 5})
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=game_data,
|
return_value=game_data,
|
||||||
):
|
):
|
||||||
@ -561,7 +561,7 @@ class TestFetchLeisureTimes:
|
|||||||
cache: dict[int, float] = {}
|
cache: dict[int, float] = {}
|
||||||
extras = _HLTBExtras(count_comp={440: 5})
|
extras = _HLTBExtras(count_comp={440: 5})
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
"steam_backlog_enforcer._hltb_detail._fetch_detail_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=game_data,
|
return_value=game_data,
|
||||||
):
|
):
|
||||||
|
|||||||
@ -8,8 +8,8 @@ from unittest.mock import MagicMock, patch
|
|||||||
|
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_search import _AuthInfo
|
from steam_backlog_enforcer._hltb_search import _AuthInfo
|
||||||
from python_pkg.steam_backlog_enforcer.hltb import (
|
from steam_backlog_enforcer.hltb import (
|
||||||
HLTB_BASE_URL,
|
HLTB_BASE_URL,
|
||||||
HLTBResult,
|
HLTBResult,
|
||||||
_fetch_batch_confidence_only,
|
_fetch_batch_confidence_only,
|
||||||
@ -21,9 +21,9 @@ from python_pkg.steam_backlog_enforcer.hltb import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_types import _HLTBExtras
|
from steam_backlog_enforcer._hltb_types import _HLTBExtras
|
||||||
|
|
||||||
PKG = "python_pkg.steam_backlog_enforcer.hltb"
|
PKG = "steam_backlog_enforcer.hltb"
|
||||||
|
|
||||||
|
|
||||||
class TestFetchHltbTimesCached:
|
class TestFetchHltbTimesCached:
|
||||||
|
|||||||
@ -4,7 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.hltb import (
|
from steam_backlog_enforcer.hltb import (
|
||||||
HLTBResult,
|
HLTBResult,
|
||||||
fetch_hltb_times,
|
fetch_hltb_times,
|
||||||
)
|
)
|
||||||
@ -21,7 +21,7 @@ class TestFetchHltbTimes:
|
|||||||
app_id=440, game_name="TF2", completionist_hours=50.0, similarity=1.0
|
app_id=440, game_name="TF2", completionist_hours=50.0, similarity=1.0
|
||||||
)
|
)
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.hltb._fetch_batch",
|
"steam_backlog_enforcer.hltb._fetch_batch",
|
||||||
return_value=[mock_result],
|
return_value=[mock_result],
|
||||||
):
|
):
|
||||||
results = fetch_hltb_times([(440, "TF2")])
|
results = fetch_hltb_times([(440, "TF2")])
|
||||||
@ -29,7 +29,7 @@ class TestFetchHltbTimes:
|
|||||||
|
|
||||||
def test_none_cache(self) -> None:
|
def test_none_cache(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.hltb._fetch_batch",
|
"steam_backlog_enforcer.hltb._fetch_batch",
|
||||||
return_value=[],
|
return_value=[],
|
||||||
):
|
):
|
||||||
results = fetch_hltb_times([(440, "TF2")])
|
results = fetch_hltb_times([(440, "TF2")])
|
||||||
@ -37,7 +37,7 @@ class TestFetchHltbTimes:
|
|||||||
|
|
||||||
def test_explicit_cache(self) -> None:
|
def test_explicit_cache(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.hltb._fetch_batch",
|
"steam_backlog_enforcer.hltb._fetch_batch",
|
||||||
return_value=[],
|
return_value=[],
|
||||||
):
|
):
|
||||||
cache: dict[int, float] = {440: 10.0}
|
cache: dict[int, float] = {440: 10.0}
|
||||||
|
|||||||
@ -9,12 +9,12 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_search import (
|
from steam_backlog_enforcer._hltb_search import (
|
||||||
_fetch_batch,
|
_fetch_batch,
|
||||||
_search_one,
|
_search_one,
|
||||||
_SearchCtx,
|
_SearchCtx,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
_SAVE_INTERVAL,
|
_SAVE_INTERVAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ class TestSearchOne:
|
|||||||
|
|
||||||
ctx.counter["done"] = _SAVE_INTERVAL - 1
|
ctx.counter["done"] = _SAVE_INTERVAL - 1
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search.save_hltb_cache"
|
"steam_backlog_enforcer._hltb_search.save_hltb_cache"
|
||||||
) as mock_save:
|
) as mock_save:
|
||||||
asyncio.run(_search_one(asyncio.Semaphore(1), ctx, 440, "TF2"))
|
asyncio.run(_search_one(asyncio.Semaphore(1), ctx, 440, "TF2"))
|
||||||
mock_save.assert_called_once()
|
mock_save.assert_called_once()
|
||||||
@ -272,11 +272,11 @@ class TestFetchBatchHltb:
|
|||||||
def test_no_auth(self) -> None:
|
def test_no_auth(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._get_hltb_search_url",
|
"steam_backlog_enforcer._hltb_search._get_hltb_search_url",
|
||||||
return_value="https://example.com",
|
return_value="https://example.com",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._get_auth_info",
|
"steam_backlog_enforcer._hltb_search._get_auth_info",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=None,
|
return_value=None,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -9,16 +9,16 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||||||
|
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_detail import (
|
from steam_backlog_enforcer._hltb_detail import (
|
||||||
_extract_leisure_hours,
|
_extract_leisure_hours,
|
||||||
_parse_game_page,
|
_parse_game_page,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_search import (
|
from steam_backlog_enforcer._hltb_search import (
|
||||||
_build_search_variants,
|
_build_search_variants,
|
||||||
_fetch_batch,
|
_fetch_batch,
|
||||||
_pick_best_hltb_entry,
|
_pick_best_hltb_entry,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
HLTBResult,
|
HLTBResult,
|
||||||
_AuthInfo,
|
_AuthInfo,
|
||||||
)
|
)
|
||||||
@ -110,16 +110,16 @@ class TestPickBestEntry:
|
|||||||
auth = _AuthInfo("token123", "ign_x", "ff")
|
auth = _AuthInfo("token123", "ign_x", "ff")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._get_hltb_search_url",
|
"steam_backlog_enforcer._hltb_search._get_hltb_search_url",
|
||||||
return_value="https://example.com",
|
return_value="https://example.com",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._get_auth_info",
|
"steam_backlog_enforcer._hltb_search._get_auth_info",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=auth,
|
return_value=auth,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._search_one",
|
"steam_backlog_enforcer._hltb_search._search_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=HLTBResult(
|
return_value=HLTBResult(
|
||||||
app_id=440,
|
app_id=440,
|
||||||
@ -130,7 +130,7 @@ class TestPickBestEntry:
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._fetch_leisure_times",
|
"steam_backlog_enforcer._hltb_search._fetch_leisure_times",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -141,21 +141,21 @@ class TestPickBestEntry:
|
|||||||
auth = _AuthInfo("tok123")
|
auth = _AuthInfo("tok123")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._get_hltb_search_url",
|
"steam_backlog_enforcer._hltb_search._get_hltb_search_url",
|
||||||
return_value="https://example.com",
|
return_value="https://example.com",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._get_auth_info",
|
"steam_backlog_enforcer._hltb_search._get_auth_info",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=auth,
|
return_value=auth,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._search_one",
|
"steam_backlog_enforcer._hltb_search._search_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=None,
|
return_value=None,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._fetch_leisure_times",
|
"steam_backlog_enforcer._hltb_search._fetch_leisure_times",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -166,21 +166,21 @@ class TestPickBestEntry:
|
|||||||
auth = _AuthInfo("tok123")
|
auth = _AuthInfo("tok123")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._get_hltb_search_url",
|
"steam_backlog_enforcer._hltb_search._get_hltb_search_url",
|
||||||
return_value="https://example.com",
|
return_value="https://example.com",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._get_auth_info",
|
"steam_backlog_enforcer._hltb_search._get_auth_info",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=auth,
|
return_value=auth,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._search_one",
|
"steam_backlog_enforcer._hltb_search._search_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=None,
|
return_value=None,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._hltb_search._fetch_leisure_times",
|
"steam_backlog_enforcer._hltb_search._fetch_leisure_times",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.library_hider import (
|
from steam_backlog_enforcer.library_hider import (
|
||||||
_cdp_result_value,
|
_cdp_result_value,
|
||||||
_evaluate_js,
|
_evaluate_js,
|
||||||
_evaluate_js_async,
|
_evaluate_js_async,
|
||||||
@ -37,7 +37,7 @@ class TestGetSharedJsWsUrl:
|
|||||||
mock_resp = MagicMock()
|
mock_resp = MagicMock()
|
||||||
mock_resp.json.return_value = targets
|
mock_resp.json.return_value = targets
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.requests.get",
|
"steam_backlog_enforcer.library_hider.requests.get",
|
||||||
return_value=mock_resp,
|
return_value=mock_resp,
|
||||||
):
|
):
|
||||||
result = _get_shared_js_ws_url()
|
result = _get_shared_js_ws_url()
|
||||||
@ -48,14 +48,14 @@ class TestGetSharedJsWsUrl:
|
|||||||
mock_resp = MagicMock()
|
mock_resp = MagicMock()
|
||||||
mock_resp.json.return_value = targets
|
mock_resp.json.return_value = targets
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.requests.get",
|
"steam_backlog_enforcer.library_hider.requests.get",
|
||||||
return_value=mock_resp,
|
return_value=mock_resp,
|
||||||
):
|
):
|
||||||
assert _get_shared_js_ws_url() is None
|
assert _get_shared_js_ws_url() is None
|
||||||
|
|
||||||
def test_connection_error(self) -> None:
|
def test_connection_error(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.requests.get",
|
"steam_backlog_enforcer.library_hider.requests.get",
|
||||||
side_effect=OSError,
|
side_effect=OSError,
|
||||||
):
|
):
|
||||||
assert _get_shared_js_ws_url() is None
|
assert _get_shared_js_ws_url() is None
|
||||||
@ -74,7 +74,7 @@ class TestEvaluateJsAsync:
|
|||||||
mock_ws.__aexit__ = AsyncMock(return_value=False)
|
mock_ws.__aexit__ = AsyncMock(return_value=False)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.websockets.connect",
|
"steam_backlog_enforcer.library_hider.websockets.connect",
|
||||||
return_value=mock_ws,
|
return_value=mock_ws,
|
||||||
):
|
):
|
||||||
result = asyncio.run(_evaluate_js_async("ws://test", "1+1"))
|
result = asyncio.run(_evaluate_js_async("ws://test", "1+1"))
|
||||||
@ -87,11 +87,11 @@ class TestEvaluateJs:
|
|||||||
def test_success(self) -> None:
|
def test_success(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
"steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
||||||
return_value="ws://test",
|
return_value="ws://test",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.asyncio.run",
|
"steam_backlog_enforcer.library_hider.asyncio.run",
|
||||||
return_value={"result": {"result": {"value": "ok"}}},
|
return_value={"result": {"result": {"value": "ok"}}},
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -101,7 +101,7 @@ class TestEvaluateJs:
|
|||||||
def test_no_ws_url(self) -> None:
|
def test_no_ws_url(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
"steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
||||||
return_value=None,
|
return_value=None,
|
||||||
),
|
),
|
||||||
pytest.raises(RuntimeError, match="SharedJSContext not found"),
|
pytest.raises(RuntimeError, match="SharedJSContext not found"),
|
||||||
@ -136,7 +136,7 @@ class TestIsSteamRunning:
|
|||||||
def test_running(self) -> None:
|
def test_running(self) -> None:
|
||||||
mock_result = MagicMock(returncode=0)
|
mock_result = MagicMock(returncode=0)
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.subprocess.run",
|
"steam_backlog_enforcer.library_hider.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
):
|
):
|
||||||
assert _is_steam_running() is True
|
assert _is_steam_running() is True
|
||||||
@ -144,7 +144,7 @@ class TestIsSteamRunning:
|
|||||||
def test_not_running(self) -> None:
|
def test_not_running(self) -> None:
|
||||||
mock_result = MagicMock(returncode=1)
|
mock_result = MagicMock(returncode=1)
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.subprocess.run",
|
"steam_backlog_enforcer.library_hider.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
):
|
):
|
||||||
assert _is_steam_running() is False
|
assert _is_steam_running() is False
|
||||||
@ -155,14 +155,14 @@ class TestSteamHasDebugPort:
|
|||||||
|
|
||||||
def test_has_port(self) -> None:
|
def test_has_port(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
"steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
||||||
return_value="ws://test",
|
return_value="ws://test",
|
||||||
):
|
):
|
||||||
assert _steam_has_debug_port() is True
|
assert _steam_has_debug_port() is True
|
||||||
|
|
||||||
def test_no_port(self) -> None:
|
def test_no_port(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
"steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
||||||
return_value=None,
|
return_value=None,
|
||||||
):
|
):
|
||||||
assert _steam_has_debug_port() is False
|
assert _steam_has_debug_port() is False
|
||||||
@ -173,7 +173,7 @@ class TestWaitForCdpReady:
|
|||||||
|
|
||||||
def test_ready_immediately(self) -> None:
|
def test_ready_immediately(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
"steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
||||||
return_value="ws://test",
|
return_value="ws://test",
|
||||||
):
|
):
|
||||||
assert _wait_for_cdp_ready() is True
|
assert _wait_for_cdp_ready() is True
|
||||||
@ -181,14 +181,14 @@ class TestWaitForCdpReady:
|
|||||||
def test_timeout(self) -> None:
|
def test_timeout(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
"steam_backlog_enforcer.library_hider._get_shared_js_ws_url",
|
||||||
return_value=None,
|
return_value=None,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.time.sleep",
|
"steam_backlog_enforcer.library_hider.time.sleep",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._STEAM_STARTUP_WAIT",
|
"steam_backlog_enforcer.library_hider._STEAM_STARTUP_WAIT",
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -201,11 +201,11 @@ class TestWaitForCollectionsReady:
|
|||||||
def test_ready(self) -> None:
|
def test_ready(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._evaluate_js",
|
"steam_backlog_enforcer.library_hider._evaluate_js",
|
||||||
return_value={"result": {"result": {"value": "ok"}}},
|
return_value={"result": {"result": {"value": "ok"}}},
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._cdp_result_value",
|
"steam_backlog_enforcer.library_hider._cdp_result_value",
|
||||||
return_value="ok",
|
return_value="ok",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -214,18 +214,18 @@ class TestWaitForCollectionsReady:
|
|||||||
def test_not_ready_then_ready(self) -> None:
|
def test_not_ready_then_ready(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._evaluate_js",
|
"steam_backlog_enforcer.library_hider._evaluate_js",
|
||||||
return_value={"result": {"result": {"value": "not_ready"}}},
|
return_value={"result": {"result": {"value": "not_ready"}}},
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._cdp_result_value",
|
"steam_backlog_enforcer.library_hider._cdp_result_value",
|
||||||
side_effect=["not_ready", "ok"],
|
side_effect=["not_ready", "ok"],
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.time.sleep",
|
"steam_backlog_enforcer.library_hider.time.sleep",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._STEAM_STARTUP_WAIT",
|
"steam_backlog_enforcer.library_hider._STEAM_STARTUP_WAIT",
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -234,14 +234,14 @@ class TestWaitForCollectionsReady:
|
|||||||
def test_timeout(self) -> None:
|
def test_timeout(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._evaluate_js",
|
"steam_backlog_enforcer.library_hider._evaluate_js",
|
||||||
side_effect=RuntimeError,
|
side_effect=RuntimeError,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.time.sleep",
|
"steam_backlog_enforcer.library_hider.time.sleep",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._STEAM_STARTUP_WAIT",
|
"steam_backlog_enforcer.library_hider._STEAM_STARTUP_WAIT",
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -255,10 +255,10 @@ class TestShutdownSteam:
|
|||||||
mock_result = MagicMock(returncode=1) # Not running
|
mock_result = MagicMock(returncode=1) # Not running
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._run_as_user",
|
"steam_backlog_enforcer.library_hider._run_as_user",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.subprocess.run",
|
"steam_backlog_enforcer.library_hider.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -268,21 +268,21 @@ class TestShutdownSteam:
|
|||||||
results = [MagicMock(returncode=0), MagicMock(returncode=1)]
|
results = [MagicMock(returncode=0), MagicMock(returncode=1)]
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._run_as_user",
|
"steam_backlog_enforcer.library_hider._run_as_user",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.subprocess.run",
|
"steam_backlog_enforcer.library_hider.subprocess.run",
|
||||||
side_effect=results,
|
side_effect=results,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.time.sleep",
|
"steam_backlog_enforcer.library_hider.time.sleep",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
_shutdown_steam()
|
_shutdown_steam()
|
||||||
|
|
||||||
def test_file_not_found(self) -> None:
|
def test_file_not_found(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._run_as_user",
|
"steam_backlog_enforcer.library_hider._run_as_user",
|
||||||
side_effect=FileNotFoundError,
|
side_effect=FileNotFoundError,
|
||||||
):
|
):
|
||||||
_shutdown_steam() # Should not raise
|
_shutdown_steam() # Should not raise
|
||||||
@ -291,14 +291,14 @@ class TestShutdownSteam:
|
|||||||
mock_result = MagicMock(returncode=0) # Still running
|
mock_result = MagicMock(returncode=0) # Still running
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._run_as_user",
|
"steam_backlog_enforcer.library_hider._run_as_user",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.subprocess.run",
|
"steam_backlog_enforcer.library_hider.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider.time.sleep",
|
"steam_backlog_enforcer.library_hider.time.sleep",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
_shutdown_steam() # Should complete loop without raising
|
_shutdown_steam() # Should complete loop without raising
|
||||||
@ -309,7 +309,7 @@ class TestLaunchSteamWithDebug:
|
|||||||
|
|
||||||
def test_launches(self) -> None:
|
def test_launches(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._run_as_user",
|
"steam_backlog_enforcer.library_hider._run_as_user",
|
||||||
) as mock_run:
|
) as mock_run:
|
||||||
_launch_steam_with_debug()
|
_launch_steam_with_debug()
|
||||||
mock_run.assert_called_once()
|
mock_run.assert_called_once()
|
||||||
@ -320,7 +320,7 @@ class TestEnsureSteamDebugPort:
|
|||||||
|
|
||||||
def test_already_available(self) -> None:
|
def test_already_available(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._steam_has_debug_port",
|
"steam_backlog_enforcer.library_hider._steam_has_debug_port",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
):
|
):
|
||||||
ensure_steam_debug_port()
|
ensure_steam_debug_port()
|
||||||
@ -328,22 +328,22 @@ class TestEnsureSteamDebugPort:
|
|||||||
def test_starts_fresh(self) -> None:
|
def test_starts_fresh(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._steam_has_debug_port",
|
"steam_backlog_enforcer.library_hider._steam_has_debug_port",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._is_steam_running",
|
"steam_backlog_enforcer.library_hider._is_steam_running",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._launch_steam_with_debug",
|
"steam_backlog_enforcer.library_hider._launch_steam_with_debug",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._wait_for_cdp_ready",
|
"steam_backlog_enforcer.library_hider._wait_for_cdp_ready",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._wait_for_collections_ready",
|
"steam_backlog_enforcer.library_hider._wait_for_collections_ready",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -352,25 +352,25 @@ class TestEnsureSteamDebugPort:
|
|||||||
def test_restarts_running_steam(self) -> None:
|
def test_restarts_running_steam(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._steam_has_debug_port",
|
"steam_backlog_enforcer.library_hider._steam_has_debug_port",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._is_steam_running",
|
"steam_backlog_enforcer.library_hider._is_steam_running",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._shutdown_steam",
|
"steam_backlog_enforcer.library_hider._shutdown_steam",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._launch_steam_with_debug",
|
"steam_backlog_enforcer.library_hider._launch_steam_with_debug",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._wait_for_cdp_ready",
|
"steam_backlog_enforcer.library_hider._wait_for_cdp_ready",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._wait_for_collections_ready",
|
"steam_backlog_enforcer.library_hider._wait_for_collections_ready",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -379,18 +379,18 @@ class TestEnsureSteamDebugPort:
|
|||||||
def test_cdp_timeout(self) -> None:
|
def test_cdp_timeout(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._steam_has_debug_port",
|
"steam_backlog_enforcer.library_hider._steam_has_debug_port",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._is_steam_running",
|
"steam_backlog_enforcer.library_hider._is_steam_running",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._launch_steam_with_debug",
|
"steam_backlog_enforcer.library_hider._launch_steam_with_debug",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._wait_for_cdp_ready",
|
"steam_backlog_enforcer.library_hider._wait_for_cdp_ready",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
pytest.raises(RuntimeError, match="Timed out waiting for Steam CDP"),
|
pytest.raises(RuntimeError, match="Timed out waiting for Steam CDP"),
|
||||||
@ -400,22 +400,22 @@ class TestEnsureSteamDebugPort:
|
|||||||
def test_collections_timeout(self) -> None:
|
def test_collections_timeout(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._steam_has_debug_port",
|
"steam_backlog_enforcer.library_hider._steam_has_debug_port",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._is_steam_running",
|
"steam_backlog_enforcer.library_hider._is_steam_running",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._launch_steam_with_debug",
|
"steam_backlog_enforcer.library_hider._launch_steam_with_debug",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._wait_for_cdp_ready",
|
"steam_backlog_enforcer.library_hider._wait_for_cdp_ready",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.library_hider._wait_for_collections_ready",
|
"steam_backlog_enforcer.library_hider._wait_for_collections_ready",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
pytest.raises(
|
pytest.raises(
|
||||||
|
|||||||
@ -6,14 +6,14 @@ import os
|
|||||||
import tempfile
|
import tempfile
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.library_hider import (
|
from steam_backlog_enforcer.library_hider import (
|
||||||
_run_as_user,
|
_run_as_user,
|
||||||
hide_other_games,
|
hide_other_games,
|
||||||
restart_steam,
|
restart_steam,
|
||||||
unhide_all_games,
|
unhide_all_games,
|
||||||
)
|
)
|
||||||
|
|
||||||
PKG = "python_pkg.steam_backlog_enforcer.library_hider"
|
PKG = "steam_backlog_enforcer.library_hider"
|
||||||
|
|
||||||
|
|
||||||
class TestRunAsUser:
|
class TestRunAsUser:
|
||||||
|
|||||||
@ -9,9 +9,9 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._whitelist import WHITELIST_COOLDOWN_SECONDS
|
from steam_backlog_enforcer._whitelist import WHITELIST_COOLDOWN_SECONDS
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
from python_pkg.steam_backlog_enforcer.main import (
|
from steam_backlog_enforcer.main import (
|
||||||
cmd_add_exception,
|
cmd_add_exception,
|
||||||
cmd_buy_dlc,
|
cmd_buy_dlc,
|
||||||
cmd_hide,
|
cmd_hide,
|
||||||
@ -27,7 +27,7 @@ from python_pkg.steam_backlog_enforcer.main import (
|
|||||||
main,
|
main,
|
||||||
)
|
)
|
||||||
|
|
||||||
PKG = "python_pkg.steam_backlog_enforcer.main"
|
PKG = "steam_backlog_enforcer.main"
|
||||||
|
|
||||||
|
|
||||||
def _snap(
|
def _snap(
|
||||||
|
|||||||
@ -5,16 +5,16 @@ from __future__ import annotations
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._cmd_done import (
|
from steam_backlog_enforcer._cmd_done import (
|
||||||
_enforce_on_done,
|
_enforce_on_done,
|
||||||
_finalize_completion,
|
_finalize_completion,
|
||||||
cmd_done,
|
cmd_done,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
CMD_DONE_PKG = "python_pkg.steam_backlog_enforcer._cmd_done"
|
CMD_DONE_PKG = "steam_backlog_enforcer._cmd_done"
|
||||||
PKG = "python_pkg.steam_backlog_enforcer.main"
|
PKG = "steam_backlog_enforcer.main"
|
||||||
|
|
||||||
|
|
||||||
def _snap(
|
def _snap(
|
||||||
|
|||||||
@ -8,15 +8,15 @@ from unittest.mock import MagicMock, patch
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._cmd_done import (
|
from steam_backlog_enforcer._cmd_done import (
|
||||||
cmd_done,
|
cmd_done,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
from python_pkg.steam_backlog_enforcer.main import cmd_pick, main
|
from steam_backlog_enforcer.main import cmd_pick, main
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
CMD_DONE_PKG = "python_pkg.steam_backlog_enforcer._cmd_done"
|
CMD_DONE_PKG = "steam_backlog_enforcer._cmd_done"
|
||||||
PKG = "python_pkg.steam_backlog_enforcer.main"
|
PKG = "steam_backlog_enforcer.main"
|
||||||
|
|
||||||
|
|
||||||
def _snap(
|
def _snap(
|
||||||
|
|||||||
@ -6,8 +6,8 @@ import json
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer import _cmd_done
|
from steam_backlog_enforcer import _cmd_done
|
||||||
from python_pkg.steam_backlog_enforcer._hltb_types import (
|
from steam_backlog_enforcer._hltb_types import (
|
||||||
HLTBResult,
|
HLTBResult,
|
||||||
_HLTBExtras,
|
_HLTBExtras,
|
||||||
load_hltb_cache,
|
load_hltb_cache,
|
||||||
@ -16,15 +16,15 @@ from python_pkg.steam_backlog_enforcer._hltb_types import (
|
|||||||
load_hltb_polls_cache,
|
load_hltb_polls_cache,
|
||||||
save_hltb_cache,
|
save_hltb_cache,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import State
|
from steam_backlog_enforcer.config import State
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
_TYPES = "python_pkg.steam_backlog_enforcer._hltb_types"
|
_TYPES = "steam_backlog_enforcer._hltb_types"
|
||||||
_CMD = "python_pkg.steam_backlog_enforcer._cmd_done"
|
_CMD = "steam_backlog_enforcer._cmd_done"
|
||||||
_SCAN = "python_pkg.steam_backlog_enforcer.scanning"
|
_SCAN = "steam_backlog_enforcer.scanning"
|
||||||
|
|
||||||
|
|
||||||
class TestCacheSchema:
|
class TestCacheSchema:
|
||||||
|
|||||||
@ -6,17 +6,17 @@ import json
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer import _cmd_done, _scanning_confidence, scanning
|
from steam_backlog_enforcer import _cmd_done, _scanning_confidence, scanning
|
||||||
from python_pkg.steam_backlog_enforcer.config import State
|
from steam_backlog_enforcer.config import State
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
_TYPES = "python_pkg.steam_backlog_enforcer._hltb_types"
|
_TYPES = "steam_backlog_enforcer._hltb_types"
|
||||||
_CMD = "python_pkg.steam_backlog_enforcer._cmd_done"
|
_CMD = "steam_backlog_enforcer._cmd_done"
|
||||||
_SCAN = "python_pkg.steam_backlog_enforcer.scanning"
|
_SCAN = "steam_backlog_enforcer.scanning"
|
||||||
_SCANCONF = "python_pkg.steam_backlog_enforcer._scanning_confidence"
|
_SCANCONF = "steam_backlog_enforcer._scanning_confidence"
|
||||||
|
|
||||||
|
|
||||||
def _state(finished: list[int], current: int | None = None) -> State:
|
def _state(finished: list[int], current: int | None = None) -> State:
|
||||||
@ -231,8 +231,8 @@ class TestScanningPollsIntegration:
|
|||||||
|
|
||||||
def test_do_scan_kept_assignment_missing_game(self) -> None:
|
def test_do_scan_kept_assignment_missing_game(self) -> None:
|
||||||
"""Covers scanning.py 110->116: current_app_id set but game absent."""
|
"""Covers scanning.py 110->116: current_app_id set but game absent."""
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config
|
from steam_backlog_enforcer.config import Config
|
||||||
from python_pkg.steam_backlog_enforcer.scanning import do_scan
|
from steam_backlog_enforcer.scanning import do_scan
|
||||||
|
|
||||||
other = GameInfo(
|
other = GameInfo(
|
||||||
app_id=999,
|
app_id=999,
|
||||||
|
|||||||
@ -9,7 +9,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.protondb import (
|
from steam_backlog_enforcer.protondb import (
|
||||||
HTTP_NOT_FOUND,
|
HTTP_NOT_FOUND,
|
||||||
ProtonDBRating,
|
ProtonDBRating,
|
||||||
_fetch_batch,
|
_fetch_batch,
|
||||||
@ -116,7 +116,7 @@ class TestProtonDBCache:
|
|||||||
cache_file = tmp_path / "protondb_cache.json"
|
cache_file = tmp_path / "protondb_cache.json"
|
||||||
cache_file.write_text(json.dumps({"440": {"tier": "gold"}}), encoding="utf-8")
|
cache_file.write_text(json.dumps({"440": {"tier": "gold"}}), encoding="utf-8")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.protondb.PROTONDB_CACHE_FILE",
|
"steam_backlog_enforcer.protondb.PROTONDB_CACHE_FILE",
|
||||||
cache_file,
|
cache_file,
|
||||||
):
|
):
|
||||||
result = _load_cache()
|
result = _load_cache()
|
||||||
@ -125,7 +125,7 @@ class TestProtonDBCache:
|
|||||||
def test_load_cache_missing(self, tmp_path: Path) -> None:
|
def test_load_cache_missing(self, tmp_path: Path) -> None:
|
||||||
cache_file = tmp_path / "nonexistent.json"
|
cache_file = tmp_path / "nonexistent.json"
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.protondb.PROTONDB_CACHE_FILE",
|
"steam_backlog_enforcer.protondb.PROTONDB_CACHE_FILE",
|
||||||
cache_file,
|
cache_file,
|
||||||
):
|
):
|
||||||
assert _load_cache() == {}
|
assert _load_cache() == {}
|
||||||
@ -135,10 +135,10 @@ class TestProtonDBCache:
|
|||||||
config_dir = tmp_path
|
config_dir = tmp_path
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.protondb.PROTONDB_CACHE_FILE",
|
"steam_backlog_enforcer.protondb.PROTONDB_CACHE_FILE",
|
||||||
cache_file,
|
cache_file,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.protondb.CONFIG_DIR", config_dir),
|
patch("steam_backlog_enforcer.protondb.CONFIG_DIR", config_dir),
|
||||||
):
|
):
|
||||||
_save_cache({"440": {"tier": "gold"}})
|
_save_cache({"440": {"tier": "gold"}})
|
||||||
assert cache_file.exists()
|
assert cache_file.exists()
|
||||||
@ -231,7 +231,7 @@ class TestFetchBatch:
|
|||||||
def test_returns_ratings(self) -> None:
|
def test_returns_ratings(self) -> None:
|
||||||
rating = ProtonDBRating(app_id=440, tier="gold")
|
rating = ProtonDBRating(app_id=440, tier="gold")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.protondb._fetch_one",
|
"steam_backlog_enforcer.protondb._fetch_one",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=rating,
|
return_value=rating,
|
||||||
):
|
):
|
||||||
@ -251,7 +251,7 @@ class TestFetchBatch:
|
|||||||
return rating if app_id == 440 else None
|
return rating if app_id == 440 else None
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.protondb._fetch_one",
|
"steam_backlog_enforcer.protondb._fetch_one",
|
||||||
side_effect=mock_fetch_one,
|
side_effect=mock_fetch_one,
|
||||||
):
|
):
|
||||||
result = asyncio.run(_fetch_batch([440, 999]))
|
result = asyncio.run(_fetch_batch([440, 999]))
|
||||||
@ -266,7 +266,7 @@ class TestFetchProtondbRatings:
|
|||||||
cache_file = tmp_path / "protondb_cache.json"
|
cache_file = tmp_path / "protondb_cache.json"
|
||||||
cache_file.write_text(json.dumps({"440": {"tier": "gold"}}), encoding="utf-8")
|
cache_file.write_text(json.dumps({"440": {"tier": "gold"}}), encoding="utf-8")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.protondb.PROTONDB_CACHE_FILE",
|
"steam_backlog_enforcer.protondb.PROTONDB_CACHE_FILE",
|
||||||
cache_file,
|
cache_file,
|
||||||
):
|
):
|
||||||
result = fetch_protondb_ratings([440])
|
result = fetch_protondb_ratings([440])
|
||||||
@ -278,12 +278,12 @@ class TestFetchProtondbRatings:
|
|||||||
config_dir = tmp_path
|
config_dir = tmp_path
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.protondb.PROTONDB_CACHE_FILE",
|
"steam_backlog_enforcer.protondb.PROTONDB_CACHE_FILE",
|
||||||
cache_file,
|
cache_file,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.protondb.CONFIG_DIR", config_dir),
|
patch("steam_backlog_enforcer.protondb.CONFIG_DIR", config_dir),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.protondb._fetch_batch",
|
"steam_backlog_enforcer.protondb._fetch_batch",
|
||||||
return_value=[ProtonDBRating(app_id=440, tier="platinum")],
|
return_value=[ProtonDBRating(app_id=440, tier="platinum")],
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
|
|||||||
@ -5,14 +5,14 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
from python_pkg.steam_backlog_enforcer.protondb import ProtonDBRating
|
from steam_backlog_enforcer.protondb import ProtonDBRating
|
||||||
from python_pkg.steam_backlog_enforcer.scanning import (
|
from steam_backlog_enforcer.scanning import (
|
||||||
_pick_playable_candidate,
|
_pick_playable_candidate,
|
||||||
do_scan,
|
do_scan,
|
||||||
pick_next_game,
|
pick_next_game,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
@ -56,24 +56,24 @@ class TestDoScan:
|
|||||||
mock_client.build_game_list.side_effect = build_game_list
|
mock_client.build_game_list.side_effect = build_game_list
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.SteamAPIClient",
|
"steam_backlog_enforcer.scanning.SteamAPIClient",
|
||||||
return_value=mock_client,
|
return_value=mock_client,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.fetch_hltb_times_cached",
|
"steam_backlog_enforcer.scanning.fetch_hltb_times_cached",
|
||||||
side_effect=lambda _games, progress_cb=None: (
|
side_effect=lambda _games, progress_cb=None: (
|
||||||
progress_cb(1, 1, 1, "TF2") if progress_cb else None,
|
progress_cb(1, 1, 1, "TF2") if progress_cb else None,
|
||||||
{440: 20.0},
|
{440: 20.0},
|
||||||
)[1],
|
)[1],
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.save_snapshot",
|
"steam_backlog_enforcer.scanning.save_snapshot",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.pick_next_game",
|
"steam_backlog_enforcer.scanning.pick_next_game",
|
||||||
) as mock_pick,
|
) as mock_pick,
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._echo",
|
"steam_backlog_enforcer.scanning._echo",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
config = Config(steam_api_key="k", steam_id="i")
|
config = Config(steam_api_key="k", steam_id="i")
|
||||||
@ -97,16 +97,16 @@ class TestDoScan:
|
|||||||
mock_client.build_game_list.side_effect = build_game_list
|
mock_client.build_game_list.side_effect = build_game_list
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.SteamAPIClient",
|
"steam_backlog_enforcer.scanning.SteamAPIClient",
|
||||||
return_value=mock_client,
|
return_value=mock_client,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.save_snapshot",
|
"steam_backlog_enforcer.scanning.save_snapshot",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.pick_next_game",
|
"steam_backlog_enforcer.scanning.pick_next_game",
|
||||||
) as mock_pick,
|
) as mock_pick,
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
):
|
):
|
||||||
config = Config(steam_api_key="k", steam_id="i")
|
config = Config(steam_api_key="k", steam_id="i")
|
||||||
state = State()
|
state = State()
|
||||||
@ -120,20 +120,20 @@ class TestDoScan:
|
|||||||
mock_client.build_game_list.return_value = [game]
|
mock_client.build_game_list.return_value = [game]
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.SteamAPIClient",
|
"steam_backlog_enforcer.scanning.SteamAPIClient",
|
||||||
return_value=mock_client,
|
return_value=mock_client,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.fetch_hltb_times_cached",
|
"steam_backlog_enforcer.scanning.fetch_hltb_times_cached",
|
||||||
return_value={440: 20.0},
|
return_value={440: 20.0},
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.save_snapshot",
|
"steam_backlog_enforcer.scanning.save_snapshot",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.pick_next_game",
|
"steam_backlog_enforcer.scanning.pick_next_game",
|
||||||
) as mock_pick,
|
) as mock_pick,
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
):
|
):
|
||||||
config = Config(steam_api_key="k", steam_id="i")
|
config = Config(steam_api_key="k", steam_id="i")
|
||||||
state = State(current_app_id=440)
|
state = State(current_app_id=440)
|
||||||
@ -149,12 +149,12 @@ class TestPickPlayableCandidate:
|
|||||||
game = _game(app_id=440, name="TF2")
|
game = _game(app_id=440, name="TF2")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.fetch_protondb_ratings",
|
"steam_backlog_enforcer.scanning.fetch_protondb_ratings",
|
||||||
return_value={
|
return_value={
|
||||||
440: ProtonDBRating(app_id=440, tier="gold"),
|
440: ProtonDBRating(app_id=440, tier="gold"),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
):
|
):
|
||||||
result = _pick_playable_candidate([game])
|
result = _pick_playable_candidate([game])
|
||||||
assert result is not None
|
assert result is not None
|
||||||
@ -165,13 +165,13 @@ class TestPickPlayableCandidate:
|
|||||||
good = _game(app_id=2, name="Good")
|
good = _game(app_id=2, name="Good")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.fetch_protondb_ratings",
|
"steam_backlog_enforcer.scanning.fetch_protondb_ratings",
|
||||||
return_value={
|
return_value={
|
||||||
1: ProtonDBRating(app_id=1, tier="borked"),
|
1: ProtonDBRating(app_id=1, tier="borked"),
|
||||||
2: ProtonDBRating(app_id=2, tier="platinum"),
|
2: ProtonDBRating(app_id=2, tier="platinum"),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
):
|
):
|
||||||
result = _pick_playable_candidate([bad, good])
|
result = _pick_playable_candidate([bad, good])
|
||||||
assert result is not None
|
assert result is not None
|
||||||
@ -181,12 +181,12 @@ class TestPickPlayableCandidate:
|
|||||||
game = _game(app_id=1, name="Bad")
|
game = _game(app_id=1, name="Bad")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.fetch_protondb_ratings",
|
"steam_backlog_enforcer.scanning.fetch_protondb_ratings",
|
||||||
return_value={
|
return_value={
|
||||||
1: ProtonDBRating(app_id=1, tier="borked"),
|
1: ProtonDBRating(app_id=1, tier="borked"),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
):
|
):
|
||||||
assert _pick_playable_candidate([game]) is None
|
assert _pick_playable_candidate([game]) is None
|
||||||
|
|
||||||
@ -198,12 +198,12 @@ class TestPickPlayableCandidate:
|
|||||||
game = _game(app_id=440, name="TF2")
|
game = _game(app_id=440, name="TF2")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.fetch_protondb_ratings",
|
"steam_backlog_enforcer.scanning.fetch_protondb_ratings",
|
||||||
return_value={
|
return_value={
|
||||||
440: ProtonDBRating(app_id=440, tier="platinum"),
|
440: ProtonDBRating(app_id=440, tier="platinum"),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
):
|
):
|
||||||
result = _pick_playable_candidate([game])
|
result = _pick_playable_candidate([game])
|
||||||
assert result is not None
|
assert result is not None
|
||||||
@ -219,17 +219,17 @@ class TestPickNextGame:
|
|||||||
state = State()
|
state = State()
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch("python_pkg.steam_backlog_enforcer._scanning_confidence._echo"),
|
patch("steam_backlog_enforcer._scanning_confidence._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
@ -241,7 +241,7 @@ class TestPickNextGame:
|
|||||||
g1 = _game(app_id=1, total=5, unlocked=5)
|
g1 = _game(app_id=1, total=5, unlocked=5)
|
||||||
config = Config(steam_api_key="k", steam_id="i")
|
config = Config(steam_api_key="k", steam_id="i")
|
||||||
state = State()
|
state = State()
|
||||||
with patch("python_pkg.steam_backlog_enforcer.scanning._echo"):
|
with patch("steam_backlog_enforcer.scanning._echo"):
|
||||||
pick_next_game([g1], state, config)
|
pick_next_game([g1], state, config)
|
||||||
assert state.current_app_id is None
|
assert state.current_app_id is None
|
||||||
|
|
||||||
@ -252,16 +252,16 @@ class TestPickNextGame:
|
|||||||
state = State(finished_app_ids=[1])
|
state = State(finished_app_ids=[1])
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
@ -275,10 +275,10 @@ class TestPickNextGame:
|
|||||||
state = State()
|
state = State()
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
return_value=None,
|
return_value=None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
):
|
):
|
||||||
pick_next_game([g1], state, config)
|
pick_next_game([g1], state, config)
|
||||||
assert state.current_app_id is None
|
assert state.current_app_id is None
|
||||||
@ -289,17 +289,17 @@ class TestPickNextGame:
|
|||||||
state = State()
|
state = State()
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch("python_pkg.steam_backlog_enforcer._scanning_confidence._echo"),
|
patch("steam_backlog_enforcer._scanning_confidence._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=2,
|
return_value=2,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
@ -313,17 +313,17 @@ class TestPickNextGame:
|
|||||||
state = State()
|
state = State()
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch("python_pkg.steam_backlog_enforcer._scanning_confidence._echo"),
|
patch("steam_backlog_enforcer._scanning_confidence._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.install_game"
|
"steam_backlog_enforcer.scanning.install_game"
|
||||||
) as mock_install,
|
) as mock_install,
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
):
|
):
|
||||||
@ -337,16 +337,16 @@ class TestPickNextGame:
|
|||||||
state = State()
|
state = State()
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
@ -361,16 +361,16 @@ class TestPickNextGame:
|
|||||||
state = State()
|
state = State()
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
@ -390,23 +390,23 @@ class TestPickNextGame:
|
|||||||
state = State()
|
state = State()
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._echo",
|
"steam_backlog_enforcer.scanning._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._echo",
|
"steam_backlog_enforcer._scanning_confidence._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
@ -428,15 +428,15 @@ class TestPickNextGame:
|
|||||||
state = State()
|
state = State()
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._echo",
|
"steam_backlog_enforcer.scanning._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._echo",
|
"steam_backlog_enforcer._scanning_confidence._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
return_value=None,
|
return_value=None,
|
||||||
) as mock_pick,
|
) as mock_pick,
|
||||||
):
|
):
|
||||||
|
|||||||
@ -5,13 +5,13 @@ from __future__ import annotations
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
from python_pkg.steam_backlog_enforcer.scanning import (
|
from steam_backlog_enforcer.scanning import (
|
||||||
_check_game_tampering,
|
_check_game_tampering,
|
||||||
detect_tampering,
|
detect_tampering,
|
||||||
)
|
)
|
||||||
|
|
||||||
PKG = "python_pkg.steam_backlog_enforcer.scanning"
|
PKG = "steam_backlog_enforcer.scanning"
|
||||||
|
|
||||||
|
|
||||||
def _entry(
|
def _entry(
|
||||||
|
|||||||
@ -5,9 +5,9 @@ from __future__ import annotations
|
|||||||
import contextlib
|
import contextlib
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
from python_pkg.steam_backlog_enforcer.scanning import pick_next_game
|
from steam_backlog_enforcer.scanning import pick_next_game
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
|
|
||||||
def _game(
|
def _game(
|
||||||
@ -50,27 +50,27 @@ class TestPickNextGame:
|
|||||||
|
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence",
|
"steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence",
|
||||||
side_effect=refresh_side_effect,
|
side_effect=refresh_side_effect,
|
||||||
) as mock_refresh,
|
) as mock_refresh,
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._echo",
|
"steam_backlog_enforcer.scanning._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._echo",
|
"steam_backlog_enforcer._scanning_confidence._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
@ -93,19 +93,19 @@ class TestPickNextGame:
|
|||||||
|
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence_batch"
|
"steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence_batch"
|
||||||
) as mock_refresh_batch,
|
) as mock_refresh_batch,
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
@ -131,27 +131,27 @@ class TestPickNextGame:
|
|||||||
|
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence.load_hltb_polls_cache",
|
"steam_backlog_enforcer._scanning_confidence.load_hltb_polls_cache",
|
||||||
return_value={1: 1, 2: 3},
|
return_value={1: 1, 2: 3},
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence.load_hltb_count_comp_cache",
|
"steam_backlog_enforcer._scanning_confidence.load_hltb_count_comp_cache",
|
||||||
return_value={1: 8, 2: 20},
|
return_value={1: 8, 2: 20},
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence_batch"
|
"steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence_batch"
|
||||||
) as mock_refresh_batch,
|
) as mock_refresh_batch,
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
@ -178,16 +178,16 @@ class TestPickNextGame:
|
|||||||
|
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=playable_side_effect,
|
side_effect=playable_side_effect,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="1"),
|
patch("builtins.input", return_value="1"),
|
||||||
@ -205,16 +205,16 @@ class TestPickNextGame:
|
|||||||
state = State()
|
state = State()
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", return_value="2"),
|
patch("builtins.input", return_value="2"),
|
||||||
@ -230,19 +230,19 @@ class TestPickNextGame:
|
|||||||
echoed: list[str] = []
|
echoed: list[str] = []
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._echo",
|
"steam_backlog_enforcer.scanning._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", side_effect=["abc", "1"]),
|
patch("builtins.input", side_effect=["abc", "1"]),
|
||||||
@ -259,19 +259,19 @@ class TestPickNextGame:
|
|||||||
echoed: list[str] = []
|
echoed: list[str] = []
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._echo",
|
"steam_backlog_enforcer.scanning._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
),
|
),
|
||||||
patch("builtins.input", side_effect=["99", "1"]),
|
patch("builtins.input", side_effect=["99", "1"]),
|
||||||
@ -289,30 +289,30 @@ class TestPickNextGameSequential:
|
|||||||
stack = contextlib.ExitStack()
|
stack = contextlib.ExitStack()
|
||||||
stack.enter_context(
|
stack.enter_context(
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
stack.enter_context(
|
stack.enter_context(
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._echo",
|
"steam_backlog_enforcer.scanning._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
stack.enter_context(
|
stack.enter_context(
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
|
"steam_backlog_enforcer.scanning.is_game_installed",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
stack.enter_context(
|
stack.enter_context(
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
|
"steam_backlog_enforcer.scanning.uninstall_other_games",
|
||||||
return_value=0,
|
return_value=0,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
stack.enter_context(
|
stack.enter_context(
|
||||||
patch("python_pkg.steam_backlog_enforcer.config._atomic_write")
|
patch("steam_backlog_enforcer.config._atomic_write")
|
||||||
)
|
)
|
||||||
return stack
|
return stack
|
||||||
|
|
||||||
@ -363,14 +363,14 @@ class TestPickNextGameSequential:
|
|||||||
echoed: list[str] = []
|
echoed: list[str] = []
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
return_value=None,
|
return_value=None,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._echo",
|
"steam_backlog_enforcer.scanning._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.config._atomic_write"),
|
patch("steam_backlog_enforcer.config._atomic_write"),
|
||||||
):
|
):
|
||||||
pick_next_game([g1], state, config, on_select=lambda _g: True)
|
pick_next_game([g1], state, config, on_select=lambda _g: True)
|
||||||
assert state.current_app_id is None
|
assert state.current_app_id is None
|
||||||
@ -386,17 +386,17 @@ class TestPickNextGameSequential:
|
|||||||
echoed: list[str] = []
|
echoed: list[str] = []
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._echo",
|
"steam_backlog_enforcer.scanning._echo",
|
||||||
side_effect=lambda *a, **_: echoed.append(a[0]),
|
side_effect=lambda *a, **_: echoed.append(a[0]),
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence",
|
"steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence",
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.config._atomic_write"),
|
patch("steam_backlog_enforcer.config._atomic_write"),
|
||||||
):
|
):
|
||||||
pick_next_game([g1], state, config, on_select=lambda _g: True)
|
pick_next_game([g1], state, config, on_select=lambda _g: True)
|
||||||
assert state.current_app_id is None
|
assert state.current_app_id is None
|
||||||
|
|||||||
@ -4,18 +4,18 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._scanning_confidence import (
|
from steam_backlog_enforcer._scanning_confidence import (
|
||||||
_filter_hltb_confident_candidates,
|
_filter_hltb_confident_candidates,
|
||||||
_force_refresh_candidate_confidence,
|
_force_refresh_candidate_confidence,
|
||||||
_refresh_candidate_confidence_batch,
|
_refresh_candidate_confidence_batch,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
from python_pkg.steam_backlog_enforcer.scanning import (
|
from steam_backlog_enforcer.scanning import (
|
||||||
_collect_top_candidates,
|
_collect_top_candidates,
|
||||||
_pick_next_shortest_candidate,
|
_pick_next_shortest_candidate,
|
||||||
do_check,
|
do_check,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
|
|
||||||
def _game(
|
def _game(
|
||||||
@ -44,7 +44,7 @@ class TestCollectTopCandidates:
|
|||||||
"""Returns at most n qualified candidates."""
|
"""Returns at most n qualified candidates."""
|
||||||
games = [_game(app_id=i, name=f"G{i}", hours=float(i)) for i in range(1, 6)]
|
games = [_game(app_id=i, name=f"G{i}", hours=float(i)) for i in range(1, 6)]
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
):
|
):
|
||||||
qualified, conf_skip, linux_skip = _collect_top_candidates(games, n=3)
|
qualified, conf_skip, linux_skip = _collect_top_candidates(games, n=3)
|
||||||
@ -59,10 +59,10 @@ class TestCollectTopCandidates:
|
|||||||
g2 = _game(app_id=2, name="Good", hours=2.0)
|
g2 = _game(app_id=2, name="Good", hours=2.0)
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: None if c[0].app_id == 1 else c[0],
|
side_effect=lambda c: None if c[0].app_id == 1 else c[0],
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
):
|
):
|
||||||
qualified, conf_skip, linux_skip = _collect_top_candidates([g1, g2], n=10)
|
qualified, conf_skip, linux_skip = _collect_top_candidates([g1, g2], n=10)
|
||||||
assert [g.app_id for g in qualified] == [2]
|
assert [g.app_id for g in qualified] == [2]
|
||||||
@ -80,10 +80,10 @@ class TestCollectTopCandidates:
|
|||||||
g = _game(app_id=1, name="Good", hours=1.0)
|
g = _game(app_id=1, name="Good", hours=1.0)
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=lambda c: c[0] if c else None,
|
side_effect=lambda c: c[0] if c else None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo") as mock_echo,
|
patch("steam_backlog_enforcer.scanning._echo") as mock_echo,
|
||||||
):
|
):
|
||||||
_collect_top_candidates([g], n=10)
|
_collect_top_candidates([g], n=10)
|
||||||
mock_echo.assert_not_called()
|
mock_echo.assert_not_called()
|
||||||
@ -93,7 +93,7 @@ class TestDoCheck:
|
|||||||
"""Tests for do_check."""
|
"""Tests for do_check."""
|
||||||
|
|
||||||
def test_no_assignment(self) -> None:
|
def test_no_assignment(self) -> None:
|
||||||
with patch("python_pkg.steam_backlog_enforcer.scanning._echo") as mock_echo:
|
with patch("steam_backlog_enforcer.scanning._echo") as mock_echo:
|
||||||
do_check(Config(), State())
|
do_check(Config(), State())
|
||||||
mock_echo.assert_called()
|
mock_echo.assert_called()
|
||||||
|
|
||||||
@ -102,11 +102,11 @@ class TestDoCheck:
|
|||||||
mock_client.refresh_single_game.return_value = None
|
mock_client.refresh_single_game.return_value = None
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.SteamAPIClient",
|
"steam_backlog_enforcer.scanning.SteamAPIClient",
|
||||||
return_value=mock_client,
|
return_value=mock_client,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning.detect_tampering"),
|
patch("steam_backlog_enforcer.scanning.detect_tampering"),
|
||||||
):
|
):
|
||||||
state = State(current_app_id=440, current_game_name="TF2")
|
state = State(current_app_id=440, current_game_name="TF2")
|
||||||
do_check(Config(steam_api_key="k", steam_id="i"), state)
|
do_check(Config(steam_api_key="k", steam_id="i"), state)
|
||||||
@ -118,7 +118,7 @@ class TestConfidenceHelpers:
|
|||||||
def test_force_refresh_candidate_confidence_delegates(self) -> None:
|
def test_force_refresh_candidate_confidence_delegates(self) -> None:
|
||||||
game = _game(app_id=10, name="A")
|
game = _game(app_id=10, name="A")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence_batch",
|
"steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence_batch",
|
||||||
) as mock_batch:
|
) as mock_batch:
|
||||||
_force_refresh_candidate_confidence(game)
|
_force_refresh_candidate_confidence(game)
|
||||||
mock_batch.assert_called_once_with([game], force=True)
|
mock_batch.assert_called_once_with([game], force=True)
|
||||||
@ -128,7 +128,7 @@ class TestConfidenceHelpers:
|
|||||||
game.comp_100_count = 3
|
game.comp_100_count = 3
|
||||||
game.count_comp = 15
|
game.count_comp = 15
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence.fetch_hltb_confidence_cached",
|
"steam_backlog_enforcer._scanning_confidence.fetch_hltb_confidence_cached",
|
||||||
) as mock_fetch:
|
) as mock_fetch:
|
||||||
_refresh_candidate_confidence_batch([game], force=False)
|
_refresh_candidate_confidence_batch([game], force=False)
|
||||||
mock_fetch.assert_not_called()
|
mock_fetch.assert_not_called()
|
||||||
@ -139,23 +139,23 @@ class TestConfidenceHelpers:
|
|||||||
game.count_comp = 0
|
game.count_comp = 0
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence.load_hltb_cache",
|
"steam_backlog_enforcer._scanning_confidence.load_hltb_cache",
|
||||||
side_effect=[{30: 9.5}, {30: -1.0}],
|
side_effect=[{30: 9.5}, {30: -1.0}],
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence.load_hltb_polls_cache",
|
"steam_backlog_enforcer._scanning_confidence.load_hltb_polls_cache",
|
||||||
return_value={30: 0},
|
return_value={30: 0},
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence.load_hltb_count_comp_cache",
|
"steam_backlog_enforcer._scanning_confidence.load_hltb_count_comp_cache",
|
||||||
return_value={30: 0},
|
return_value={30: 0},
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence.fetch_hltb_confidence_cached",
|
"steam_backlog_enforcer._scanning_confidence.fetch_hltb_confidence_cached",
|
||||||
return_value={30: -1.0},
|
return_value={30: -1.0},
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence.save_hltb_cache",
|
"steam_backlog_enforcer._scanning_confidence.save_hltb_cache",
|
||||||
) as mock_save,
|
) as mock_save,
|
||||||
):
|
):
|
||||||
_refresh_candidate_confidence_batch([game], force=True)
|
_refresh_candidate_confidence_batch([game], force=True)
|
||||||
@ -170,10 +170,10 @@ class TestConfidenceHelpers:
|
|||||||
low.count_comp = 2
|
low.count_comp = 2
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence_batch",
|
"steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence_batch",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._echo"
|
"steam_backlog_enforcer._scanning_confidence._echo"
|
||||||
) as mock_echo,
|
) as mock_echo,
|
||||||
):
|
):
|
||||||
result = _filter_hltb_confident_candidates([low])
|
result = _filter_hltb_confident_candidates([low])
|
||||||
@ -190,10 +190,10 @@ class TestConfidenceHelpers:
|
|||||||
|
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
side_effect=[None, good],
|
side_effect=[None, good],
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo") as mock_echo,
|
patch("steam_backlog_enforcer.scanning._echo") as mock_echo,
|
||||||
):
|
):
|
||||||
picked, skipped_low_conf, skipped_linux = _pick_next_shortest_candidate(
|
picked, skipped_low_conf, skipped_linux = _pick_next_shortest_candidate(
|
||||||
[bad, good],
|
[bad, good],
|
||||||
@ -214,10 +214,10 @@ class TestConfidenceHelpers:
|
|||||||
good = _game(app_id=51, name="Good", hours=2.0)
|
good = _game(app_id=51, name="Good", hours=2.0)
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
return_value=good,
|
return_value=good,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo") as mock_echo,
|
patch("steam_backlog_enforcer.scanning._echo") as mock_echo,
|
||||||
):
|
):
|
||||||
picked, _skipped_low_conf, skipped_linux = _pick_next_shortest_candidate(
|
picked, _skipped_low_conf, skipped_linux = _pick_next_shortest_candidate(
|
||||||
[good],
|
[good],
|
||||||
@ -233,9 +233,9 @@ class TestConfidenceHelpers:
|
|||||||
low_conf.count_comp = 0
|
low_conf.count_comp = 0
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence"
|
"steam_backlog_enforcer._scanning_confidence._refresh_candidate_confidence"
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
):
|
):
|
||||||
picked, skipped_low_conf, skipped_linux = _pick_next_shortest_candidate(
|
picked, skipped_low_conf, skipped_linux = _pick_next_shortest_candidate(
|
||||||
[low_conf],
|
[low_conf],
|
||||||
@ -249,10 +249,10 @@ class TestConfidenceHelpers:
|
|||||||
g1 = _game(app_id=10, name="Borked", hours=1.0)
|
g1 = _game(app_id=10, name="Borked", hours=1.0)
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning._pick_playable_candidate",
|
"steam_backlog_enforcer.scanning._pick_playable_candidate",
|
||||||
return_value=None,
|
return_value=None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo") as mock_echo,
|
patch("steam_backlog_enforcer.scanning._echo") as mock_echo,
|
||||||
):
|
):
|
||||||
picked, _skipped_low_conf, skipped_linux = _pick_next_shortest_candidate(
|
picked, _skipped_low_conf, skipped_linux = _pick_next_shortest_candidate(
|
||||||
[g1],
|
[g1],
|
||||||
@ -270,21 +270,21 @@ class TestConfidenceHelpers:
|
|||||||
snap = [game.to_snapshot()]
|
snap = [game.to_snapshot()]
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.SteamAPIClient",
|
"steam_backlog_enforcer.scanning.SteamAPIClient",
|
||||||
return_value=mock_client,
|
return_value=mock_client,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.send_notification",
|
"steam_backlog_enforcer.scanning.send_notification",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.load_snapshot",
|
"steam_backlog_enforcer.scanning.load_snapshot",
|
||||||
return_value=snap,
|
return_value=snap,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.pick_next_game",
|
"steam_backlog_enforcer.scanning.pick_next_game",
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning.detect_tampering"),
|
patch("steam_backlog_enforcer.scanning.detect_tampering"),
|
||||||
):
|
):
|
||||||
state = State(current_app_id=440, current_game_name="TF2")
|
state = State(current_app_id=440, current_game_name="TF2")
|
||||||
do_check(Config(steam_api_key="k", steam_id="i"), state)
|
do_check(Config(steam_api_key="k", steam_id="i"), state)
|
||||||
@ -296,18 +296,18 @@ class TestConfidenceHelpers:
|
|||||||
mock_client.refresh_single_game.return_value = game
|
mock_client.refresh_single_game.return_value = game
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.SteamAPIClient",
|
"steam_backlog_enforcer.scanning.SteamAPIClient",
|
||||||
return_value=mock_client,
|
return_value=mock_client,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.send_notification",
|
"steam_backlog_enforcer.scanning.send_notification",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.load_snapshot",
|
"steam_backlog_enforcer.scanning.load_snapshot",
|
||||||
return_value=None,
|
return_value=None,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning.detect_tampering"),
|
patch("steam_backlog_enforcer.scanning.detect_tampering"),
|
||||||
):
|
):
|
||||||
state = State(current_app_id=440, current_game_name="TF2")
|
state = State(current_app_id=440, current_game_name="TF2")
|
||||||
do_check(Config(steam_api_key="k", steam_id="i"), state)
|
do_check(Config(steam_api_key="k", steam_id="i"), state)
|
||||||
@ -318,11 +318,11 @@ class TestConfidenceHelpers:
|
|||||||
mock_client.refresh_single_game.return_value = game
|
mock_client.refresh_single_game.return_value = game
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.scanning.SteamAPIClient",
|
"steam_backlog_enforcer.scanning.SteamAPIClient",
|
||||||
return_value=mock_client,
|
return_value=mock_client,
|
||||||
),
|
),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning._echo"),
|
patch("steam_backlog_enforcer.scanning._echo"),
|
||||||
patch("python_pkg.steam_backlog_enforcer.scanning.detect_tampering"),
|
patch("steam_backlog_enforcer.scanning.detect_tampering"),
|
||||||
):
|
):
|
||||||
state = State(current_app_id=440, current_game_name="TF2")
|
state = State(current_app_id=440, current_game_name="TF2")
|
||||||
do_check(Config(steam_api_key="k", steam_id="i"), state)
|
do_check(Config(steam_api_key="k", steam_id="i"), state)
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._stats import (
|
from steam_backlog_enforcer._stats import (
|
||||||
_ensure_rush_data,
|
_ensure_rush_data,
|
||||||
_filter_qualifying_games,
|
_filter_qualifying_games,
|
||||||
_format_completion_date,
|
_format_completion_date,
|
||||||
@ -16,11 +16,11 @@ from python_pkg.steam_backlog_enforcer._stats import (
|
|||||||
_sum_hours,
|
_sum_hours,
|
||||||
cmd_stats,
|
cmd_stats,
|
||||||
)
|
)
|
||||||
from python_pkg.steam_backlog_enforcer.config import Config, State
|
from steam_backlog_enforcer.config import Config, State
|
||||||
from python_pkg.steam_backlog_enforcer.protondb import ProtonDBRating
|
from steam_backlog_enforcer.protondb import ProtonDBRating
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import GameInfo
|
from steam_backlog_enforcer.steam_api import GameInfo
|
||||||
|
|
||||||
_PKG = "python_pkg.steam_backlog_enforcer._stats"
|
_PKG = "steam_backlog_enforcer._stats"
|
||||||
|
|
||||||
|
|
||||||
def _game(
|
def _game(
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from unittest.mock import MagicMock, patch
|
|||||||
import pytest
|
import pytest
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.steam_api import (
|
from steam_backlog_enforcer.steam_api import (
|
||||||
AchievementInfo,
|
AchievementInfo,
|
||||||
GameInfo,
|
GameInfo,
|
||||||
SteamAPIClient,
|
SteamAPIClient,
|
||||||
@ -163,7 +163,7 @@ class TestSteamAPIClient:
|
|||||||
# Fill up the rate limit window
|
# Fill up the rate limit window
|
||||||
client._request_times = [__import__("time").time()] * client._max_rps
|
client._request_times = [__import__("time").time()] * client._max_rps
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.steam_api.time.sleep",
|
"steam_backlog_enforcer.steam_api.time.sleep",
|
||||||
) as mock_sleep:
|
) as mock_sleep:
|
||||||
# Next call should trigger sleep then succeed
|
# Next call should trigger sleep then succeed
|
||||||
client._rate_limit()
|
client._rate_limit()
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.store_blocker import (
|
from steam_backlog_enforcer.store_blocker import (
|
||||||
_block_store_iptables,
|
_block_store_iptables,
|
||||||
_block_via_hosts_install,
|
_block_via_hosts_install,
|
||||||
_is_iptables_blocked,
|
_is_iptables_blocked,
|
||||||
@ -27,7 +27,7 @@ class TestIsStoreBlocked:
|
|||||||
hosts_file.write_text("0.0.0.0 store.steampowered.com\n", encoding="utf-8")
|
hosts_file.write_text("0.0.0.0 store.steampowered.com\n", encoding="utf-8")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
"steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
||||||
hosts_file,
|
hosts_file,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -38,11 +38,11 @@ class TestIsStoreBlocked:
|
|||||||
hosts_file.write_text("# 0.0.0.0 store.steampowered.com\n", encoding="utf-8")
|
hosts_file.write_text("# 0.0.0.0 store.steampowered.com\n", encoding="utf-8")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
"steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
||||||
hosts_file,
|
hosts_file,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._is_iptables_blocked",
|
"steam_backlog_enforcer.store_blocker._is_iptables_blocked",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -53,11 +53,11 @@ class TestIsStoreBlocked:
|
|||||||
hosts_file.write_text("127.0.0.1 localhost\n", encoding="utf-8")
|
hosts_file.write_text("127.0.0.1 localhost\n", encoding="utf-8")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
"steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
||||||
hosts_file,
|
hosts_file,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._is_iptables_blocked",
|
"steam_backlog_enforcer.store_blocker._is_iptables_blocked",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -67,11 +67,11 @@ class TestIsStoreBlocked:
|
|||||||
hosts_file = tmp_path / "nonexistent"
|
hosts_file = tmp_path / "nonexistent"
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
"steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
||||||
hosts_file,
|
hosts_file,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._is_iptables_blocked",
|
"steam_backlog_enforcer.store_blocker._is_iptables_blocked",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -82,11 +82,11 @@ class TestIsStoreBlocked:
|
|||||||
hosts_file.write_text("127.0.0.1 store.steampowered.com\n", encoding="utf-8")
|
hosts_file.write_text("127.0.0.1 store.steampowered.com\n", encoding="utf-8")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
"steam_backlog_enforcer.store_blocker.HOSTS_FILE",
|
||||||
hosts_file,
|
hosts_file,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._is_iptables_blocked",
|
"steam_backlog_enforcer.store_blocker._is_iptables_blocked",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -98,7 +98,7 @@ class TestBlockStore:
|
|||||||
|
|
||||||
def test_already_blocked(self) -> None:
|
def test_already_blocked(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
):
|
):
|
||||||
assert block_store() is True
|
assert block_store() is True
|
||||||
@ -106,18 +106,18 @@ class TestBlockStore:
|
|||||||
def test_reblock_succeeds(self) -> None:
|
def test_reblock_succeeds(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
side_effect=[False, True],
|
side_effect=[False, True],
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._reblock_hosts",
|
"steam_backlog_enforcer.store_blocker._reblock_hosts",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._block_store_iptables",
|
"steam_backlog_enforcer.store_blocker._block_store_iptables",
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
"steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
assert block_store() is True
|
assert block_store() is True
|
||||||
@ -125,23 +125,23 @@ class TestBlockStore:
|
|||||||
def test_fallback_to_install_script(self) -> None:
|
def test_fallback_to_install_script(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
side_effect=[False, False],
|
side_effect=[False, False],
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._reblock_hosts",
|
"steam_backlog_enforcer.store_blocker._reblock_hosts",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._block_via_hosts_install",
|
"steam_backlog_enforcer.store_blocker._block_via_hosts_install",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._block_store_iptables",
|
"steam_backlog_enforcer.store_blocker._block_store_iptables",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
"steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
assert block_store() is True
|
assert block_store() is True
|
||||||
@ -149,19 +149,19 @@ class TestBlockStore:
|
|||||||
def test_all_fail(self) -> None:
|
def test_all_fail(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
side_effect=[False, False],
|
side_effect=[False, False],
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._reblock_hosts",
|
"steam_backlog_enforcer.store_blocker._reblock_hosts",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._block_via_hosts_install",
|
"steam_backlog_enforcer.store_blocker._block_via_hosts_install",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._block_store_iptables",
|
"steam_backlog_enforcer.store_blocker._block_store_iptables",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -170,23 +170,23 @@ class TestBlockStore:
|
|||||||
def test_iptables_only_succeeds(self) -> None:
|
def test_iptables_only_succeeds(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
side_effect=[False, False],
|
side_effect=[False, False],
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._reblock_hosts",
|
"steam_backlog_enforcer.store_blocker._reblock_hosts",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._block_via_hosts_install",
|
"steam_backlog_enforcer.store_blocker._block_via_hosts_install",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._block_store_iptables",
|
"steam_backlog_enforcer.store_blocker._block_store_iptables",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
"steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
assert block_store() is True
|
assert block_store() is True
|
||||||
@ -197,7 +197,7 @@ class TestBlockViaHostsInstall:
|
|||||||
|
|
||||||
def test_already_blocked(self) -> None:
|
def test_already_blocked(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
):
|
):
|
||||||
assert _block_via_hosts_install() is True
|
assert _block_via_hosts_install() is True
|
||||||
@ -205,11 +205,11 @@ class TestBlockViaHostsInstall:
|
|||||||
def test_script_missing(self, tmp_path: Path) -> None:
|
def test_script_missing(self, tmp_path: Path) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_INSTALL_SCRIPT",
|
"steam_backlog_enforcer.store_blocker.HOSTS_INSTALL_SCRIPT",
|
||||||
tmp_path / "nonexistent.sh",
|
tmp_path / "nonexistent.sh",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -221,15 +221,15 @@ class TestBlockViaHostsInstall:
|
|||||||
mock_result = MagicMock(returncode=0)
|
mock_result = MagicMock(returncode=0)
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_INSTALL_SCRIPT",
|
"steam_backlog_enforcer.store_blocker.HOSTS_INSTALL_SCRIPT",
|
||||||
script,
|
script,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -241,15 +241,15 @@ class TestBlockViaHostsInstall:
|
|||||||
mock_result = MagicMock(returncode=1, stderr="error", stdout="")
|
mock_result = MagicMock(returncode=1, stderr="error", stdout="")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_INSTALL_SCRIPT",
|
"steam_backlog_enforcer.store_blocker.HOSTS_INSTALL_SCRIPT",
|
||||||
script,
|
script,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -261,15 +261,15 @@ class TestBlockViaHostsInstall:
|
|||||||
mock_result = MagicMock(returncode=1, stderr="", stdout="out")
|
mock_result = MagicMock(returncode=1, stderr="", stdout="out")
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_INSTALL_SCRIPT",
|
"steam_backlog_enforcer.store_blocker.HOSTS_INSTALL_SCRIPT",
|
||||||
script,
|
script,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -280,15 +280,15 @@ class TestBlockViaHostsInstall:
|
|||||||
script.touch()
|
script.touch()
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.is_store_blocked",
|
"steam_backlog_enforcer.store_blocker.is_store_blocked",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_INSTALL_SCRIPT",
|
"steam_backlog_enforcer.store_blocker.HOSTS_INSTALL_SCRIPT",
|
||||||
script,
|
script,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
side_effect=OSError,
|
side_effect=OSError,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -301,7 +301,7 @@ class TestIsIptablesBlocked:
|
|||||||
def test_blocked(self) -> None:
|
def test_blocked(self) -> None:
|
||||||
mock_result = MagicMock(returncode=0, stdout="DROP blah")
|
mock_result = MagicMock(returncode=0, stdout="DROP blah")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
):
|
):
|
||||||
assert _is_iptables_blocked() is True
|
assert _is_iptables_blocked() is True
|
||||||
@ -309,7 +309,7 @@ class TestIsIptablesBlocked:
|
|||||||
def test_not_blocked_no_drop(self) -> None:
|
def test_not_blocked_no_drop(self) -> None:
|
||||||
mock_result = MagicMock(returncode=0, stdout="ACCEPT")
|
mock_result = MagicMock(returncode=0, stdout="ACCEPT")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
):
|
):
|
||||||
assert _is_iptables_blocked() is False
|
assert _is_iptables_blocked() is False
|
||||||
@ -317,14 +317,14 @@ class TestIsIptablesBlocked:
|
|||||||
def test_not_blocked_error(self) -> None:
|
def test_not_blocked_error(self) -> None:
|
||||||
mock_result = MagicMock(returncode=1, stdout="")
|
mock_result = MagicMock(returncode=1, stdout="")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
):
|
):
|
||||||
assert _is_iptables_blocked() is False
|
assert _is_iptables_blocked() is False
|
||||||
|
|
||||||
def test_os_error(self) -> None:
|
def test_os_error(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
side_effect=OSError,
|
side_effect=OSError,
|
||||||
):
|
):
|
||||||
assert _is_iptables_blocked() is False
|
assert _is_iptables_blocked() is False
|
||||||
@ -337,11 +337,11 @@ class TestBlockStoreIptables:
|
|||||||
mock_result = MagicMock(returncode=0)
|
mock_result = MagicMock(returncode=0)
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.socket.getaddrinfo",
|
"steam_backlog_enforcer.store_blocker.socket.getaddrinfo",
|
||||||
return_value=[
|
return_value=[
|
||||||
(None, None, None, None, ("1.2.3.4", 443)),
|
(None, None, None, None, ("1.2.3.4", 443)),
|
||||||
],
|
],
|
||||||
@ -351,7 +351,7 @@ class TestBlockStoreIptables:
|
|||||||
|
|
||||||
def test_os_error(self) -> None:
|
def test_os_error(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
side_effect=OSError,
|
side_effect=OSError,
|
||||||
):
|
):
|
||||||
assert _block_store_iptables() is False
|
assert _block_store_iptables() is False
|
||||||
@ -362,11 +362,11 @@ class TestBlockStoreIptables:
|
|||||||
mock_result = MagicMock(returncode=0)
|
mock_result = MagicMock(returncode=0)
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
return_value=mock_result,
|
return_value=mock_result,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.socket.getaddrinfo",
|
"steam_backlog_enforcer.store_blocker.socket.getaddrinfo",
|
||||||
side_effect=socket.gaierror,
|
side_effect=socket.gaierror,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -390,11 +390,11 @@ class TestBlockStoreIptables:
|
|||||||
|
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
side_effect=side_effect,
|
side_effect=side_effect,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.socket.getaddrinfo",
|
"steam_backlog_enforcer.store_blocker.socket.getaddrinfo",
|
||||||
side_effect=__import__("socket").gaierror,
|
side_effect=__import__("socket").gaierror,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
@ -407,15 +407,15 @@ class TestUnblockStore:
|
|||||||
def test_both_succeed(self) -> None:
|
def test_both_succeed(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._unblock_store_iptables",
|
"steam_backlog_enforcer.store_blocker._unblock_store_iptables",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._unblock_hosts",
|
"steam_backlog_enforcer.store_blocker._unblock_hosts",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
"steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
assert unblock_store() is True
|
assert unblock_store() is True
|
||||||
@ -423,15 +423,15 @@ class TestUnblockStore:
|
|||||||
def test_iptables_fails(self) -> None:
|
def test_iptables_fails(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._unblock_store_iptables",
|
"steam_backlog_enforcer.store_blocker._unblock_store_iptables",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._unblock_hosts",
|
"steam_backlog_enforcer.store_blocker._unblock_hosts",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
"steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
assert unblock_store() is True
|
assert unblock_store() is True
|
||||||
@ -439,15 +439,15 @@ class TestUnblockStore:
|
|||||||
def test_both_fail(self) -> None:
|
def test_both_fail(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._unblock_store_iptables",
|
"steam_backlog_enforcer.store_blocker._unblock_store_iptables",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker._unblock_hosts",
|
"steam_backlog_enforcer.store_blocker._unblock_hosts",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
),
|
),
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
"steam_backlog_enforcer.store_blocker.flush_dns_cache",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
assert unblock_store() is False
|
assert unblock_store() is False
|
||||||
@ -458,13 +458,13 @@ class TestUnblockStoreIptables:
|
|||||||
|
|
||||||
def test_success(self) -> None:
|
def test_success(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
):
|
):
|
||||||
assert _unblock_store_iptables() is True
|
assert _unblock_store_iptables() is True
|
||||||
|
|
||||||
def test_os_error(self) -> None:
|
def test_os_error(self) -> None:
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer.store_blocker.subprocess.run",
|
"steam_backlog_enforcer.store_blocker.subprocess.run",
|
||||||
side_effect=OSError,
|
side_effect=OSError,
|
||||||
):
|
):
|
||||||
assert _unblock_store_iptables() is False
|
assert _unblock_store_iptables() is False
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer.store_blocker import (
|
from steam_backlog_enforcer.store_blocker import (
|
||||||
_disable_hosts_protection,
|
_disable_hosts_protection,
|
||||||
_enable_hosts_protection,
|
_enable_hosts_protection,
|
||||||
_reblock_hosts,
|
_reblock_hosts,
|
||||||
@ -17,7 +17,7 @@ from python_pkg.steam_backlog_enforcer.store_blocker import (
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
PKG = "python_pkg.steam_backlog_enforcer.store_blocker"
|
PKG = "steam_backlog_enforcer.store_blocker"
|
||||||
|
|
||||||
|
|
||||||
class TestSudoWriteHosts:
|
class TestSudoWriteHosts:
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from python_pkg.steam_backlog_enforcer._whitelist import (
|
from steam_backlog_enforcer._whitelist import (
|
||||||
WHITELIST_COOLDOWN_SECONDS,
|
WHITELIST_COOLDOWN_SECONDS,
|
||||||
_append_audit_log,
|
_append_audit_log,
|
||||||
_load_approved,
|
_load_approved,
|
||||||
@ -170,7 +170,7 @@ class TestLockAndUnlock:
|
|||||||
|
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"python_pkg.steam_backlog_enforcer._whitelist.APPROVED_EXCEPTIONS_FILE",
|
"steam_backlog_enforcer._whitelist.APPROVED_EXCEPTIONS_FILE",
|
||||||
approved,
|
approved,
|
||||||
),
|
),
|
||||||
patch("shutil.which", return_value="/usr/bin/chattr"),
|
patch("shutil.which", return_value="/usr/bin/chattr"),
|
||||||
@ -206,7 +206,7 @@ class TestPersistence:
|
|||||||
bad = tmp_path / "pending.json"
|
bad = tmp_path / "pending.json"
|
||||||
bad.write_text("not json{{", encoding="utf-8")
|
bad.write_text("not json{{", encoding="utf-8")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._whitelist.PENDING_EXCEPTIONS_FILE",
|
"steam_backlog_enforcer._whitelist.PENDING_EXCEPTIONS_FILE",
|
||||||
bad,
|
bad,
|
||||||
):
|
):
|
||||||
assert _load_pending() == []
|
assert _load_pending() == []
|
||||||
@ -215,7 +215,7 @@ class TestPersistence:
|
|||||||
bad = tmp_path / "pending.json"
|
bad = tmp_path / "pending.json"
|
||||||
bad.write_text('{"key": "value"}', encoding="utf-8")
|
bad.write_text('{"key": "value"}', encoding="utf-8")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._whitelist.PENDING_EXCEPTIONS_FILE",
|
"steam_backlog_enforcer._whitelist.PENDING_EXCEPTIONS_FILE",
|
||||||
bad,
|
bad,
|
||||||
):
|
):
|
||||||
assert _load_pending() == []
|
assert _load_pending() == []
|
||||||
@ -234,7 +234,7 @@ class TestPersistence:
|
|||||||
bad = tmp_path / "approved.json"
|
bad = tmp_path / "approved.json"
|
||||||
bad.write_text("{{broken", encoding="utf-8")
|
bad.write_text("{{broken", encoding="utf-8")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._whitelist.APPROVED_EXCEPTIONS_FILE",
|
"steam_backlog_enforcer._whitelist.APPROVED_EXCEPTIONS_FILE",
|
||||||
bad,
|
bad,
|
||||||
):
|
):
|
||||||
assert _load_approved() == []
|
assert _load_approved() == []
|
||||||
@ -243,7 +243,7 @@ class TestPersistence:
|
|||||||
bad = tmp_path / "approved.json"
|
bad = tmp_path / "approved.json"
|
||||||
bad.write_text('"just a string"', encoding="utf-8")
|
bad.write_text('"just a string"', encoding="utf-8")
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._whitelist.APPROVED_EXCEPTIONS_FILE",
|
"steam_backlog_enforcer._whitelist.APPROVED_EXCEPTIONS_FILE",
|
||||||
bad,
|
bad,
|
||||||
):
|
):
|
||||||
assert _load_approved() == []
|
assert _load_approved() == []
|
||||||
@ -268,7 +268,7 @@ class TestAppendAuditLog:
|
|||||||
def test_audit_log_written(self, tmp_path: Path) -> None:
|
def test_audit_log_written(self, tmp_path: Path) -> None:
|
||||||
log_file = tmp_path / "audit.log"
|
log_file = tmp_path / "audit.log"
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._whitelist.EXCEPTION_AUDIT_LOG",
|
"steam_backlog_enforcer._whitelist.EXCEPTION_AUDIT_LOG",
|
||||||
log_file,
|
log_file,
|
||||||
):
|
):
|
||||||
_append_audit_log(440, "some reason", "REQUESTED")
|
_append_audit_log(440, "some reason", "REQUESTED")
|
||||||
@ -280,7 +280,7 @@ class TestAppendAuditLog:
|
|||||||
def test_audit_log_appends(self, tmp_path: Path) -> None:
|
def test_audit_log_appends(self, tmp_path: Path) -> None:
|
||||||
log_file = tmp_path / "audit.log"
|
log_file = tmp_path / "audit.log"
|
||||||
with patch(
|
with patch(
|
||||||
"python_pkg.steam_backlog_enforcer._whitelist.EXCEPTION_AUDIT_LOG",
|
"steam_backlog_enforcer._whitelist.EXCEPTION_AUDIT_LOG",
|
||||||
log_file,
|
log_file,
|
||||||
):
|
):
|
||||||
_append_audit_log(440, "first", "REQUESTED")
|
_append_audit_log(440, "first", "REQUESTED")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user