Compare commits

..
1 Commits
Author SHA1 Message Date
aclist 7ac079577f Merge 1b344c1260 into 5ba6b6c040 2026-05-21 11:56:55 +00:00
27 changed files with 128 additions and 347 deletions

No files matched your search

-1
View File
@@ -34,7 +34,6 @@
- Early load alerts button
- Preconnect dialog
- Preconnect warnings/failsafes like filesize
- Save filters per server context between sessions
## Changed
+11 -2
View File
@@ -84,6 +84,7 @@ class Controller(GObject.GObject):
self.emitter = Emitter()
self.emitter.connect("map_selection_changed", self._on_map_selection_changed)
self.emitter.connect("check_toggled", self._on_check_toggled)
self.emitter.connect("servers_loaded_init", self._on_servers_loaded_init)
# NOTE: suppress requests until entire UI is loaded
self.loaded = False
@@ -320,7 +321,6 @@ class Controller(GObject.GObject):
self.mediator.filters.button_grid.block_toggles(True)
self.populate_filter_prefs()
self.mediator.filters.button_grid.block_toggles(False)
self.emitter.emit("lan_page_initialized")
ServerModelManager(self, tv).load()
def populate_filter_prefs(self) -> None:
@@ -347,7 +347,16 @@ class Controller(GObject.GObject):
filter_man = self.get_filter_man()
return filter_man.get_filters()
# FIXME: wipe maps store when changing tabs if model is none
# TODO: rename
def _on_servers_loaded_init(self, emitter: "Emitter") -> None:
"""Triggered after servers load but prior to maps loading"""
# FIXME: wipe maps store when changing tabs if model is none
# e.g. select recent, toggle map, then select lan -> not wiped
tv = self.get_active_treeview()
if tv.loaded is False:
return
store = self.get_map_store()
self.emitter.emit("load_maps", store)
def has_server_model(self) -> bool:
treeview = self.get_active_treeview()
-1
View File
@@ -34,7 +34,6 @@
- Early load alerts button
- Preconnect dialog
- Preconnect warnings/failsafes like filesize
- Save filters per server context between sessions
## Changed
+8 -20
View File
@@ -1,7 +1,6 @@
import shutil
from pathlib import Path
from typing import Any
from dzgui.const.constants import LEGACY_CONFIG_PATH, LEGACY_COLS_PATH, LEGACY_IPS_PATH
from dzgui.config.convert import rc2json
from dzgui.util._json import read_json, write_json
@@ -18,28 +17,17 @@ def has_new_config(config: Path) -> bool:
return config.exists()
def convert_cols_file(res: Path) -> Any | None:
j = read_json(res)
cols = j["cols"]
# NOTE: implies prior conversion
if "View" in cols:
return None
# NOTE: user may not have changed these widths in API 6
try:
cols["View"] = cols.pop("Perspective")
cols["Max"] = cols.pop("Maximum")
except Exception:
pass
return j
def migrate_cols_file(res: Path) -> None:
# NOTE: filename "dzg.columns.json" is API 7 spec
# NOTE: dzg.columns.json is API 7 spec
old_res = Path.home() / LEGACY_COLS_PATH
if old_res.is_file():
j = convert_cols_file(old_res)
if j is not None:
write_json(j, res)
j = read_json(old_res)
cols = j["cols"]
if "View" in cols:
return
cols["View"] = cols.pop("Perspective")
cols["Max"] = cols.pop("Maximum")
write_json(j, res)
def copy_state_files(state_path: Path) -> None:
+3 -7
View File
@@ -121,6 +121,8 @@ def main() -> None:
with open(XDG.debug, "w") as f:
f.truncate(0)
latest_release = check_updates(version)
if _is_steam_deck is False:
# TODO: sudo escalation dialog
# count = get_map_count()
@@ -128,22 +130,16 @@ def main() -> None:
if has_steam_client() is False:
EarlyAlertDialog(init.requires_steam)
is_dayz_installed(XDG.config)
# TODO: slow running procs here--needs dialog
# NOTE: clears versions file of unlinked mods
rebuild_symlinks(XDG.config)
remove_stale_signatures(XDG.config, XDG.version)
is_dayz_installed(XDG.config)
# TODO: handle IP DB failure and use coords fallback
# TODO: drop this after dialog is complete
print("Fetching geolocation data, may take some time...")
get_ipdb(XDG.ips)
local_coords = get_local_coords(XDG.ips)
use_miles = lookup(XDG.config, Preferences.DIST)
latest_release = check_updates(version)
prefs = UserPrefs(
is_steam_deck=_is_steam_deck,
is_game_mode=_is_game_mode,
+3 -9
View File
@@ -161,7 +161,7 @@ class ConnectionManager:
if len(self.missing_mods) > 0:
required_size = sum(row[2] for row in self.missing_mods)
required_mib = format_mib(required_size)
free_mib = format_mib(free)
free_mib = format_mib(required_size)
dayz_running = is_dayz_running()
@@ -222,8 +222,7 @@ class ConnectionManager:
def query_modlist_and_present(self, record: Servers.Record) -> None:
try:
mods = self._query_modlist(record)
except Exception as e:
print(f"{type(e).__name__}: {e}")
except Exception:
self.thread_man.set_cleanup_func(
StoredFunc(self._server_timeout), destroy_first=True
)
@@ -280,13 +279,8 @@ class ConnectionManager:
for title, mod, stamp, size in self.missing_mods:
# TODO: check cancel and exit events
if self.controller.get_exit_event().is_set():
return
if self.controller.get_cancel_event().is_set():
self.controller.clear_cancel_event()
return
enqueue_mod(mod, self.appid)
time.sleep(3)
time.sleep(2)
if raise_window is True:
logger.info("Bringing window to foreground")
-67
View File
@@ -1,67 +0,0 @@
import logging
import requests
import shutil
import subprocess
import tarfile
from typing import TYPE_CHECKING
from dzgui.const.constants import (
APP_NAME,
TMP_EXE,
TMP_PATH,
TMP_TARBALL,
)
from dzgui.strings import dialogs
from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager
from dzgui.views.dialogs.generic import ExceptionDialog, QuitDialog
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib # noqa E402
if TYPE_CHECKING:
from dzgui.controllers.mc import Controller
logger = logging.getLogger(APP_NAME)
class UpdateManager:
def __init__(self, controller: "Controller") -> None:
self.thread_man = ThreadingManager(controller)
self.controller = controller
@call_on_thread(dialogs.fetching_update)
def update_version(self, exe_path: str, url: str) -> None:
try:
res = requests.get(url)
if res.status_code == 200:
with open(TMP_TARBALL, "wb") as file:
file.write(res.content)
with tarfile.open(TMP_TARBALL) as tar:
tar.extractall(TMP_PATH)
shutil.move(TMP_EXE, exe_path)
proc = subprocess.run([exe_path, "self", "restore"])
if proc.returncode == 0:
func = StoredFunc(self._on_update_success)
self.thread_man.set_cleanup_func(func, destroy_first=True)
else:
msg = dialogs.failed_to_update
func = StoredFunc(self._on_update_failure, msg)
self.thread_man.set_cleanup_func(func, destroy_first=True)
except Exception as e:
func = StoredFunc(self._on_update_failure, e)
self.thread_man.set_cleanup_func(func, destroy_first=True)
logger.warning(e)
def _on_update_success(self) -> None:
msg = dialogs.update_success
dialog = QuitDialog(self.controller, msg)
dialog.run()
def _on_update_failure(self, msg: str) -> None:
dialog = ExceptionDialog(self.controller, msg)
dialog.run()
+1
View File
@@ -122,6 +122,7 @@ class ProxyModelManager:
# TODO: filter cache: return a dataclass object with clearly enumerated map, keyword, and filter values
# instead of just a serial list of strings
filters = self.filter_man.get_all_filters()
print(filters)
if skip_cache is False:
if filters in self.filter_cache:
+6 -10
View File
@@ -243,11 +243,9 @@ class ServerModelManager:
filter_man = self.tv.get_filter_man()
maps = self._get_new_maps()
filter_man.set_unique_maps(maps)
store = filter_man.get_map_store()
self.first_iteration = False
self.emitter.emit("load_maps", store)
# self.emitter.emit("servers_loaded_init")
self.emitter.emit("servers_loaded_init")
def add_to_history(self, record: dict[str, Any]) -> None:
proxy_man = self._get_proxy_man()
@@ -324,7 +322,6 @@ class ServerModelManager:
self.thread_man.set_cleanup_func(func)
return
config_man.add_saved_server(fqip)
# FIXME: this is valid if saved servers tab is already open,
# but not if app was just booted; causes single row to appear prematurely
if proxy_man.has_control_model() is False:
@@ -375,31 +372,30 @@ class ServerModelManager:
proxy = self._get_proxy_man().get_proxy_model()
self.tv.set_model(proxy)
if self.controller.get_active_treeview().get_enum == ServerTab.SAVED:
self.emitter.emit("servers_loaded", self.enum)
self.emitter.emit("servers_loaded", self.enum)
filter_man = self.tv.get_filter_man()
# NOTE: maps are set outside of thread because it triggers map changed signals
maps = self._get_new_maps()
filter_man.set_unique_maps(maps)
store = filter_man.get_map_store()
self.emitter.emit("load_maps", store)
self.first_iteration = False
self.emitter.emit("servers_loaded_init")
self.emitter.emit("saved_servers_changed")
def _update_maps(self) -> None:
filter_man = self.tv.get_filter_man()
filter_man.set_unique_maps(self._get_new_maps())
store = filter_man.get_map_store()
self.emitter.emit("load_maps", store)
self.emitter.emit("servers_loaded_init")
self.first_iteration = False
def _cleanup_on_success(self) -> None:
proxy = self._get_proxy_man().get_proxy_model()
self.tv.set_model(proxy)
# TODO: servers_loaded vs servers_reloaded
self.emitter.emit("servers_loaded", self.enum)
if self.first_iteration:
self._update_maps()
+1 -1
View File
@@ -12,7 +12,7 @@ def read_json(path: Path) -> Any:
raise e
def write_json(data: dict[str, Any], path: Path) -> None:
def write_json(data: dict, path: Path) -> None:
try:
j = json.dumps(data, indent=2)
path.write_text(j)
+7 -10
View File
@@ -43,14 +43,11 @@ def clone_symlinks(steam_path: Path) -> None:
# TODO: test these two operations
# use less time intensive logic like the above
try:
for file in exp_path.iterdir():
if file.is_symlink():
file.unlink()
for file in exp_path.iterdir():
if file.is_symlink():
file.unlink()
for file in dayz_path.iterdir():
if file.is_symlink():
uid = file.name
Path(exp_path / uid).symlink_to(dayz_path / uid)
except Exception as e:
logger.critical(e)
for file in dayz_path.iterdir():
if file.is_symlink():
uid = file.name
Path(exp_path / uid).symlink_to(dayz_path / uid)
+5 -12
View File
@@ -94,11 +94,9 @@ class RefreshButton(IconTextButton):
icon=REFRESH_ICON,
label=atomic_buttons.refresh,
)
self.controller = controller
emitter = self.controller.get_emitter()
self.loading = False
self.is_clicked = False
self.time = 30
@@ -112,21 +110,17 @@ class RefreshButton(IconTextButton):
def _on_refresh_clicked(self, button: Self) -> None:
"""Spawned in a thread"""
self.is_clicked = True
self.loading = True
self.controller.refresh_tree()
# TODO: get server tab enum
# if LAN tab, reload existing entries in place
def start_decrement(self, emitter: "Emitter", tab: "ServerTab") -> None:
if self.is_clicked is False:
return
if self.loading:
return
self.set_sensitive(False)
self.loading = True
self.is_clicked = False
self.show_time(True)
GLib.timeout_add_seconds(1, self.decrement)
self.set_sensitive(False)
self.loading = False
self.show_time(True)
GLib.timeout_add_seconds(1, self.decrement)
def decrement(self) -> bool:
self.time -= 1
@@ -134,7 +128,6 @@ class RefreshButton(IconTextButton):
self.time = 30
self.show_time(False)
self.set_sensitive(True)
self.loading = False
return False
self.show_time(True)
return True
+56 -11
View File
@@ -1,5 +1,9 @@
import logging
import os
import requests
import shutil
import subprocess
import tarfile
from typing import Literal, TYPE_CHECKING
@@ -9,14 +13,20 @@ from dzgui.const.constants import (
NO_FILL,
FILL,
NO_PADDING,
TMP_EXE,
TMP_PATH,
TMP_TARBALL,
)
from dzgui.const.update import ALLOW_UPDATES
from dzgui.const.enum import ServerTab
from dzgui.managers.update import UpdateManager
from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager
from dzgui.strings import dialogs
from dzgui.util.clip import copy_clipboard
from dzgui.views.components.buttonbox import ButtonBox
from dzgui.views.components.filter_panel import FilterPanel
from dzgui.views.components.mod_panel import ModSelectionPanel
from dzgui.views.components.buttons import IconTextButton, RefreshButton, KeysButton
from dzgui.views.dialogs.generic import ExceptionDialog, QuitDialog
import gi
@@ -35,6 +45,7 @@ class RightPanel(Gtk.Box):
def __init__(self, controller: "Controller"):
super().__init__(spacing=6, orientation=Gtk.Orientation.VERTICAL)
self.thread_man = ThreadingManager(controller)
self.controller = controller
self.controller.register_widget("right_panel", self)
@@ -85,20 +96,54 @@ class RightPanel(Gtk.Box):
valign=Gtk.Align.END,
spacing=10,
)
exe_path = os.getenv("PYAPP")
if exe_path and update is not None:
if ALLOW_UPDATES and update is not None:
self.update_button.set_halign(Gtk.Align.END)
self.gutter_box.add(self.update_button)
self.update_button.connect(
"clicked", self._on_update_button_clicked, exe_path, update
"clicked", self._on_update_button_clicked, update
)
self.gutter_box.add(eb)
self.pack_start(self.gutter_box, NO_EXPAND, FILL, NO_PADDING)
def _on_update_button_clicked(
self, button: Gtk.Button, exe_path: str, url: str
) -> None:
UpdateManager(self.controller).update_version(exe_path, url)
def _on_update_success(self) -> None:
msg = dialogs.update_success
dialog = QuitDialog(self.controller, msg)
dialog.run()
def _on_update_failure(self, msg: str) -> None:
dialog = ExceptionDialog(self.controller, msg)
dialog.run()
@call_on_thread(dialogs.fetching_update)
def _on_update_button_clicked(self, button: Gtk.Button, url: str) -> None:
try:
res = requests.get(url)
if res.status_code == 200:
with open(TMP_TARBALL, "wb") as file:
file.write(res.content)
with tarfile.open(TMP_TARBALL) as tar:
tar.extractall(TMP_PATH)
exe_path = os.getenv("PYAPP")
if exe_path is None:
msg = dialogs.failed_to_update
func = StoredFunc(self._on_update_failure, msg)
self.thread_man.set_cleanup_func(func, destroy_first=True)
return
shutil.move(TMP_EXE, exe_path)
proc = subprocess.run([exe_path, "self", "restore"])
if proc.returncode == 0:
func = StoredFunc(self._on_update_success)
self.thread_man.set_cleanup_func(func, destroy_first=True)
else:
msg = dialogs.failed_to_update
func = StoredFunc(self._on_update_failure, msg)
self.thread_man.set_cleanup_func(func, destroy_first=True)
except Exception as e:
func = StoredFunc(self._on_update_failure, e)
self.thread_man.set_cleanup_func(func, destroy_first=True)
logger.warning(e)
def _on_server_page_changed(
self, emitter: "Emitter", page: "ServerTreeView"
@@ -107,16 +152,16 @@ class RightPanel(Gtk.Box):
if page.loaded is True:
return
self.filters_vbox.set_sensitive(False)
# TODO: unless it is lan page
#self.refresh_button.set_sensitive(False)
def _on_lan_page_init(self, emitter: "Emitter") -> None:
self.filters_vbox.set_sensitive(False)
self.refresh_button.set_sensitive(False)
def _on_servers_loaded(self, emitter: "Emitter", context: "ServerTab") -> None:
# TODO: similar logic on notebook page change
state = self.controller.has_server_model()
self.filters_vbox.set_sensitive(state)
for el in self.filters_vbox, self.refresh_button:
el.set_sensitive(state)
def _on_version_clicked(self, widget: Gtk.EventBox, event: Gdk.EventButton) -> None:
def revert() -> Literal[False]:
-9
View File
@@ -1,9 +0,0 @@
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa
class NoOverlayScrolledWindow(Gtk.ScrolledWindow):
def __init__(self) -> None:
super().__init__(overlay_scrolling=False)
-2
View File
@@ -53,5 +53,3 @@ class EarlyIgnoreDialog(EarlyAlertDialog):
# TODO: reverse order
self.add_button("Ignore", Gtk.ResponseType.CANCEL)
# TODO: if exit, sys.exit(1), else pass
+1 -2
View File
@@ -1,6 +1,5 @@
from typing import TYPE_CHECKING
from dzgui.const.constants import LOG_FILTERS
from dzgui.views.components.scrollable import NoOverlayScrolledWindow
from dzgui.views.mixins.cursor_mixin import CursorMixin
from dzgui.views.mixins.help_menu_mixin import HelpMenuMixin
from dzgui.views.trees.tree_log import LogTreeView
@@ -22,7 +21,7 @@ class Log(CursorMixin, HelpMenuMixin, Gtk.Box): # type: ignore
NOTE: LogTreeView is kept in a separate ScrolledWindow so that
checkboxes will be flush on bottom
"""
self.scrolled = NoOverlayScrolledWindow()
self.scrolled = Gtk.ScrolledWindow()
self.treeview = LogTreeView(controller)
self.scrolled.add(self.treeview)
+1 -3
View File
@@ -1,5 +1,4 @@
from typing import Self, TYPE_CHECKING
from dzgui.views.components.scrollable import NoOverlayScrolledWindow
from dzgui.views.trees.tree_mods import ModTreeView
import gi
@@ -11,8 +10,7 @@ if TYPE_CHECKING:
from dzgui.controllers.mc import Controller
class Mods(NoOverlayScrolledWindow):
class Mods(Gtk.ScrolledWindow):
def __init__(self, controller: "Controller") -> None:
super().__init__()
+13
View File
@@ -162,6 +162,19 @@ class ServerNotebook(Gtk.ScrolledWindow):
return tv
raise ValueError("No treeview set")
def add_notification(self) -> None:
saved = self.notebook.get_nth_page(1)
if saved is None:
return
text = self.notebook.get_tab_label_text(saved)
if text is None:
return
# TODO: strings
if "*" in text:
return
text += "*"
self.notebook.set_tab_label_text(saved, text)
def update_tab_widths(self, col: Gtk.TreeViewColumn) -> None:
# TODO: may cause pixel offsets when application is maximized
width = col.get_width()
+2 -4
View File
@@ -72,7 +72,6 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore
logger.critical(e)
valid_json = False
# NOTE: reasonable defaults for long columns
width_map = {
"Name": 800,
"Map": 300,
@@ -97,9 +96,8 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore
column.set_fixed_width(saved_size)
column.set_expand(True)
else:
if column_title in width_map:
w = width_map[column_title]
column.set_fixed_width(w)
w = width_map[column_title]
column.set_fixed_width(w)
if column_title == "Ping":
column.set_cell_data_func(renderer, self._get_ping)
+1 -1
View File
@@ -4,7 +4,7 @@ description = "DayZ server browser and mod manager for Linux"
authors = [
{name = "aclist"}
]
version = "7.0.0b6"
version = "7.0.0b4"
license = "GPL-3.0-or-later"
license-files = ["LICENSE"]
readme = "README.md"
-81
View File
@@ -1,81 +0,0 @@
import os
import requests
import subprocess
import tarfile
from pathlib import Path
from urllib.parse import unquote
BUILD = "3.13.9"
DATE = "20251014"
CPYTHON_BUILD = f"cpython-{BUILD}"
root = Path(__file__).resolve().parents[1]
build_dir = root.joinpath("build")
cpython_dir = build_dir.joinpath(CPYTHON_BUILD)
def fetch(url: str, destination: str) -> None:
print(f"Fetching URL '{url}'")
res = requests.get(url)
code = res.status_code
if code != 200:
raise Exception(f"URL '{url}' returned status code {code}")
with open(build_dir.joinpath(destination), "wb") as f:
f.write(res.content)
def get_cpython() -> None:
source = f"https://github.com/astral-sh/python-build-standalone/releases/download/{DATE}/"
build = f"{CPYTHON_BUILD}%2B{DATE}-x86_64_v3-unknown-linux-gnu-install_only_stripped.tar.gz"
url = f"{source}{build}"
outfile = unquote(build)
fetch(url, outfile)
version = build.split("%")[0]
untar(outfile, "python", version)
def get_pyapp() -> None:
url = "https://github.com/ofek/pyapp/releases/latest/download/source.tar.gz"
outfile = "pyapp-latest.tar.gz"
fetch(url, outfile)
untar(outfile, "pyapp-*", "pyapp-latest")
def untar(file: str, glob: str, renamed: str) -> None:
full_path = build_dir.joinpath(file)
with tarfile.open(full_path, "r:gz") as tar:
tar.extractall(path=build_dir)
full_path.unlink()
for _dir in build_dir.glob(glob):
os.rename(_dir, build_dir.joinpath(renamed))
def install_deps() -> None:
pip = build_dir.joinpath(f"{CPYTHON_BUILD}/bin/pip")
subprocess.run([pip, "install", root])
def repackage() -> None:
print("Preparing tar archive...")
outfile = build_dir.joinpath("airgapped.tar.gz")
with tarfile.open(outfile, "w:gz") as tar:
tar.add(build_dir.joinpath(CPYTHON_BUILD), arcname="python")
def rebuild_cpython() -> None:
if cpython_dir.is_dir() is False:
get_cpython()
install_deps()
repackage()
return get_packaged_version()
def get_packaged_version() -> str:
proc = subprocess.run(
[cpython_dir.joinpath("bin/dzgui"), "-v"],
capture_output=True,
text=True,
check=True,
)
return proc.stdout.rstrip()
+6 -19
View File
@@ -5,12 +5,11 @@ import tarfile
from pathlib import Path
from prebuild import get_pyapp, rebuild_cpython
root = Path(__file__).resolve().parents[1]
output = root.joinpath("dist")
build_dir = root.joinpath("build")
pyapp_dir = root.joinpath("pyapp-latest")
cpython = root.joinpath("build/cpython/airgapped.tar.gz")
builder = build.ProjectBuilder(root)
wheel = builder.build("wheel", output_directory=output)
@@ -21,21 +20,15 @@ metadata = stem.split("-")
appname = metadata[0]
version = metadata[1]
pyapp_dir = build_dir.joinpath("pyapp-latest")
if pyapp_dir.is_dir() is False:
get_pyapp()
packaged_version = rebuild_cpython()
assert packaged_version == version
cpython = build_dir.joinpath("airgapped.tar.gz")
entrypoint = "dzgui.main:main"
env = os.environ
env["PYAPP_PROJECT_VERSION"] = version
env["PYAPP_PROJECT_NAME"] = appname
env["PYAPP_EXEC_SPEC"] = entrypoint
env["PYAPP_PROJECT_PATH"] = wheel
env["PYAPP_PASS_LOCATION"] = "true"
# env["PYAPP_PYTHON_VERSION"] = "3.13"
# NOTE: explicitly install all dependencies into distribution
env["PYAPP_SKIP_INSTALL"] = "true"
@@ -46,16 +39,10 @@ env["PYAPP_DISTRIBUTION_PYTHON_PATH"] = "python/bin/python3"
proc = subprocess.run(["cargo", "build", "--release"], env=env, cwd=pyapp_dir)
if proc.returncode == 0:
output_exe = build_dir.joinpath("pyapp-latest/target/release/pyapp")
output_exe = root.joinpath("pyapp-latest/target/release/pyapp")
release_exe = output.joinpath(appname)
output_exe.rename(release_exe)
tarpath = output.joinpath(tarname)
with tarfile.open(tarpath, "w:gz") as tar:
tar.add(release_exe, arcname=appname)
print(f"Wrote tarfile to '{tarpath}'")
proc = subprocess.run([release_exe, "-v"], capture_output=True, text=True)
assert proc.stdout.rstrip() == version
release_exe.unlink()
Path(wheel).unlink()
-14
View File
@@ -1,14 +0,0 @@
{
"cols": {
"Name": 1,
"Map": 1,
"Gametime": 1,
"Players": 1,
"Queue": 1,
"IP": 1,
"Qport": 1,
"Ping": 1,
"Maximum": 1,
"Perspective": 1
}
}
-12
View File
@@ -1,12 +0,0 @@
{
"cols": {
"Name": 398,
"Map": 181,
"Gametime": 151,
"Players": 119,
"Queue": 96,
"IP": 247,
"Qport": 94,
"Ping": 253
}
}
-13
View File
@@ -1,13 +0,0 @@
{
"cols": {
"Name": 1,
"Map": 1,
"Gametime": 1,
"Players": 1,
"Queue": 1,
"IP": 1,
"Qport": 1,
"Ping": 1,
"View": 1
}
}
-33
View File
@@ -1,33 +0,0 @@
import pytest
from dzgui.init.migrate import convert_cols_file
from tests.fixtures import fixture_path
@pytest.fixture
def columns_with_perspective():
return fixture_path("columns_1")
@pytest.fixture
def columns_without_perspective():
return fixture_path("columns_2")
@pytest.fixture
def columns_with_view():
return fixture_path("columns_3")
@pytest.mark.config
def test_columns_with_perspective(columns_with_perspective):
j = convert_cols_file(columns_with_perspective)
assert "View" in j["cols"]
assert "Max" in j["cols"]
@pytest.mark.config
def test_columns_without_perspective(columns_without_perspective):
j = convert_cols_file(columns_without_perspective)
assert "View" not in j["cols"]
assert "Max" not in j["cols"]
@pytest.mark.config
def test_columns_with_view(columns_with_view):
j = convert_cols_file(columns_with_view)
assert j is None
+3 -3
View File
@@ -2,14 +2,14 @@ from dzgui.util import localize
def test_de(monkeypatch):
monkeypatch.setenv("LC_ALL", "de_DE.UTF-8")
monkeypatch.setenv("LC_CTYPE", "de_DE.UTF-8")
localize.set_locale()
assert localize.number(9900) == "9.900"
assert localize.number(99.88) == "99,88"
def test_en(monkeypatch):
monkeypatch.setenv("LC_ALL", "en_US.UTF-8")
monkeypatch.setenv("LC_CTYPE", "en_US.UTF-8")
localize.set_locale()
assert localize.number(9900) == "9,900"
assert localize.number(99.88) == "99.88"
@@ -22,7 +22,7 @@ def test_none(monkeypatch):
def test_empty(monkeypatch):
monkeypatch.setenv("LC_ALL", "")
monkeypatch.setenv("LC_CTYPE", "")
localize.set_locale()
assert localize.number(9900) == "9,900"
assert localize.number(99.88) == "99.88"