Compare commits

..
1 Commits
Author SHA1 Message Date
aclist c2cf996f92 Merge fa8792ba69 into f839001097 2026-06-20 10:45:45 +00:00
34 changed files with 166 additions and 345 deletions

No files matched your search

+7 -17
View File
@@ -49,7 +49,6 @@ 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
@@ -58,10 +57,9 @@ 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:
@@ -78,7 +76,6 @@ 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("*"):
@@ -126,27 +123,20 @@ def _hash(uid: str, use_custom: bool = False) -> str:
return prefix + md5.hexdigest()[:8]
def remove_stale_signatures(
config: Path, versions: Path, ids: list[int] | None = None
) -> None:
def remove_stale_signatures(config: Path, versions: Path) -> 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)
if ids is None:
local_ids = get_local_mod_ids(steam_path)
ids = get_local_mod_ids(steam_path)
with open(versions, "r") as f:
lines = f.readlines()
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]
for line in lines:
uid = int(line.split(",")[0])
if uid not in ids:
lines.remove(line)
with open(versions, "w") as f:
for line in lines:
f.write(line)
+1 -2
View File
@@ -289,14 +289,13 @@ def query_direct(ip: str, qport: int, timeout: float = 3.0) -> dict[str, Any] |
def get_details(record: Record) -> Details:
# TODO: consolidate try/except statements
ip = record.ip
qport = record.qport
default_str = strings.none_provided
try:
info = a2s.info((ip, qport))
except (TimeoutError, a2s.exceptions.BrokenMessageError):
except TimeoutError:
return Details(None, default_str, False)
try:
rules = dayzquery.dayz_rules((ip, qport))
+1 -3
View File
@@ -10,6 +10,7 @@ from shlex import shlex
from pathlib import Path
from dzgui.init.prereqs import has_steam_client
from dzgui.api.mods import _hash
from dzgui.const.constants import (
APPID_DAYZ,
APP_NAME,
@@ -57,9 +58,6 @@ def get_steam_paths() -> list[tuple[Path, str]]:
def concat_mods(mods: list[str]) -> str:
# TODO: circular import workaround
from dzgui.api.mods import _hash
hashes = []
for mod in mods:
md5sum = _hash(mod)
-109
View File
@@ -1,109 +0,0 @@
import logging
import os
from typing import TYPE_CHECKING
from dzgui.const.constants import APP_NAME
from dzgui.const.enum import Preferences
from dzgui.config.query import lookup
from dzgui.config.userprefs import UserPrefs
from dzgui.config.xdg import get_xdg_paths, parse_filepaths
from dzgui.init.migrate import (
has_new_config,
copy_state_files,
migrate_cols_file,
)
from dzgui.init.flock import lock_acquire
from dzgui.init.prereqs import has_steam_client
from dzgui.strings import boot
# from dzgui.util.map_count import get_map_count
from dzgui.util.deck import is_steam_deck, is_game_mode
from dzgui.util.localize import set_locale
from dzgui.util.strings import init
from dzgui.views.base import App
from dzgui.views.dialogs.boot import BootWindow
from dzgui.views.dialogs.early_alert import EarlyAlertDialog
from dzgui.views.dialogs.wizard import SetupWizard
if TYPE_CHECKING:
from pathlib import Path
logger = logging.getLogger(APP_NAME)
# TODO: profile load time
def make_parents(path: "Path") -> None:
path.parent.mkdir(parents=True, exist_ok=True)
def setup_logger(log_path: "Path") -> None:
_format = (
"%(asctime)s␞%(levelname)s␞%(filename)s::%(funcName)s::%(lineno)s␞%(message)s"
)
fh = logging.FileHandler(log_path)
formatter = logging.Formatter(_format)
fh.setFormatter(formatter)
fh.setLevel(logging.DEBUG)
logger.setLevel(logging.DEBUG)
logger.addHandler(fh)
def load_gui(version: str, is_debug: bool) -> None:
lock = lock_acquire() # noqa
set_locale()
# NOTE: consider aborting this check if steam deck
xdg_paths = get_xdg_paths()
XDG = parse_filepaths(xdg_paths)
if XDG.resolution.parent.is_dir() is False:
make_parents(XDG.resolution)
if XDG.debug.is_file() is False:
make_parents(XDG.debug)
_is_steam_deck = is_steam_deck()
_is_game_mode = is_game_mode() if _is_steam_deck else False
if _is_game_mode:
# NOTE: this may no longer be necessary on newer versions of SteamOS
del os.environ["GTK_IM_MODULE"]
if has_new_config(XDG.config) is False:
migrate_cols_file(XDG.columns)
copy_state_files(xdg_paths["XDG_STATE_HOME"])
# TODO: add logging inside wizard
SetupWizard(_is_steam_deck, XDG.config)
# NOTE: implies that setup wizard failed or was closed
if has_new_config(XDG.config) is False:
return
setup_logger(XDG.debug)
with open(XDG.debug, "w") as f:
f.truncate(0)
if _is_steam_deck is False:
# TODO: sudo escalation dialog
# count = get_map_count()
# TODO: move into module
if has_steam_client() is False:
EarlyAlertDialog(init.requires_steam)
bootwin = BootWindow(XDG, version)
local_coords, latest_release = bootwin.get_results()
use_miles = lookup(XDG.config, Preferences.DIST)
prefs = UserPrefs(
is_steam_deck=_is_steam_deck,
is_game_mode=_is_game_mode,
is_debug=is_debug,
coords=local_coords,
version=version,
paths=XDG,
latest_release=latest_release,
use_miles=use_miles,
)
print(boot.all_ok)
App(prefs)
-6
View File
@@ -3,8 +3,6 @@ import shlex
from pathlib import Path
from typing import Any
from dzgui.const.boilerplate import config_boilerplate
"""
Convert legacy dztuirc to config.json
@@ -91,8 +89,4 @@ def rc2json(file: Path) -> str:
keys["ip_list"] = ips
keys["use_miles"] = False
keys["start_tab"] = 0
# NOTE: workaround for DZGUI 6 logic (see #375)
for key in config_boilerplate.keys():
if key not in keys:
keys[key] = config_boilerplate[key]
return json.dumps(keys, indent=2)
+2 -2
View File
@@ -81,8 +81,8 @@ class Emitter(GObject.GObject):
def distcalc_started(self) -> None:
pass
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(bool, int))
def mod_page_toggled(self, state: bool, mods: int) -> None:
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(bool,))
def mod_page_toggled(self, state: bool) -> None:
pass
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(bool,))
+1
View File
@@ -205,6 +205,7 @@ class Controller(GObject.GObject):
self.mediator.grid.notebook.settings.populate_settings()
except Exception as e:
msg = format_exception(e)
print(msg)
logger.critical(msg)
return
case ButtonType.MODS:
+1 -1
View File
@@ -44,7 +44,7 @@ def has_libgi() -> bool:
return exists
def test_libgi_missing() -> None:
def test_missing_lib() -> bool:
msg = f"System is missing the required library '{LIB}'. Install it via your system package manager."
if has_libgi() is False:
print(msg)
+1 -9
View File
@@ -1,12 +1,10 @@
import psutil
import subprocess
import shutil
import logging
from warnings import deprecated
from dzgui.const.constants import (
APP_NAME,
DAYZ_BINARY,
STEAM_CMD,
FLATPAK_APPID,
@@ -15,10 +13,6 @@ from dzgui.const.constants import (
FLATPAK_SANDBOX,
)
from dzgui.util.format import format_exception
logger = logging.getLogger(APP_NAME)
# TODO: move to util.proc
def is_dayz_running() -> bool:
@@ -28,9 +22,7 @@ def is_dayz_running() -> bool:
for proc in psutil.process_iter():
try:
procs.append(proc.cmdline())
except Exception as e:
msg = format_exception(e)
logger.warning(msg)
except Exception:
continue
return any(substring in item for sublist in procs for item in sublist)
+103 -6
View File
@@ -1,11 +1,40 @@
import argparse
import logging
import os
import sys
import warnings
from typing import TYPE_CHECKING
from dzgui.const.constants import APP_NAME
from dzgui.init.libgi import test_libgi_missing
from dzgui.const.enum import Preferences
from dzgui.config.query import lookup
from dzgui.config.userprefs import UserPrefs
from dzgui.config.xdg import get_xdg_paths, parse_filepaths
from dzgui.init.flock import lock_acquire
from dzgui.init.migrate import (
has_new_config,
copy_state_files,
migrate_cols_file,
)
from dzgui.init.prefix import get_version
from dzgui.util.strings import flags
from dzgui.init.prereqs import has_steam_client
from dzgui.strings import boot
# from dzgui.util.map_count import get_map_count
from dzgui.util.deck import is_steam_deck, is_game_mode
from dzgui.util.localize import set_locale
from dzgui.util.strings import init, flags
from dzgui.views.base import App
from dzgui.views.dialogs.boot import BootWindow
from dzgui.views.dialogs.early_alert import EarlyAlertDialog
from dzgui.views.dialogs.wizard import SetupWizard
if TYPE_CHECKING:
from pathlib import Path
logger = logging.getLogger(APP_NAME)
parser = argparse.ArgumentParser(description=flags.description)
parser.add_argument("-v", "--version", action="store_true", help=flags.version)
@@ -14,6 +43,11 @@ parser.add_argument("-d", "--debug", action="store_true", help=flags.debug)
args = parser.parse_args()
# TODO: profile load time
def make_parents(path: "Path") -> None:
path.parent.mkdir(parents=True, exist_ok=True)
def uninstall() -> None:
# TODO: uninstall data files (-u)
# -u removes state, log, freedesktop
@@ -23,7 +57,21 @@ def uninstall() -> None:
pass
def setup_logger(log_path: "Path") -> None:
_format = (
"%(asctime)s␞%(levelname)s␞%(filename)s::%(funcName)s::%(lineno)s␞%(message)s"
)
fh = logging.FileHandler(log_path)
formatter = logging.Formatter(_format)
fh.setFormatter(formatter)
fh.setLevel(logging.DEBUG)
logger.setLevel(logging.DEBUG)
logger.addHandler(fh)
def main() -> None:
lock = lock_acquire() # noqa
if args.version is True:
print(get_version())
sys.exit(0)
@@ -34,11 +82,60 @@ def main() -> None:
warnings.filterwarnings("default", category=DeprecationWarning)
version = get_version()
set_locale()
print(f"{APP_NAME} {version}")
test_libgi_missing()
# NOTE: only import ligbirepository modules after the above check
from dzgui.app_init import load_gui
# NOTE: consider aborting this check if steam deck
xdg_paths = get_xdg_paths()
XDG = parse_filepaths(xdg_paths)
load_gui(version, args.debug)
if XDG.resolution.parent.is_dir() is False:
make_parents(XDG.resolution)
if XDG.debug.is_file() is False:
make_parents(XDG.debug)
_is_steam_deck = is_steam_deck()
_is_game_mode = is_game_mode() if _is_steam_deck else False
if _is_game_mode:
# NOTE: this may no longer be necessary on newer versions of SteamOS
del os.environ["GTK_IM_MODULE"]
if has_new_config(XDG.config) is False:
migrate_cols_file(XDG.columns)
copy_state_files(xdg_paths["XDG_STATE_HOME"])
# TODO: add logging inside wizard
SetupWizard(_is_steam_deck, XDG.config)
# NOTE: implies that setup wizard failed or was closed
if has_new_config(XDG.config) is False:
return
setup_logger(XDG.debug)
with open(XDG.debug, "w") as f:
f.truncate(0)
if _is_steam_deck is False:
# TODO: sudo escalation dialog
# count = get_map_count()
# TODO: move into module
if has_steam_client() is False:
EarlyAlertDialog(init.requires_steam)
bootwin = BootWindow(XDG, version)
local_coords, latest_release = bootwin.get_results()
use_miles = lookup(XDG.config, Preferences.DIST)
prefs = UserPrefs(
is_steam_deck=_is_steam_deck,
is_game_mode=_is_game_mode,
is_debug=args.debug,
coords=local_coords,
version=version,
paths=XDG,
latest_release=latest_release,
use_miles=use_miles,
)
print(boot.all_ok)
App(prefs)
+13 -24
View File
@@ -35,11 +35,7 @@ from dzgui.const.constants import (
from dzgui.const.enum import NotebookPage, Preferences
from dzgui.init.proc import is_dayz_running, is_steam_running
from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager
from dzgui.strings.dialogs import (
waiting_for_launch,
waiting_for_mods,
waiting_for_directories,
)
from dzgui.strings.dialogs import waiting_for_launch, waiting_for_mods, waiting_for_directories
from dzgui.strings.server_mods import checkmark, resync
from dzgui.util.format import format_mib
from dzgui.util.strings import dialog, server_timeout
@@ -148,14 +144,21 @@ class ConnectionManager:
remote_mods: list[list[str]] = []
if res.is_modded():
try:
remote_mods, missing_mods = self._query_modlist(record)
self.missing_mods = missing_mods
remote_mods = self._query_modlist(record)
self.remote_mod_ids = [mod[1] for mod in remote_mods]
except Exception as e:
logger.warning(e)
self.thread_man.set_cleanup_func(failure_func, destroy_first=True)
return
hashes = get_remote_signatures(self.remote_mod_ids)
version_file = prefs.paths.version
self.missing_mods = get_needs_update(version_file, hashes)
for mod in remote_mods:
if any(mod[1] in tuple for tuple in self.missing_mods):
mod[2] = resync
if local_version is not None:
pefile_path = PeFile.get_pefile_path(steam_path, info.game_id)
total, used, free = shutil.disk_usage(pefile_path)
@@ -219,13 +222,10 @@ class ConnectionManager:
StoredFunc(self._present_details_dialog, details), destroy_first=True
)
def _query_modlist(
self, record: Servers.Record
) -> tuple[list[list[str]], list[tuple[str, str, int, int]]]:
def _query_modlist(self, record: Servers.Record) -> list[list[str]]:
mods = Servers.get_rules(record)
steam_path = self.controller.query_config(Preferences.DEFAULT)
local = get_local_mod_ids(steam_path)
alpha_mods: list[list[str]] = [
[
mod.name,
@@ -235,23 +235,12 @@ class ConnectionManager:
for mod in mods
]
alpha_mods.sort(key=lambda x: x[0])
prefs = self.controller.get_prefs()
version_file = prefs.paths.version
remote_mod_ids = [mod[1] for mod in alpha_mods]
hashes = get_remote_signatures(remote_mod_ids)
missing_mods = get_needs_update(version_file, hashes)
for mod in alpha_mods:
if any(mod[1] in tuple for tuple in missing_mods):
mod[2] = resync
return alpha_mods, missing_mods
return alpha_mods
@call_on_thread(dialog.querying)
def query_modlist_and_present(self, record: Servers.Record) -> None:
try:
mods, missing_mods = self._query_modlist(record)
mods = self._query_modlist(record)
except Exception:
self.thread_man.set_cleanup_func(
StoredFunc(self._server_timeout), destroy_first=True
-1
View File
@@ -80,7 +80,6 @@ class FilterManager:
if maps is None:
return
if len(maps) < 1:
self.reinit_map_store()
return
self.reinit_map_store()
+6 -15
View File
@@ -23,7 +23,6 @@ from dzgui.model.model_factory import FastInsertListStore, ModelFactory
from dzgui.strings import dialogs
from dzgui.util.format import format_mods
from dzgui.util.strings import server_timeout
from dzgui.util.symlink import rebuild_symlinks
from dzgui.views.dialogs.generic import ExceptionDialog
@@ -67,13 +66,9 @@ class ModManager:
self.thread_man.set_cleanup_func(func)
return
prefs = self.controller.get_prefs()
rebuild_symlinks(prefs.paths.config)
self.store = ModelFactory().make_mod_store()
self.store.extend(mods)
func = StoredFunc(self._on_mods_loaded)
self.thread_man.set_cleanup_func(func)
def set_store(self, store: "FastInsertListStore") -> None:
@@ -98,7 +93,6 @@ class ModManager:
continue
mod, _iter = res
mods.append((mod, _iter))
self.thread_man.set_job_count(len(mods))
self.unsub_all_mods(mods)
def get_mod_from_tree_path(
@@ -115,10 +109,10 @@ class ModManager:
def unsub_all_mods(self, mods: list[tuple[str, Gtk.TreeIter]]) -> None:
for mod, _iter in mods:
self.unsub_atomic_mod(mod)
self.thread_man.increment_dialog()
time.sleep(API_RATE_LIMIT)
func = StoredFunc(self._on_mods_unsubbed, mods)
iters = [_iter for mod, _iter in mods]
func = StoredFunc(self._on_mods_unsubbed, iters)
self.thread_man.set_cleanup_func(func)
def unsub_atomic_mod(self, mod: str) -> None:
@@ -145,21 +139,18 @@ class ModManager:
pass
time.sleep(API_RATE_LIMIT)
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]
def _on_mods_unsubbed(self, iters: list[Gtk.TreeIter]) -> None:
if self.store is None:
return
for _iter in iters:
self.store.remove(_iter)
# TODO: process config path in called function
remove_stale_signatures(self.prefs.paths.config, self.prefs.paths.version, mods)
remove_stale_signatures(self.prefs.paths.config, self.prefs.paths.version)
model = self.treeview.get_model()
if model is None:
return
total_mods = len(model)
mods = len(model)
msg = self.format_mod_statusbar()
self.emitter.emit("mods_updated", msg, total_mods)
self.emitter.emit("mods_updated", msg, mods)
def uncolorize_mods(self) -> None:
model = self.treeview.get_model()
+1 -3
View File
@@ -395,10 +395,8 @@ class ServerModelManager:
self.first_iteration = False
def _cleanup_on_success(self) -> None:
proxy = self.proxy_man.get_proxy_model()
proxy = self._get_proxy_man().get_proxy_model()
self.tv.set_model(proxy)
if self.preserve_on_fail is True:
self.proxy_man.wipe_cache()
self.emitter.emit("servers_loaded", self.enum)
if self.first_iteration:
+3 -2
View File
@@ -130,6 +130,7 @@ servers = {
"Enter/space/double-click": "connect to server",
"Right-click/Ctrl-l": "additional context menus",
"Ctrl-r": "refresh players",
"Ctrl-p": "refresh ping",
"Ctrl-f": "jump to keyword search field",
"Ctrl-m": "jump to maps field",
"Ctrl-d": "select default LAN port",
@@ -147,8 +148,8 @@ servers = {
vim = {
"j": "Move down a row/scroll up",
"k": "Move up a row/scroll down",
"h": "Jump to main area from sidebar",
"l": "Jump to sidebar from main area",
"l": "Jump to main area from sidebar",
"h": "Jump to sidebar from main area",
"g": "Jump to first row/top of page",
"G": "Jump to last row/bottom of page",
}
-2
View File
@@ -141,8 +141,6 @@ class RefreshButton(IconTextButton):
def _on_refresh_clicked(self, button: Self) -> None:
"""Spawned in a thread"""
if self.controller.get_active_treeview().is_loaded() is False:
return
self.is_clicked = True
self.controller.refresh_tree()
# TODO: get server tab enum
+4 -8
View File
@@ -80,18 +80,14 @@ class ModSelectionPanel(Gtk.Box):
self.highlight_stale_button.set_sensitive(True)
def _on_mods_updated(self, emitter: "Emitter", msg: str, mods: int) -> None:
self._toggle_panel_sensitivity(mods)
def _toggle_panel_sensitivity(self, mods: int) -> None:
state = bool(mods)
for el in self.main_panel, self.stale_panel:
el.set_sensitive(state)
if mods < 1:
self.main_panel.set_sensitive(False)
self.stale_panel.set_sensitive(False)
def _on_mods_highlighted(self, emitter: "Emitter") -> None:
self.swap_sensitive(True)
def _on_mod_page_toggled(self, emitter: "Emitter", state: bool, mods: int) -> None:
self._toggle_panel_sensitivity(mods)
def _on_mod_page_toggled(self, emitter: "Emitter", state: bool) -> None:
self.set_visible(state)
def swap_sensitive(self, state: bool) -> None:
+2 -7
View File
@@ -64,15 +64,10 @@ class Mods(Gtk.Box):
self.controller.open_offline()
def _on_unmap(self, widget: Self) -> None:
self.emitter.emit("mod_page_toggled", False, 0)
self.emitter.emit("mod_page_toggled", False)
def _on_map(self, widget: Self) -> None:
model = self.tree.get_model()
if model is None:
mods = 0
else:
mods = len(model)
self.emitter.emit("mod_page_toggled", True, mods)
self.emitter.emit("mod_page_toggled", True)
# TODO: delegation
# NOTE: handles going back from offline mods page
# more generic cache restoration method
+2 -2
View File
@@ -307,12 +307,12 @@ class PreConnectionAssistant(Gtk.Box):
self.mod_count.set_text(msg)
if prereqs.required_space != 0:
self.ok.set_label(preconnect.connect)
pretty = number(prereqs.required_space)
suffix = f" Need to download {pretty} MiB of mod updates."
prefix = preconnect.total_mods
self.mod_count.set_text(f"{prefix}{str(total_mods)}.{suffix}")
else:
self.ok.set_label(preconnect.connect)
if prereqs.is_last_server:
self.connect_last.show()
+1 -2
View File
@@ -4,7 +4,7 @@ description = "DayZ server browser and mod manager for Linux"
authors = [
{name = "aclist"}
]
version = "7.0.0b14"
version = "7.0.0b13"
license = "GPL-3.0-or-later"
license-files = ["LICENSE"]
readme = "README.md"
@@ -107,7 +107,6 @@ config-settings-package = { pygobject-stubs = { config = "Gtk3,Gdk3,Soup2" } }
[tool.pytest.ini_options]
markers = [
"config: config file keys/values",
"mods: tests mod metadata/link creation",
"pefile: validate PE files",
"post_install: requires a completed installation",
"slow: long-running tests",
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
View File
@@ -0,0 +1,3 @@
from dzgui.api.mods import tokenize
print(tokenize("meta4.cpp"))
-8
View File
@@ -1,8 +0,0 @@
1559212036,1771519119
1564026768,1770917948
2545327648,1780174455
2276010135,1756744083
1654462998,1780501511
3410710885,1752864732
2918418331,1780413260
3739934289,1780855136
-42
View File
@@ -1,42 +0,0 @@
#Path to DayZ installation
steam_path="/tmp"
#Battlemetrics API key
api_key=""
#Favorited server IP:PORT array
ip_list=(
)
#Favorite server to fast-connect to (limit one)
fav_server=""
#Favorite server label (human readable)
fav_label=""
#Custom player name (optional, required by some servers)
name=""
#Set to 1 to perform dry-run and print launch options
debug="1"
#Toggle stable/testing branch
branch="testing"
#Steam API key
steam_api=""
#Auto-install mods
auto_install="2"
#Automod staging directory
staging_dir="/tmp"
#Path to default Steam client
default_steam_path="/tmp"
#Preferred Steam launch command (for Flatpak support)
preferred_client="steam"
#DZGUI source path
src_path=""
File renamed without changes.
File renamed without changes.
+3 -15
View File
@@ -1,7 +1,6 @@
import json
import pytest
from dzgui.const.boilerplate import config_boilerplate
from dzgui.config.query import get_config
from dzgui.config.xdg import get_xdg_paths, parse_filepaths
from dzgui.config import convert
@@ -12,11 +11,7 @@ pytestmark = pytest.mark.config
@pytest.fixture
def legacy_config():
return fixture_path("dztuirc_1")
@pytest.fixture
def unset_values():
return fixture_path("dztuirc_3")
return fixture_path("dztuirc_one")
@pytest.fixture
@@ -65,8 +60,8 @@ def test_contains_invalid_values(keys, config):
@pytest.mark.parametrize(
"fixture, expect",
[
("dztuirc_1", (False, True, True)),
("dztuirc_2", (False, False, False)),
("dztuirc_one", (False, True, True)),
("dztuirc_two", (False, False, False)),
],
)
def test_bool_conversion(fixture, expect):
@@ -91,12 +86,5 @@ def test_key_conversion(legacy_config):
for key in keys:
assert key not in j
def test_missing_values(unset_values):
j = convert.rc2json(unset_values)
j = json.loads(j)
assert j.keys() == config_boilerplate.keys()
# TODO: test that when a config file is created from scratch, it contains all values
-52
View File
@@ -1,52 +0,0 @@
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"]
+11 -7
View File
@@ -1,13 +1,17 @@
import pytest
from pathlib import Path
from dzgui.api.mods import tokenize
from tests.fixtures import fixture_path
@pytest.mark.mods
@pytest.mark.parametrize("i", range(1, 7))
def test_modmeta(i: int) -> None:
fixture = fixture_path(f"cpp/mod{i}")
path = Path(fixture)
meta = tokenize(path)
@pytest.mark.parametrize("fixture", [
fixture_path("cpp/meta1.cpp"),
fixture_path("cpp/meta2.cpp"),
fixture_path("cpp/meta3.cpp"),
fixture_path("cpp/meta4.cpp"),
fixture_path("cpp/meta5.cpp"),
fixture_path("cpp/meta6.cpp"),
]
)
def test_modmeta(fixture: str) -> None:
meta = tokenize(fixture)
assert meta["name"] == "ModName"