diff --git a/dzgui/api/mods.py b/dzgui/api/mods.py index 81b6d1c..4089859 100644 --- a/dzgui/api/mods.py +++ b/dzgui/api/mods.py @@ -49,6 +49,7 @@ def get_local_mods(workshop_path: Path) -> list[Path]: mods = [file for file in workshop_path.iterdir() if file.is_dir()] return mods + def is_mission(path: Path) -> bool: # TODO: parse integrity of other files parent = path.parent.name @@ -57,9 +58,10 @@ def is_mission(path: Path) -> bool: file = path / "init.c" return file.exists() + def tokenize(mod: Path) -> dict[str, Any] | None: file = mod.joinpath("meta.cpp") - delimiter=r"\s*=\s*" + delimiter = r"\s*=\s*" modmeta = {} try: with open(file, "r", encoding="utf-8") as f: @@ -76,6 +78,7 @@ def tokenize(mod: Path) -> dict[str, Any] | None: logger.critical(e) return None + def get_mod_size(path: Path) -> float: s = 0 for f in path.rglob("*"): @@ -123,20 +126,27 @@ def _hash(uid: str, use_custom: bool = False) -> str: return prefix + md5.hexdigest()[:8] -def remove_stale_signatures(config: Path, versions: Path) -> None: +def remove_stale_signatures( + config: Path, versions: Path, ids: list[int] | None = None +) -> None: if versions.is_file() is False: logger.warning("Creating new version signatures file") versions.touch() return + path = lookup(config, Preferences.DEFAULT) steam_path = Path(path) - ids = get_local_mod_ids(steam_path) + if ids is None: + local_ids = get_local_mod_ids(steam_path) + with open(versions, "r") as f: lines = f.readlines() - for line in lines: - uid = int(line.split(",")[0]) - if uid not in ids: - lines.remove(line) + + if ids is None: + lines = [line for line in lines if int(line.split(",")[0]) in local_ids] + else: + lines = [line for line in lines if int(line.split(",")[0]) not in ids] + with open(versions, "w") as f: for line in lines: f.write(line) diff --git a/dzgui/init/proc.py b/dzgui/init/proc.py index 42647e9..1c97f74 100644 --- a/dzgui/init/proc.py +++ b/dzgui/init/proc.py @@ -1,6 +1,7 @@ import psutil import subprocess import shutil +import logging from warnings import deprecated diff --git a/dzgui/managers/mods.py b/dzgui/managers/mods.py index 87e9994..d609378 100644 --- a/dzgui/managers/mods.py +++ b/dzgui/managers/mods.py @@ -118,8 +118,7 @@ class ModManager: self.thread_man.increment_dialog() time.sleep(API_RATE_LIMIT) - iters = [_iter for mod, _iter in mods] - func = StoredFunc(self._on_mods_unsubbed, iters) + func = StoredFunc(self._on_mods_unsubbed, mods) self.thread_man.set_cleanup_func(func) def unsub_atomic_mod(self, mod: str) -> None: @@ -146,18 +145,21 @@ class ModManager: pass time.sleep(API_RATE_LIMIT) - def _on_mods_unsubbed(self, iters: list[Gtk.TreeIter]) -> None: + def _on_mods_unsubbed(self, mod_iter: list[tuple[str, Gtk.TreeIter]]) -> None: + mods = [int(mod) for mod, _iter in mod_iter] + iters = [_iter for mod, _iter in mod_iter] if self.store is None: return for _iter in iters: self.store.remove(_iter) - remove_stale_signatures(self.prefs.paths.config, self.prefs.paths.version) + # TODO: process config path in called function + remove_stale_signatures(self.prefs.paths.config, self.prefs.paths.version, mods) model = self.treeview.get_model() if model is None: return - mods = len(model) + total_mods = len(model) msg = self.format_mod_statusbar() - self.emitter.emit("mods_updated", msg, mods) + self.emitter.emit("mods_updated", msg, total_mods) def uncolorize_mods(self) -> None: model = self.treeview.get_model() diff --git a/tests/fixtures/dzg.versions b/tests/fixtures/dzg.versions new file mode 100644 index 0000000..6ebdc35 --- /dev/null +++ b/tests/fixtures/dzg.versions @@ -0,0 +1,8 @@ +1559212036,1771519119 +1564026768,1770917948 +2545327648,1780174455 +2276010135,1756744083 +1654462998,1780501511 +3410710885,1752864732 +2918418331,1780413260 +3739934289,1780855136 diff --git a/tests/test_mod_signatures.py b/tests/test_mod_signatures.py new file mode 100644 index 0000000..8aa5dd6 --- /dev/null +++ b/tests/test_mod_signatures.py @@ -0,0 +1,52 @@ +import pytest +import shutil +import tempfile + +from pathlib import Path +from typing import TYPE_CHECKING + +import dzgui.api.mods +import dzgui.config.query + +from tests.fixtures import fixture_path + +if TYPE_CHECKING: + from dzgui.const.enums import Preferences + +pytestmark = pytest.mark.mods + +@pytest.fixture +def versions() -> str: + return fixture_path("dzg.versions") + +@pytest.fixture +def tmp() -> str: + with tempfile.NamedTemporaryFile(delete=False) as f: + tmp = f.name + return tmp + +def mock_local_ids(path: Path) -> list[int]: + return [3410710885, 3739934289] + +def mock_lookup(path: Path, prefs: "Preferences") -> str: + return "" + +def test_signatures(monkeypatch, tmp: str, versions: str) -> None: + ids = [1559212036, 1654462998] + shutil.copyfile(versions, tmp) + path = Path(tmp) + monkeypatch.setattr("dzgui.api.mods.lookup", mock_lookup) + dzgui.api.mods.remove_stale_signatures(path, path, ids) + with open(tmp, "r") as f: + lines = f.readlines() + assert ids not in lines + +def test_signatures_with_no_ids(monkeypatch, tmp: str, versions: str) -> None: + shutil.copyfile(versions, tmp) + path = Path(tmp) + monkeypatch.setattr("dzgui.api.mods.get_local_mod_ids", mock_local_ids) + monkeypatch.setattr("dzgui.api.mods.lookup", mock_lookup) + dzgui.api.mods.remove_stale_signatures(path, path) + with open(tmp, "r") as f: + lines = f.readlines() + assert lines == ["3410710885,1752864732\n", "3739934289,1780855136\n"]