clan-vm-manager: Fix double instantiation of Singleton. clan_cli: Shorten filepath of logging messages
checks / test (pull_request) Failing after 1m8s Details
checks-impure / test (pull_request) Failing after 10m22s Details

This commit is contained in:
Luis Hebendanz 2024-02-21 16:16:58 +07:00
parent ff3a1dc928
commit 51b087f7ae
5 changed files with 47 additions and 32 deletions

View File

@ -18,11 +18,14 @@ def get_formatter(color: str) -> Callable[[logging.LogRecord, bool], logging.For
) -> logging.Formatter:
reset = "\x1b[0m"
filepath = Path(record.pathname).resolve()
home = Path.home()
filepath = Path("~", filepath.relative_to(home))
if not with_location:
return logging.Formatter(f"{color}%(levelname)s{reset}: %(message)s")
return logging.Formatter(
f"{color}%(levelname)s{reset}: %(message)s\n {filepath}:%(lineno)d::%(funcName)s\n"
f"{color}%(levelname)s{reset}: %(message)s\nLocation: {filepath}:%(lineno)d::%(funcName)s\n"
)
return myformatter
@ -62,7 +65,10 @@ def get_caller() -> str:
if caller_frame is None:
return "unknown"
frame_info = inspect.getframeinfo(caller_frame)
ret = f"{frame_info.filename}:{frame_info.lineno}::{frame_info.function}"
filepath = Path(frame_info.filename).resolve()
filepath = Path("~", filepath.relative_to(Path.home()))
ret = f"{filepath}:{frame_info.lineno}::{frame_info.function}"
return ret
@ -76,7 +82,7 @@ def setup_logging(level: Any, root_log_name: str = __name__.split(".")[0]) -> No
# Create and add your custom handler
default_handler.setLevel(level)
default_handler.setFormatter(CustomFormatter(level == logging.DEBUG))
default_handler.setFormatter(CustomFormatter(str(level) == str(logging.DEBUG)))
main_logger.addHandler(default_handler)
# Set logging level for other modules used by this module

View File

@ -14,15 +14,19 @@ from gi.repository import Adw, Gdk, Gio, Gtk
from clan_vm_manager.models.interfaces import ClanConfig
from clan_vm_manager.models.use_join import GLib, GObject
from clan_vm_manager.models.use_vms import VMs
from .trayicon import TrayIcon
from .windows.main_window import MainWindow
log = logging.getLogger(__name__)
class MainApplication(Adw.Application):
"""
This class is initialized every time the app is started
Only the Adw.ApplicationWindow is a singleton.
So don't use any singletons in the Adw.Application class.
"""
__gsignals__: ClassVar = {
"join_request": (GObject.SignalFlags.RUN_FIRST, None, [str]),
}
@ -34,7 +38,6 @@ class MainApplication(Adw.Application):
flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
**kwargs,
)
self.tray_icon: TrayIcon | None = None
self.add_main_option(
"debug",
@ -44,10 +47,8 @@ class MainApplication(Adw.Application):
"enable debug mode",
None,
)
self.vms = VMs.use()
log.debug(f"VMS object: {self.vms}")
self.window: Adw.ApplicationWindow | None = None
self.connect("shutdown", self.on_shutdown)
self.connect("activate", self.show_window)
def do_command_line(self, command_line: Any) -> int:
@ -56,10 +57,10 @@ class MainApplication(Adw.Application):
options = options.end().unpack()
if "debug" in options:
setup_logging("DEBUG", root_log_name=__name__.split(".")[0])
setup_logging("DEBUG", root_log_name="clan_cli")
setup_logging(logging.DEBUG, root_log_name=__name__.split(".")[0])
setup_logging(logging.DEBUG, root_log_name="clan_cli")
else:
setup_logging("INFO", root_log_name=__name__.split(".")[0])
setup_logging(logging.INFO, root_log_name=__name__.split(".")[0])
log.debug("Debug logging enabled")
args = command_line.get_arguments()
@ -72,14 +73,6 @@ class MainApplication(Adw.Application):
self.emit("join_request", uri)
return 0
def on_shutdown(self, app: Gtk.Application) -> None:
log.debug("Shutting down")
self.vms.kill_all()
if self.tray_icon is not None:
self.tray_icon.destroy()
def on_window_hide_unhide(self, *_args: Any) -> None:
assert self.window is not None
if self.window.is_visible():
@ -90,15 +83,12 @@ class MainApplication(Adw.Application):
def dummy_menu_entry(self) -> None:
log.info("Dummy menu entry called")
def do_activate(self) -> None:
self.show_window()
def show_window(self, app: Any = None) -> None:
def show_window(self, *_args: Any) -> None:
if not self.window:
self.init_style()
self.window = MainWindow(config=ClanConfig(initial_view="list"))
self.window.set_application(self)
self.tray_icon = TrayIcon(self)
self.window.present()
# TODO: For css styling

View File

@ -122,7 +122,7 @@ class VM(GObject.Object):
self.log_dir = tempfile.TemporaryDirectory(
prefix="clan_vm-", suffix=f"-{self.data.flake.flake_attr}"
)
self._finalizer = weakref.finalize(self, self.kill)
self._finalizer = weakref.finalize(self, self.kill_ref_drop)
self.connect("build_vm", self.build_vm)
uri = ClanURI.from_str(
url=self.data.flake.flake_url, flake_attr=self.data.flake.flake_attr
@ -269,6 +269,11 @@ class VM(GObject.Object):
log.info(f"Stopping VM {self.get_id()}")
threading.Thread(target=self.__stop).start()
def kill_ref_drop(self) -> None:
if self.is_running():
log.warning("Killing VM due to reference drop")
self.kill()
def kill(self) -> None:
if not self.is_running():
log.warning(f"Tried to kill VM {self.get_id()} is not running")
@ -315,14 +320,12 @@ class VMs:
for vm in self.list_store:
if ident == vm.get_id():
return vm
return None
def get_running_vms(self) -> list[VM]:
return list(filter(lambda vm: vm.is_running(), self.list_store))
def kill_all(self) -> None:
log.debug(f"Running vms: {self.get_running_vms()}")
for vm in self.get_running_vms():
vm.kill()

View File

@ -10,6 +10,7 @@ from clan_cli.clan_uri import ClanURI
from clan_vm_manager.models.interfaces import ClanConfig
from clan_vm_manager.models.use_join import Join, JoinValue
from clan_vm_manager.models.use_views import Views
from clan_vm_manager.models.use_vms import VMs
gi.require_version("Adw", "1")
from gi.repository import Adw, Gdk, Gio, GLib, GObject, Gtk
@ -123,7 +124,7 @@ class ClanList(Gtk.Box):
def on_search_changed(self, entry: Gtk.SearchEntry) -> None:
Clans.use().filter_by_name(entry.get_text())
# Disable the shadow if the list is empty
if not self.app.vms.list_store.get_n_items():
if not VMs.use().list_store.get_n_items():
self.group_list.add_css_class("no-shadow")
def render_vm_row(self, boxed_list: Gtk.ListBox, vm: VM) -> Gtk.Widget:
@ -202,7 +203,7 @@ class ClanList(Gtk.Box):
def on_edit(self, action: Any, parameter: Any) -> None:
target = parameter.get_string()
vm = self.app.vms.get_by_id(target)
vm = VMs.use().get_by_id(target)
if not vm:
raise ClanError("Something went wrong. Please restart the app.")
@ -220,7 +221,7 @@ class ClanList(Gtk.Box):
row.add_css_class("trust")
# TODO: figure out how to detect that
exist = self.app.vms.use().get_by_id(item.url.get_id())
exist = VMs.use().use().get_by_id(item.url.get_id())
if exist:
sub = row.get_subtitle()
row.set_subtitle(

View File

@ -1,13 +1,18 @@
from typing import Any
import gi
from clan_vm_manager.models.interfaces import ClanConfig
from clan_vm_manager.models.use_views import Views
from clan_vm_manager.models.use_vms import VMs
from clan_vm_manager.views.details import Details
from clan_vm_manager.views.list import ClanList
gi.require_version("Adw", "1")
from gi.repository import Adw, Gtk
from gi.repository import Adw, Gio, Gtk
from ..trayicon import TrayIcon
class MainWindow(Adw.ApplicationWindow):
@ -22,6 +27,10 @@ class MainWindow(Adw.ApplicationWindow):
header = Adw.HeaderBar()
view.add_top_bar(header)
self.vms = VMs.use()
app = Gio.Application.get_default()
self.tray_icon: TrayIcon = TrayIcon(app)
# Initialize all views
stack_view = Views.use().view
Views.use().set_main_window(self)
@ -41,3 +50,9 @@ class MainWindow(Adw.ApplicationWindow):
clamp.set_maximum_size(1000)
view.set_content(clamp)
self.connect("destroy", self.on_destroy)
def on_destroy(self, *_args: Any) -> None:
self.tray_icon.destroy()
self.vms.kill_all()