From d3a6eaa4d1ddd22d087b34dc413c2a5162b7de50 Mon Sep 17 00:00:00 2001 From: GeoffreyCoulaud Date: Thu, 27 Jul 2023 04:34:33 +0200 Subject: [PATCH] Fix source id being translated - Additional fix, lutris source db subpath --- src/importer/importer.py | 14 +++++------ src/importer/sources/bottles_source.py | 3 ++- src/importer/sources/flatpak_source.py | 3 ++- src/importer/sources/heroic_source.py | 5 ++-- src/importer/sources/itch_source.py | 3 ++- src/importer/sources/legendary_source.py | 3 ++- src/importer/sources/lutris_source.py | 7 +++--- src/importer/sources/source.py | 11 ++------- src/importer/sources/steam_source.py | 3 ++- src/preferences.py | 30 ++++++++++++++---------- 10 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/importer/importer.py b/src/importer/importer.py index 8b30c6b..756ea3b 100644 --- a/src/importer/importer.py +++ b/src/importer/importer.py @@ -105,7 +105,7 @@ class Importer(ErrorProducer): manager.reset_cancellable() for source in self.sources: - logging.debug("Importing games from source %s", source.id) + logging.debug("Importing games from source %s", source.source_id) task = Task.new(None, None, self.source_callback, (source,)) self.n_source_tasks_created += 1 task.set_task_data((source,)) @@ -138,16 +138,16 @@ class Importer(ErrorProducer): # Early exit if not available or not installed if not source.is_available: - logging.info("Source %s skipped, not available", source.id) + logging.info("Source %s skipped, not available", source.source_id) return try: iterator = iter(source) except UnresolvableLocationError: - logging.info("Source %s skipped, bad location", source.id) + logging.info("Source %s skipped, bad location", source.source_id) return # Get games from source - logging.info("Scanning source %s", source.id) + logging.info("Scanning source %s", source.source_id) while True: # Handle exceptions raised when iterating try: @@ -155,7 +155,7 @@ class Importer(ErrorProducer): except StopIteration: break except Exception as error: # pylint: disable=broad-exception-caught - logging.exception("%s in %s", type(error).__name__, source.id) + logging.exception("%s in %s", type(error).__name__, source.source_id) self.report_error(error) continue @@ -172,7 +172,7 @@ class Importer(ErrorProducer): # Should not happen on production code logging.warning( "%s produced an invalid iteration return type %s", - source.id, + source.source_id, type(iteration_result), ) continue @@ -194,7 +194,7 @@ class Importer(ErrorProducer): def source_callback(self, _obj, _result, data): """Callback executed when a source is fully scanned""" source, *_rest = data - logging.debug("Import done for source %s", source.id) + logging.debug("Import done for source %s", source.source_id) self.n_source_tasks_done += 1 self.progress_changed_callback() diff --git a/src/importer/sources/bottles_source.py b/src/importer/sources/bottles_source.py index 5b48078..041247b 100644 --- a/src/importer/sources/bottles_source.py +++ b/src/importer/sources/bottles_source.py @@ -43,7 +43,7 @@ class BottlesSourceIterable(SourceIterable): for entry in library.values(): # Build game values = { - "source": self.source.id, + "source": self.source.source_id, "added": added_time, "name": entry["name"], "game_id": self.source.game_id_format.format(game_id=entry["id"]), @@ -84,6 +84,7 @@ class BottlesLocations(NamedTuple): class BottlesSource(URLExecutableSource): """Generic Bottles source""" + source_id = "bottles" name = _("Bottles") iterable_class = BottlesSourceIterable url_format = 'bottles:run/"{bottle_name}"/"{game_name}"' diff --git a/src/importer/sources/flatpak_source.py b/src/importer/sources/flatpak_source.py index b78815c..ee4ebbe 100644 --- a/src/importer/sources/flatpak_source.py +++ b/src/importer/sources/flatpak_source.py @@ -77,7 +77,7 @@ class FlatpakSourceIterable(SourceIterable): continue values = { - "source": self.source.id, + "source": self.source.source_id, "added": added_time, "name": name, "game_id": self.source.game_id_format.format(game_id=flatpak_id), @@ -119,6 +119,7 @@ class FlatpakLocations(NamedTuple): class FlatpakSource(Source): """Generic Flatpak source""" + source_id = "flatpak" name = _("Flatpak") iterable_class = FlatpakSourceIterable executable_format = "flatpak run {flatpak_id}" diff --git a/src/importer/sources/heroic_source.py b/src/importer/sources/heroic_source.py index 605ba56..33b7f90 100644 --- a/src/importer/sources/heroic_source.py +++ b/src/importer/sources/heroic_source.py @@ -100,7 +100,7 @@ class SubSourceIterable(Iterable): # Build game values = { - "source": f"{self.source.id}_{self.service}", + "source": f"{self.source.source_id}_{self.service}", "added": added_time, "name": entry["title"], "developer": entry.get("developer", None), @@ -356,6 +356,7 @@ class HeroicLocations(NamedTuple): class HeroicSource(URLExecutableSource): """Generic Heroic Games Launcher source""" + source_id = "heroic" name = _("Heroic") iterable_class = HeroicSourceIterable url_format = "heroic://launch/{app_name}" @@ -384,4 +385,4 @@ class HeroicSource(URLExecutableSource): @property def game_id_format(self) -> str: """The string format used to construct game IDs""" - return self.id + "_{service}_{game_id}" + return self.source_id + "_{service}_{game_id}" diff --git a/src/importer/sources/itch_source.py b/src/importer/sources/itch_source.py index 8302e91..36e02e0 100644 --- a/src/importer/sources/itch_source.py +++ b/src/importer/sources/itch_source.py @@ -62,7 +62,7 @@ class ItchSourceIterable(SourceIterable): for row in cursor: values = { "added": added_time, - "source": self.source.id, + "source": self.source.source_id, "name": row[1], "game_id": self.source.game_id_format.format(game_id=row[0]), "executable": self.source.executable_format.format(cave_id=row[4]), @@ -80,6 +80,7 @@ class ItchLocations(NamedTuple): class ItchSource(URLExecutableSource): + source_id = "itch" name = _("itch") iterable_class = ItchSourceIterable url_format = "itch://caves/{cave_id}/launch" diff --git a/src/importer/sources/legendary_source.py b/src/importer/sources/legendary_source.py index 48f0cac..03bbdd2 100644 --- a/src/importer/sources/legendary_source.py +++ b/src/importer/sources/legendary_source.py @@ -43,7 +43,7 @@ class LegendarySourceIterable(SourceIterable): app_name = entry["app_name"] values = { "added": added_time, - "source": self.source.id, + "source": self.source.source_id, "name": entry["title"], "game_id": self.source.game_id_format.format(game_id=app_name), "executable": self.source.executable_format.format(app_name=app_name), @@ -94,6 +94,7 @@ class LegendaryLocations(NamedTuple): class LegendarySource(Source): + source_id = "legendary" name = _("Legendary") executable_format = "legendary launch {app_name}" available_on = {"linux"} diff --git a/src/importer/sources/lutris_source.py b/src/importer/sources/lutris_source.py index 9afc977..023d3be 100644 --- a/src/importer/sources/lutris_source.py +++ b/src/importer/sources/lutris_source.py @@ -65,7 +65,7 @@ class LutrisSourceIterable(SourceIterable): "added": added_time, "hidden": row[4], "name": row[1], - "source": f"{self.source.id}_{row[3]}", + "source": f"{self.source.source_id}_{row[3]}", "game_id": self.source.game_id_format.format( runner=row[3], game_id=row[0] ), @@ -92,6 +92,7 @@ class LutrisLocations(NamedTuple): class LutrisSource(URLExecutableSource): """Generic Lutris source""" + source_id = "lutris" name = _("Lutris") iterable_class = LutrisSourceIterable url_format = "lutris:rungameid/{game_id}" @@ -108,7 +109,7 @@ class LutrisSource(URLExecutableSource): shared.home / ".local" / "share" / "lutris", ), paths={ - "pga.db": (False, "pga.db"), + "pga.db": LocationSubPath("pga.db"), }, invalid_subtitle=Location.DATA_INVALID_SUBTITLE, ), @@ -128,4 +129,4 @@ class LutrisSource(URLExecutableSource): @property def game_id_format(self): - return self.id + "_{runner}_{game_id}" + return self.source_id + "_{runner}_{game_id}" diff --git a/src/importer/sources/source.py b/src/importer/sources/source.py index 57b45d7..26b2a84 100644 --- a/src/importer/sources/source.py +++ b/src/importer/sources/source.py @@ -51,6 +51,7 @@ class SourceIterable(Iterable): class Source(Iterable): """Source of games. E.g an installed app with a config file that lists game directories""" + source_id: str name: str variant: str = None available_on: set[str] = set() @@ -65,18 +66,10 @@ class Source(Iterable): full_name_ += f" ({self.variant})" return full_name_ - @property - def id(self) -> str: # pylint: disable=invalid-name - """The source's identifier""" - id_ = self.name.lower() - if self.variant is not None: - id_ += f"_{self.variant.lower()}" - return id_ - @property def game_id_format(self) -> str: """The string format used to construct game IDs""" - return self.id + "_{game_id}" + return self.source_id + "_{game_id}" @property def is_available(self): diff --git a/src/importer/sources/steam_source.py b/src/importer/sources/steam_source.py index f1c34ba..904fb0b 100644 --- a/src/importer/sources/steam_source.py +++ b/src/importer/sources/steam_source.py @@ -92,7 +92,7 @@ class SteamSourceIterable(SourceIterable): values = { "added": added_time, "name": local_data["name"], - "source": self.source.id, + "source": self.source.source_id, "game_id": self.source.game_id_format.format(game_id=appid), "executable": self.source.executable_format.format(game_id=appid), } @@ -114,6 +114,7 @@ class SteamLocations(NamedTuple): class SteamSource(URLExecutableSource): + source_id = "steam" name = _("Steam") available_on = {"linux", "win32"} iterable_class = SteamSourceIterable diff --git a/src/preferences.py b/src/preferences.py index 53bc098..1a16123 100644 --- a/src/preferences.py +++ b/src/preferences.py @@ -143,7 +143,7 @@ class PreferencesWindow(Adw.PreferencesWindow): ): source = source_class() if not source.is_available: - expander_row = getattr(self, f"{source.id}_expander_row") + expander_row = getattr(self, f"{source.source_id}_expander_row") expander_row.set_visible(False) else: self.init_source_row(source) @@ -250,12 +250,14 @@ class PreferencesWindow(Adw.PreferencesWindow): """Set the dir subtitle for a source's action rows""" for location in ("data", "config", "cache"): # Get the action row to subtitle - action_row = getattr(self, f"{source.id}_{location}_action_row", None) + action_row = getattr( + self, f"{source.source_id}_{location}_action_row", None + ) if not action_row: continue infix = "-cache" if location == "cache" else "" - key = f"{source.id}{infix}-location" + key = f"{source.source_id}{infix}-location" path = Path(shared.schema.get_string(key)).expanduser() # Remove the path prefix if picked via Flatpak portal @@ -269,7 +271,9 @@ class PreferencesWindow(Adw.PreferencesWindow): label.select_region(-1, -1) for location_name, location in source.locations._asdict().items(): - action_row = getattr(self, f"{source.id}_{location_name}_action_row", None) + action_row = getattr( + self, f"{source.source_id}_{location_name}_action_row", None + ) if not action_row: continue @@ -311,7 +315,7 @@ class PreferencesWindow(Adw.PreferencesWindow): menu_button.add_css_class("warning") action_row.add_prefix(menu_button) - self.warning_menu_buttons[source.id] = menu_button + self.warning_menu_buttons[source.source_id] = menu_button def init_source_row(self, source: Source): """Initialize a preference row for a source class""" @@ -333,18 +337,18 @@ class PreferencesWindow(Adw.PreferencesWindow): infix = "" case _: infix = f"-{location_name}" - key = f"{source.id}{infix}-location" + key = f"{source.source_id}{infix}-location" value = str(path) shared.schema.set_string(key, value) # Update the row self.update_source_action_row_paths(source) - if self.warning_menu_buttons.get(source.id): + if self.warning_menu_buttons.get(source.source_id): action_row = getattr( - self, f"{source.id}_{location_name}_action_row", None + self, f"{source.source_id}_{location_name}_action_row", None ) - action_row.remove(self.warning_menu_buttons[source.id]) - self.warning_menu_buttons.pop(source.id) + action_row.remove(self.warning_menu_buttons[source.source_id]) + self.warning_menu_buttons.pop(source.source_id) logging.debug("User-set value for schema key %s: %s", key, value) @@ -366,9 +370,9 @@ class PreferencesWindow(Adw.PreferencesWindow): dialog.connect("response", on_response) # Bind expander row activation to source being enabled - expander_row = getattr(self, f"{source.id}_expander_row") + expander_row = getattr(self, f"{source.source_id}_expander_row") shared.schema.bind( - source.id, + source.source_id, expander_row, "enable-expansion", Gio.SettingsBindFlags.DEFAULT, @@ -377,7 +381,7 @@ class PreferencesWindow(Adw.PreferencesWindow): # Connect dir picker buttons for location_name in source.locations._asdict(): button = getattr( - self, f"{source.id}_{location_name}_file_chooser_button", None + self, f"{source.source_id}_{location_name}_file_chooser_button", None ) if button is not None: button.connect("clicked", self.choose_folder, set_dir, location_name)