mirror of
https://github.com/aclist/dztui.git
synced 2026-08-30 03:37:00 +02:00
Compare commits
7 Commits
27136a0906
...
81168d3952
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81168d3952 | ||
|
|
ee90be42ee | ||
|
|
48f341bae2 | ||
|
|
0653f064b2 | ||
|
|
525dc24508 | ||
|
|
4e7c831a53 | ||
|
|
e41bef7b00 |
@ -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()]
|
mods = [file for file in workshop_path.iterdir() if file.is_dir()]
|
||||||
return mods
|
return mods
|
||||||
|
|
||||||
|
|
||||||
def is_mission(path: Path) -> bool:
|
def is_mission(path: Path) -> bool:
|
||||||
# TODO: parse integrity of other files
|
# TODO: parse integrity of other files
|
||||||
parent = path.parent.name
|
parent = path.parent.name
|
||||||
@ -57,6 +58,7 @@ def is_mission(path: Path) -> bool:
|
|||||||
file = path / "init.c"
|
file = path / "init.c"
|
||||||
return file.exists()
|
return file.exists()
|
||||||
|
|
||||||
|
|
||||||
def tokenize(mod: Path) -> dict[str, Any] | None:
|
def tokenize(mod: Path) -> dict[str, Any] | None:
|
||||||
file = mod.joinpath("meta.cpp")
|
file = mod.joinpath("meta.cpp")
|
||||||
delimiter = r"\s*=\s*"
|
delimiter = r"\s*=\s*"
|
||||||
@ -76,6 +78,7 @@ def tokenize(mod: Path) -> dict[str, Any] | None:
|
|||||||
logger.critical(e)
|
logger.critical(e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_mod_size(path: Path) -> float:
|
def get_mod_size(path: Path) -> float:
|
||||||
s = 0
|
s = 0
|
||||||
for f in path.rglob("*"):
|
for f in path.rglob("*"):
|
||||||
@ -123,20 +126,27 @@ def _hash(uid: str, use_custom: bool = False) -> str:
|
|||||||
return prefix + md5.hexdigest()[:8]
|
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:
|
if versions.is_file() is False:
|
||||||
logger.warning("Creating new version signatures file")
|
logger.warning("Creating new version signatures file")
|
||||||
versions.touch()
|
versions.touch()
|
||||||
return
|
return
|
||||||
|
|
||||||
path = lookup(config, Preferences.DEFAULT)
|
path = lookup(config, Preferences.DEFAULT)
|
||||||
steam_path = Path(path)
|
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:
|
with open(versions, "r") as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
for line in lines:
|
|
||||||
uid = int(line.split(",")[0])
|
if ids is None:
|
||||||
if uid not in ids:
|
lines = [line for line in lines if int(line.split(",")[0]) in local_ids]
|
||||||
lines.remove(line)
|
else:
|
||||||
|
lines = [line for line in lines if int(line.split(",")[0]) not in ids]
|
||||||
|
|
||||||
with open(versions, "w") as f:
|
with open(versions, "w") as f:
|
||||||
for line in lines:
|
for line in lines:
|
||||||
f.write(line)
|
f.write(line)
|
||||||
|
|||||||
@ -81,8 +81,8 @@ class Emitter(GObject.GObject):
|
|||||||
def distcalc_started(self) -> None:
|
def distcalc_started(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(bool,))
|
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(bool, int))
|
||||||
def mod_page_toggled(self, state: bool) -> None:
|
def mod_page_toggled(self, state: bool, mods: int) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(bool,))
|
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(bool,))
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import psutil
|
import psutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import shutil
|
import shutil
|
||||||
|
import logging
|
||||||
|
|
||||||
from warnings import deprecated
|
from warnings import deprecated
|
||||||
|
|
||||||
|
|||||||
@ -118,8 +118,7 @@ class ModManager:
|
|||||||
self.thread_man.increment_dialog()
|
self.thread_man.increment_dialog()
|
||||||
time.sleep(API_RATE_LIMIT)
|
time.sleep(API_RATE_LIMIT)
|
||||||
|
|
||||||
iters = [_iter for mod, _iter in mods]
|
func = StoredFunc(self._on_mods_unsubbed, mods)
|
||||||
func = StoredFunc(self._on_mods_unsubbed, iters)
|
|
||||||
self.thread_man.set_cleanup_func(func)
|
self.thread_man.set_cleanup_func(func)
|
||||||
|
|
||||||
def unsub_atomic_mod(self, mod: str) -> None:
|
def unsub_atomic_mod(self, mod: str) -> None:
|
||||||
@ -146,18 +145,21 @@ class ModManager:
|
|||||||
pass
|
pass
|
||||||
time.sleep(API_RATE_LIMIT)
|
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:
|
if self.store is None:
|
||||||
return
|
return
|
||||||
for _iter in iters:
|
for _iter in iters:
|
||||||
self.store.remove(_iter)
|
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()
|
model = self.treeview.get_model()
|
||||||
if model is None:
|
if model is None:
|
||||||
return
|
return
|
||||||
mods = len(model)
|
total_mods = len(model)
|
||||||
msg = self.format_mod_statusbar()
|
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:
|
def uncolorize_mods(self) -> None:
|
||||||
model = self.treeview.get_model()
|
model = self.treeview.get_model()
|
||||||
|
|||||||
@ -80,14 +80,18 @@ class ModSelectionPanel(Gtk.Box):
|
|||||||
self.highlight_stale_button.set_sensitive(True)
|
self.highlight_stale_button.set_sensitive(True)
|
||||||
|
|
||||||
def _on_mods_updated(self, emitter: "Emitter", msg: str, mods: int) -> None:
|
def _on_mods_updated(self, emitter: "Emitter", msg: str, mods: int) -> None:
|
||||||
if mods < 1:
|
self._toggle_panel_sensitivity(mods)
|
||||||
self.main_panel.set_sensitive(False)
|
|
||||||
self.stale_panel.set_sensitive(False)
|
def _toggle_panel_sensitivity(self, mods: int) -> None:
|
||||||
|
state = bool(mods)
|
||||||
|
for el in self.main_panel, self.stale_panel:
|
||||||
|
el.set_sensitive(state)
|
||||||
|
|
||||||
def _on_mods_highlighted(self, emitter: "Emitter") -> None:
|
def _on_mods_highlighted(self, emitter: "Emitter") -> None:
|
||||||
self.swap_sensitive(True)
|
self.swap_sensitive(True)
|
||||||
|
|
||||||
def _on_mod_page_toggled(self, emitter: "Emitter", state: bool) -> None:
|
def _on_mod_page_toggled(self, emitter: "Emitter", state: bool, mods: int) -> None:
|
||||||
|
self._toggle_panel_sensitivity(mods)
|
||||||
self.set_visible(state)
|
self.set_visible(state)
|
||||||
|
|
||||||
def swap_sensitive(self, state: bool) -> None:
|
def swap_sensitive(self, state: bool) -> None:
|
||||||
|
|||||||
@ -64,10 +64,15 @@ class Mods(Gtk.Box):
|
|||||||
self.controller.open_offline()
|
self.controller.open_offline()
|
||||||
|
|
||||||
def _on_unmap(self, widget: Self) -> None:
|
def _on_unmap(self, widget: Self) -> None:
|
||||||
self.emitter.emit("mod_page_toggled", False)
|
self.emitter.emit("mod_page_toggled", False, 0)
|
||||||
|
|
||||||
def _on_map(self, widget: Self) -> None:
|
def _on_map(self, widget: Self) -> None:
|
||||||
self.emitter.emit("mod_page_toggled", True)
|
model = self.tree.get_model()
|
||||||
|
if model is None:
|
||||||
|
mods = 0
|
||||||
|
else:
|
||||||
|
mods = len(model)
|
||||||
|
self.emitter.emit("mod_page_toggled", True, mods)
|
||||||
# TODO: delegation
|
# TODO: delegation
|
||||||
# NOTE: handles going back from offline mods page
|
# NOTE: handles going back from offline mods page
|
||||||
# more generic cache restoration method
|
# more generic cache restoration method
|
||||||
|
|||||||
8
tests/fixtures/dzg.versions
vendored
Normal file
8
tests/fixtures/dzg.versions
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
1559212036,1771519119
|
||||||
|
1564026768,1770917948
|
||||||
|
2545327648,1780174455
|
||||||
|
2276010135,1756744083
|
||||||
|
1654462998,1780501511
|
||||||
|
3410710885,1752864732
|
||||||
|
2918418331,1780413260
|
||||||
|
3739934289,1780855136
|
||||||
52
tests/test_mod_signatures.py
Normal file
52
tests/test_mod_signatures.py
Normal file
@ -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"]
|
||||||
Loading…
Reference in New Issue
Block a user