Merge pull request 'clan_vm_manager: Added suffix task to glib task functions' (#894) from Qubasa-main into main

This commit is contained in:
clan-bot
2024-03-03 09:18:42 +00:00
3 changed files with 102 additions and 63 deletions

View File

@@ -32,56 +32,19 @@ class GKVStore(GObject.GObject, Gio.ListModel, Generic[K, V]):
self.key_gen = key_gen self.key_gen = key_gen
self._items: "OrderedDict[K, V]" = OrderedDict() self._items: "OrderedDict[K, V]" = OrderedDict()
##################################
# #
# Gio.ListStore Interface #
# #
##################################
@classmethod @classmethod
def new(cls: Any, gtype: type[V]) -> "GKVStore": def new(cls: Any, gtype: type[V]) -> "GKVStore":
return cls.__new__(cls, gtype) return cls.__new__(cls, gtype)
######################### def append(self, item: V) -> None:
# # key = self.key_gen(item)
# READ OPERATIONS # self[key] = item
# #
#########################
def keys(self) -> list[K]:
return list(self._items.keys())
def values(self) -> list[V]:
return list(self._items.values())
def items(self) -> list[tuple[K, V]]:
return list(self._items.items())
def get(self, key: K, default: V | None = None) -> V | None:
return self._items.get(key, default)
def get_n_items(self) -> int:
return len(self._items)
def do_get_n_items(self) -> int:
return self.get_n_items()
def get_item(self, position: int) -> V | None:
if position < 0 or position >= self.get_n_items():
return None
# Access items by index since OrderedDict does not support direct indexing
key = list(self._items.keys())[position]
return self._items[key]
def do_get_item(self, position: int) -> V | None:
return self.get_item(position)
def get_item_type(self) -> GObject.GType:
return self.gtype.__gtype__
def do_get_item_type(self) -> GObject.GType:
return self.get_item_type()
def first(self) -> V:
return self.values()[0]
def last(self) -> V:
return self.values()[-1]
# O(n) operation
def find(self, item: V) -> tuple[bool, int]: def find(self, item: V) -> tuple[bool, int]:
log.warning("Finding is O(n) in GKVStore. Better use indexing") log.warning("Finding is O(n) in GKVStore. Better use indexing")
for i, v in enumerate(self.values()): for i, v in enumerate(self.values()):
@@ -89,11 +52,24 @@ class GKVStore(GObject.GObject, Gio.ListModel, Generic[K, V]):
return True, i return True, i
return False, -1 return False, -1
######################### def find_with_equal_func(
# # self, item: V, equal_func: Callable[[V, V], bool]
# WRITE OPERATIONS # ) -> tuple[bool, int]:
# # log.warning("Finding is O(n) in GKVStore. Better use indexing")
######################### for i, v in enumerate(self.values()):
if equal_func(v, item):
return True, i
return False, -1
def find_with_equal_func_full(
self, item: V, equal_func: Callable[[V, V, Any], bool], user_data: Any
) -> tuple[bool, int]:
log.warning("Finding is O(n) in GKVStore. Better use indexing")
for i, v in enumerate(self.values()):
if equal_func(v, item, user_data):
return True, i
return False, -1
def insert(self, position: int, item: V) -> None: def insert(self, position: int, item: V) -> None:
log.warning("Inserting is O(n) in GKVStore. Better use append") log.warning("Inserting is O(n) in GKVStore. Better use append")
log.warning( log.warning(
@@ -122,9 +98,10 @@ class GKVStore(GObject.GObject, Gio.ListModel, Generic[K, V]):
# Notify the model of the changes # Notify the model of the changes
self.items_changed(position, 0, 1) self.items_changed(position, 0, 1)
def append(self, item: V) -> None: def insert_sorted(
key = self.key_gen(item) self, item: V, compare_func: Callable[[V, V, Any], int], user_data: Any
self[key] = item ) -> None:
raise NotImplementedError("insert_sorted is not implemented in GKVStore")
def remove(self, position: int) -> None: def remove(self, position: int) -> None:
if position < 0 or position >= self.get_n_items(): if position < 0 or position >= self.get_n_items():
@@ -137,6 +114,56 @@ class GKVStore(GObject.GObject, Gio.ListModel, Generic[K, V]):
self._items.clear() self._items.clear()
self.items_changed(0, len(self._items), 0) self.items_changed(0, len(self._items), 0)
def sort(self, compare_func: Callable[[V, V, Any], int], user_data: Any) -> None:
raise NotImplementedError("sort is not implemented in GKVStore")
def splice(self, position: int, n_removals: int, additions: list[V]) -> None:
raise NotImplementedError("splice is not implemented in GKVStore")
##################################
# #
# Gio.ListModel Interface #
# #
##################################
def get_item(self, position: int) -> V | None:
if position < 0 or position >= self.get_n_items():
return None
# Access items by index since OrderedDict does not support direct indexing
key = list(self._items.keys())[position]
return self._items[key]
def do_get_item(self, position: int) -> V | None:
return self.get_item(position)
def get_item_type(self) -> GObject.GType:
return self.gtype.__gtype__
def do_get_item_type(self) -> GObject.GType:
return self.get_item_type()
def get_n_items(self) -> int:
return len(self._items)
def do_get_n_items(self) -> int:
return self.get_n_items()
##################################
# #
# Dict Interface #
# #
##################################
def keys(self) -> list[K]:
return list(self._items.keys())
def values(self) -> list[V]:
return list(self._items.values())
def items(self) -> list[tuple[K, V]]:
return list(self._items.items())
def get(self, key: K, default: V | None = None) -> V | None:
return self._items.get(key, default)
# O(1) operation if the key does not exist, O(n) if it does # O(1) operation if the key does not exist, O(n) if it does
def __setitem__(self, key: K, value: V) -> None: def __setitem__(self, key: K, value: V) -> None:
# If the key already exists, remove it O(n) # If the key already exists, remove it O(n)
@@ -178,3 +205,14 @@ class GKVStore(GObject.GObject, Gio.ListModel, Generic[K, V]):
def __repr__(self) -> str: def __repr__(self) -> str:
return self._items.__str__() return self._items.__str__()
##################################
# #
# Custom Methods #
# #
##################################
def first(self) -> V:
return self.values()[0]
def last(self) -> V:
return self.values()[-1]

View File

@@ -26,7 +26,7 @@ class JoinValue(GObject.Object):
url: ClanURI url: ClanURI
entry: HistoryEntry | None entry: HistoryEntry | None
def _join_finished(self) -> bool: def _join_finished_task(self) -> bool:
self.emit("join_finished", self) self.emit("join_finished", self)
return GLib.SOURCE_REMOVE return GLib.SOURCE_REMOVE
@@ -38,7 +38,7 @@ class JoinValue(GObject.Object):
def __join(self) -> None: def __join(self) -> None:
new_entry = add_history(self.url) new_entry = add_history(self.url)
self.entry = new_entry self.entry = new_entry
GLib.idle_add(self._join_finished) GLib.idle_add(self._join_finished_task)
def join(self) -> None: def join(self) -> None:
threading.Thread(target=self.__join).start() threading.Thread(target=self.__join).start()

View File

@@ -37,7 +37,7 @@ class VM(GObject.Object):
"vm_status_changed": (GObject.SignalFlags.RUN_FIRST, None, [GObject.Object]) "vm_status_changed": (GObject.SignalFlags.RUN_FIRST, None, [GObject.Object])
} }
def vm_status_changed(self) -> bool: def vm_status_changed_task(self) -> bool:
self.emit("vm_status_changed", self) self.emit("vm_status_changed", self)
return GLib.SOURCE_REMOVE return GLib.SOURCE_REMOVE
@@ -130,7 +130,7 @@ class VM(GObject.Object):
yield self.machine yield self.machine
self.machine = None self.machine = None
def _pulse_progress_bar(self) -> bool: def _pulse_progress_bar_task(self) -> bool:
if self.progress_bar.is_visible(): if self.progress_bar.is_visible():
self.progress_bar.pulse() self.progress_bar.pulse()
return GLib.SOURCE_CONTINUE return GLib.SOURCE_CONTINUE
@@ -150,7 +150,7 @@ class VM(GObject.Object):
machine=machine, machine=machine,
tmpdir=log_dir, tmpdir=log_dir,
) )
GLib.idle_add(self.vm_status_changed) GLib.idle_add(self.vm_status_changed_task)
# Start the logs watcher # Start the logs watcher
self._logs_id = GLib.timeout_add( self._logs_id = GLib.timeout_add(
@@ -162,7 +162,7 @@ class VM(GObject.Object):
# Start the progress bar and show it # Start the progress bar and show it
self.progress_bar.show() self.progress_bar.show()
self.prog_bar_id = GLib.timeout_add(100, self._pulse_progress_bar) self.prog_bar_id = GLib.timeout_add(100, self._pulse_progress_bar_task)
if self.prog_bar_id == 0: if self.prog_bar_id == 0:
log.error("Couldn't spawn a progess bar task") log.error("Couldn't spawn a progess bar task")
@@ -175,7 +175,7 @@ class VM(GObject.Object):
# Check if the VM was built successfully # Check if the VM was built successfully
if self.build_process.proc.exitcode != 0: if self.build_process.proc.exitcode != 0:
log.error(f"Failed to build VM {self.get_id()}") log.error(f"Failed to build VM {self.get_id()}")
GLib.idle_add(self.vm_status_changed) GLib.idle_add(self.vm_status_changed_task)
return return
log.info(f"Successfully built VM {self.get_id()}") log.info(f"Successfully built VM {self.get_id()}")
@@ -187,7 +187,7 @@ class VM(GObject.Object):
vm=self.data.flake.vm, vm=self.data.flake.vm,
) )
log.debug(f"Started VM {self.get_id()}") log.debug(f"Started VM {self.get_id()}")
GLib.idle_add(self.vm_status_changed) GLib.idle_add(self.vm_status_changed_task)
# Start the logs watcher # Start the logs watcher
self._logs_id = GLib.timeout_add(50, self._get_logs_task, self.vm_process) self._logs_id = GLib.timeout_add(50, self._get_logs_task, self.vm_process)
@@ -198,7 +198,7 @@ class VM(GObject.Object):
# Wait for the VM to stop # Wait for the VM to stop
self.vm_process.proc.join() self.vm_process.proc.join()
log.debug(f"VM {self.get_id()} has stopped") log.debug(f"VM {self.get_id()} has stopped")
GLib.idle_add(self.vm_status_changed) GLib.idle_add(self.vm_status_changed_task)
def start(self) -> None: def start(self) -> None:
if self.is_running(): if self.is_running():
@@ -274,7 +274,7 @@ class VM(GObject.Object):
# Try 20 times to stop the VM # Try 20 times to stop the VM
time.sleep(self.KILL_TIMEOUT / 20) time.sleep(self.KILL_TIMEOUT / 20)
GLib.idle_add(self.vm_status_changed) GLib.idle_add(self.vm_status_changed_task)
log.debug(f"VM {self.get_id()} has stopped") log.debug(f"VM {self.get_id()} has stopped")
def shutdown(self) -> None: def shutdown(self) -> None:
@@ -348,6 +348,7 @@ class VMs:
return GLib.SOURCE_REMOVE return GLib.SOURCE_REMOVE
def push_history_entry(self, entry: HistoryEntry) -> None: def push_history_entry(self, entry: HistoryEntry) -> None:
# TODO: We shouldn't do this here but in the list view
if entry.flake.icon is None: if entry.flake.icon is None:
icon = assets.loc / "placeholder.jpeg" icon = assets.loc / "placeholder.jpeg"
else: else: