chore: clear typehinting errors

This commit is contained in:
aclist 2026-05-02 20:01:57 +09:00
parent 806e05977d
commit 5757f79755
17 changed files with 91 additions and 46 deletions

View File

@ -51,7 +51,7 @@ def query_defunct() -> None:
def concat_mods(mods: list[str]) -> str:
for mod in mods:
mods[mod] = "@" + mod
mods[mod] = f"@{mod}"
return ";".join(mods)

View File

@ -1,7 +1,7 @@
import logging
import threading
from typing import Any, TYPE_CHECKING
from typing import Any, TYPE_CHECKING, Union
import dzgui.util._json as JSON # noqa
@ -110,14 +110,14 @@ class Controller(GObject.GObject):
return bool(self.query_config(Preferences.INSTALL))
def suppress_signal(
self, owner: Gtk.Widget, widget: Gtk.Widget, func_name: str, state: bool
self, owner: Any, child: Any, func_name: str, state: bool
) -> None:
func = getattr(owner, func_name)
if state:
widget.handler_block_by_func(func)
child.handler_block_by_func(func)
else:
widget.handler_unblock_by_func(func)
child.handler_unblock_by_func(func)
def get_active_context(self) -> "ServerTab":
return self.get_active_treeview().get_enum()
@ -139,7 +139,7 @@ class Controller(GObject.GObject):
def remove_statusbar(self, context: "NotebookPage | ServerTab") -> None:
self.mediator.statusbar.pop(context)
def set_statusbar_dist(self, haversine: "Haversine", enum: "ServerTab") -> None:
def set_statusbar_dist(self, haversine: Union["Haversine", None], enum: "ServerTab") -> None:
"""
NOTE: prevents race condition when server tab changed,
but allows caching the distance in the background
@ -153,6 +153,9 @@ class Controller(GObject.GObject):
self.emitter.emit("distcalc_ended", None, context)
return
if haversine is None:
self.emitter.emit("distcalc_ended", None, context)
return
dist = haversine.get_rounded(self.prefs.use_miles)
self.emitter.emit("distcalc_ended", dist, context)

View File

@ -36,6 +36,7 @@ class ConfigManager:
def __init__(self, prefs: "UserPrefs", controller: "Controller") -> None:
self.prefs = prefs
self.config = prefs.paths.config
self.controller = controller
self.emitter = controller.get_emitter()
self.thread_man = ThreadingManager(controller)
@ -95,7 +96,7 @@ class ConfigManager:
return
def get_favorites(self) -> list[str]:
return self.lookup(Preferences.IP_LIST)
return list(self.lookup(Preferences.IP_LIST))
def get_favorite(self) -> tuple[str, str] | tuple[None, None]:
fav = str(self.lookup(Preferences.FAV_LBL))
@ -112,7 +113,7 @@ class ConfigManager:
return False
def enum_to_key(self, enum: Preferences) -> str:
return enum.dict["key"]
return str(enum.dict["key"])
def get_client_index(self, client: str) -> int:
if client == STEAM_CMD:
@ -121,6 +122,7 @@ class ConfigManager:
return 1
if client == FLATPAK_SANDBOX:
return 2
return 0
def toggle_config(self, key: Preferences) -> None:
try:
@ -149,7 +151,7 @@ class ConfigManager:
except Exception as e:
logger.critical(e)
trace = traceback.format_exc()
dialog = ExceptionDialog(self, trace)
dialog = ExceptionDialog(self.controller, trace)
dialog.run()
raise e

View File

@ -8,6 +8,8 @@ from dzgui.util.clip import copy_clipboard
from dzgui.util.open_links import open_workshop_page
from dzgui.views.dialogs.note import NoteDialog
from dzgui.views.trees.tree_mods import ModTreeView
from dzgui.views.trees.tree_log import LogTreeView
from dzgui.views.trees.tree_servers import ServerTreeView
@ -19,13 +21,12 @@ logger = logging.getLogger(APP_NAME)
if TYPE_CHECKING:
from dzgui.controllers.mc import Controller
from dzgui.views.trees.tree_servers import ServerTreeView
class ContextMenuManager:
def __init__(
self,
treeview: "ServerTreeView",
treeview: LogTreeView | ModTreeView | ServerTreeView,
controller: "Controller",
) -> None:
self.controller = controller
@ -49,28 +50,40 @@ class ContextMenuManager:
self.open_mod_page()
case ContextMenu.SET_FAV:
name = self.treeview.get_value_at_index(0)
record = self.treeview.get_record_string()
record_str = self.treeview.get_record_string()
simple = self.treeview.get_simplified_ip()
self.controller.set_fav(name, record, simple)
self.controller.set_fav(name, record_str, simple)
# THREADED
case ContextMenu.ADD_SERVER:
record = self.treeview.get_record()
if record is None:
return
self.controller.add_by_record(record)
case ContextMenu.CONNECT:
record = self.treeview.get_record()
if record is None:
return
self.controller.connect_by_record(record)
case ContextMenu.REFRESH_PLAYERS:
record = self.treeview.get_record()
if record is None:
return
self.controller.refresh_players(record)
case ContextMenu.REMOVE_HISTORY:
record = self.treeview.get_record()
if record is None:
return
self.controller.remove_from_history(record)
case ContextMenu.REMOVE_SERVER:
record = self.treeview.get_record()
if record is None:
return
self.controller.remove_by_record(record)
case ContextMenu.SHOW_DETAILS:
record = self.treeview.get_record()
if record is None:
return
self.controller.get_details(record)
case ContextMenu.SHOW_MODS:
record = self.treeview.get_record()
@ -89,11 +102,15 @@ class ContextMenuManager:
copy_clipboard(name)
def open_mod_page(self) -> None:
if not isinstance(self.treeview, ModTreeView):
return
mod = self.treeview.get_selected_mod()
cmd = self.controller.query_config(Preferences.CLIENT)
open_workshop_page(mod, cmd)
def copy_log(self) -> None:
if not isinstance(self.treeview, LogTreeView):
return
log = self.treeview.concatenate_rows()
if log is None:
return

View File

@ -42,7 +42,7 @@ class FilterManager:
def get_active_map_name(self) -> str:
return self.active_map[1]
def get_active_map(self) -> int:
def get_active_map(self) -> tuple[int, str]:
return self.active_map
def set_active_map(self, ind: int, name: str) -> None:

View File

@ -1,7 +1,7 @@
import inspect
import logging
import threading
from typing import Any, TYPE_CHECKING
from typing import Any, Literal, TYPE_CHECKING
from functools import wraps
from typing import Callable
@ -23,7 +23,7 @@ logger = logging.getLogger(APP_NAME)
def call_on_thread(dialog_str: str) -> Callable:
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Callable:
def wrapper(*args: Any, **kwargs: Any) -> None:
self = args[0]
stored = StoredFunc(func, *args, **kwargs)
if not hasattr(self, "thread_man"):
@ -40,7 +40,7 @@ def call_on_thread(dialog_str: str) -> Callable:
class StoredFunc:
def __init__(self, func: Callable, *args, **kwargs) -> None:
def __init__(self, func: Callable, *args: Any, **kwargs: Any) -> None:
sig = inspect.signature(func)
self.func = func
self.bindings = sig.bind(*args, **kwargs)
@ -53,7 +53,7 @@ class ThreadingManager:
def __init__(self, controller: "Controller") -> None:
self.controller = controller
self.jobs = 1
self.cleanup_func = None
self.cleanup_func: StoredFunc | None
self.destroy_first = False
def call_on_thread(self, dialog_str: str, func: StoredFunc) -> None:
@ -75,7 +75,7 @@ class ThreadingManager:
def increment_dialog_with_str(self, text: str) -> None:
GLib.idle_add(lambda: self.wait_dialog.increment(text))
def set_cleanup_func(self, func: StoredFunc, destroy_first: bool = False) -> None:
def set_cleanup_func(self, func: StoredFunc | None, destroy_first: bool = False) -> None:
if type(func) not in (StoredFunc, type(None)):
msg = f"Callback function '{func}' is not of type StoredFunc or None"
logger.critical(msg)
@ -83,10 +83,10 @@ class ThreadingManager:
self.destroy_first = destroy_first
self.cleanup_func = func
def get_cleanup_func(self) -> StoredFunc:
def get_cleanup_func(self) -> StoredFunc | None:
return self.cleanup_func
def _destroy_on_idle(self) -> GLib.SOURCE_REMOVE:
def _destroy_on_idle(self) -> Literal[False]:
if self.destroy_first:
self.wait_dialog.destroy()
@ -97,7 +97,7 @@ class ThreadingManager:
if not self.destroy_first:
self.wait_dialog.destroy()
return GLib.SOURCE_REMOVE
return False
def get_wait_dialog(self) -> WaitDialog:
return self.wait_dialog

View File

@ -86,7 +86,7 @@ class ServerModelManager:
key = config_man.lookup(Preferences.STEAM)
job = Servers.query_api
params = Servers.params
servers = []
servers: list[dict[Any, Any]] = []
with ThreadPoolExecutor() as executor:
futures = [executor.submit(job, key, APPID_DAYZ, param) for param in params]
for future in as_completed(futures):

View File

@ -33,7 +33,7 @@ import gi
gi.require_version("Gtk", "3.0")
gi.require_version("GLibUnix", "2.0")
from gi.repository import Gtk, GLib, GLibUnix, Gdk, GObject, Pango # noqa E402
from gi.repository import Gtk, GLib, GLibUnix, Gdk # type: ignore # noqa E402
logger = logging.getLogger(APP_NAME)
# https://bugzilla.gnome.org/show_bug.cgi?id=708676
@ -201,7 +201,8 @@ class Notebook(ScrollableMixin, Gtk.Notebook): # type: ignore
if widget is None:
return
widget.grab_content_area()
if hasattr(widget, "grab_content_area"):
widget.grab_content_area()
def get_page(self) -> Gtk.Widget | None:
ind = self.get_current_page()

View File

@ -133,6 +133,9 @@ class FavPanel(Gtk.Frame):
emitter.connect("fav_server_changed", self._on_fav_server_changed)
# TODO: do not return a None, None tuple
self.server_name: str
self.server_ip: str
self.server_name, self.server_ip = (
self.controller.get_config_man().get_favorite()
)

View File

@ -45,7 +45,7 @@ class ButtonGrid(Gtk.Grid):
checkbox = Gtk.CheckButton(label=check)
label = checkbox.get_child()
if label is not None:
label.set_ellipsize(Pango.EllipsizeMode.END)
label.set_ellipsize(Pango.EllipsizeMode.END) # type: ignore
if defaults[check]:
checkbox.set_active(True)
@ -186,7 +186,7 @@ class FilterPanel(Gtk.Box):
self.maps_combo = Gtk.ComboBox.new_with_model_and_entry(self.map_store)
self.maps_combo.set_entry_text_column(0)
self.maps_entry = self.maps_combo.get_child()
self.maps_entry: Gtk.Entry = self.maps_combo.get_child() # type: ignore
self.maps_entry.set_completion(completion)
self.maps_entry.set_placeholder_text("Filter by map")
self.maps_entry.connect("changed", self._on_map_completion, True)
@ -215,9 +215,10 @@ class FilterPanel(Gtk.Box):
i: int
row: Gtk.TreeModelRow
for i, row in enumerate(model):
if text == row[0]:
for i, row in enumerate(model): # type: ignore
if text == row[0]: # type: ignore
self.maps_combo.set_active(i)
return
def _on_maps_loaded(self, emitter: "Emitter", store: Gtk.ListStore) -> None:
self.maps_combo.set_model(store)
@ -262,7 +263,7 @@ class FilterPanel(Gtk.Box):
) -> None:
self.maps_combo.set_active_iter(it)
def _on_map_completion(self, entry: Gtk.Entry, editable: Literal[True]):
def _on_map_completion(self, entry: Gtk.Entry, editable: Literal[True]) -> None:
text = entry.get_text()
completion = entry.get_completion()
store = self.controller.get_map_store()

View File

@ -98,7 +98,7 @@ class Statusbar(Gtk.Grid):
def _on_server_row_changed(self, statusbar: Self) -> None:
self.spinner.start()
def _on_distcalc_started(self, e) -> None:
def _on_distcalc_started(self, emitter: "Emitter") -> None:
self.spinner.start()
def _on_distcalc_ended(

View File

@ -44,7 +44,7 @@ class GenericDialog(Gtk.MessageDialog):
self.set_default_response(Gtk.ResponseType.OK)
self.get_action_area().set_layout(Gtk.ButtonBoxStyle.CENTER)
self.get_action_area().set_layout(Gtk.ButtonBoxStyle.CENTER) # type: ignore
self.get_action_area().set_margin_bottom(20)
self.outer = self.get_content_area()
self.outer.set_margin_start(30)
@ -76,7 +76,10 @@ class IgnoreDialog(GenericDialog):
secondary=secondary,
)
cancel = self.get_widget_for_response(Gtk.ResponseType.CANCEL)
cancel.set_label("Ignore")
if cancel is None:
return
if hasattr(cancel, "set_label"):
cancel.set_label("Ignore")
class NotifyDialog(GenericDialog):
@ -199,7 +202,11 @@ class ExceptionDialog(GenericDialog):
match response:
case Gtk.ResponseType.OK:
self.destroy()
return None
case Gtk.ResponseType.NONE:
return True
case Gtk.ResponseType.DELETE_EVENT:
self.destroy()
return None
case _:
return None

View File

@ -19,7 +19,7 @@ class ContextMixin(TreeView):
self,
widget: Gtk.Widget,
event: Gdk.EventButton | Gdk.EventKey,
) -> None:
) -> bool:
if self.is_selection_empty():
return False
@ -56,6 +56,7 @@ class ContextMixin(TreeView):
self.context_menu.popup_at_pointer(event)
self.context_menu.select_first(False)
return True
def _process_dynamic_row(self, row: ContextMenu) -> Gtk.MenuItem:
if row == ContextMenu.ADD_SERVER and self.is_in_favs(): # type: ignore

View File

@ -18,9 +18,6 @@ class Help(Gtk.ScrolledWindow):
self.controller = controller
# FIXME: remember focused row
#self.treeview.focus_first_row()
def get_treeview(self) -> MenuTreeView:
return self.treeview

View File

@ -59,8 +59,8 @@ class Options(Gtk.Box):
css.add_class(label, "page-heading")
self.add(label)
self.steam_entry: Gtk.Entry = None
self.bm_entry: Gtk.Entry = None
self.steam_entry: Gtk.Entry
self.bm_entry: Gtk.Entry
self.steam = WebButton(label=strings.options.steam_web)
self.steam.connect("clicked", self._on_link_button_clicked, STEAM_API_SETUP)
@ -436,7 +436,8 @@ class Options(Gtk.Box):
install = config["auto_install"]
steam_path = Path(default_steam_path)
self.uid = find_user_id(steam_path)
uid = find_user_id(steam_path)
self.uid = "" if uid is None else uid
self.old_steam = steam
self.old_bm = bm
@ -444,7 +445,9 @@ class Options(Gtk.Box):
self.steam_entry.set_text(steam)
self.bm_entry.set_text(bm)
self.player_box.get_children()[0].set_text(name)
p = self.player_box.get_children()[0]
if hasattr(p, "set_text"):
p.set_text(name)
# NOTE: suppress toggle signal until radios are built
self._suppress_toggles(True)

View File

@ -1,6 +1,6 @@
import logging
from typing import Optional, Self, TYPE_CHECKING
from typing import Self, TYPE_CHECKING
from dzgui.const.constants import APP_NAME
from dzgui.const.enum import ContextMenuGroup, ServerTab
@ -77,6 +77,8 @@ class ServerNotebook(Gtk.ScrolledWindow):
return
page = self.notebook.get_nth_page(saved)
label = self.notebook.get_tab_label(page)
if label is None:
return
label.set_text(f"{server_labels.saved}*")
def _on_servers_loaded(self, emitter: "Emitter", tab: "ServerTab") -> None:
@ -86,6 +88,7 @@ class ServerNotebook(Gtk.ScrolledWindow):
state = False if tv.get_model() is None else True
tv.set_headers_visible(state)
tv.set_loaded(True)
tv.focus_first_row()
tv.grab_focus()
def _on_map(self, widget: Self) -> None:
@ -94,7 +97,7 @@ class ServerNotebook(Gtk.ScrolledWindow):
def _on_unmap(self, widget: Self) -> None:
self.emitter.emit("server_page_toggled", False)
def _on_keypress(self, widget: Self, event: Gdk.EventKey) -> Optional[False]:
def _on_keypress(self, widget: Self, event: Gdk.EventKey) -> bool:
# NOTE: abort if modifier mask is active
if event.state != 0:
return False
@ -116,6 +119,8 @@ class ServerNotebook(Gtk.ScrolledWindow):
def get_current_tab_text(self) -> str:
ind = self.notebook.get_current_page()
child = self.notebook.get_nth_page(ind)
if child is None:
return ""
return self.notebook.get_tab_label_text(child)
def _on_page_changed(

View File

@ -172,7 +172,7 @@ class ServerTreeView(ContextMixin, TreeView):
self.start_queue_checker()
self.start_distcalc()
def _on_unmap(self, a) -> None:
def _on_unmap(self, tree: Self) -> None:
# NOTE: removes queue checker for this tab
GLib.Source.remove(self.queue_id)
self.emitter.disconnect(self.handler_id)
@ -229,7 +229,7 @@ class ServerTreeView(ContextMixin, TreeView):
def _on_server_keypress(
self, treeview: Gtk.TreeView, event: Gdk.EventKey
) -> bool | None:
) -> None:
if event.state is Gdk.ModifierType.CONTROL_MASK:
match event.keyval:
case Gdk.KEY_f:
@ -248,10 +248,14 @@ class ServerTreeView(ContextMixin, TreeView):
case Gdk.KEY_r:
# TODO: unimplemented, needs threading
self.controller.menu_action(ContextMenu.REFRESH_PLAYERS, self)
case _:
return False
return True
else:
match event.keyval:
case Gdk.KEY_l | Gdk.KEY_Right:
self.emitter.emit("request_button_box_focus")
return True
case _:
self.emitter.emit("check_button_pressed", event.keyval)
@ -307,7 +311,8 @@ class ServerTreeView(ContextMixin, TreeView):
try:
ip, gameport, qport = r.split(":")
return Record(ip, int(gameport), int(qport))
except ValueError:
except ValueError as e:
logger.critical(e)
return None
def is_loaded(self) -> bool: