From f2912e273e0dc286b4a16cfe774ff8f815bf531b Mon Sep 17 00:00:00 2001 From: Adam Lohr Date: Tue, 14 Feb 2023 15:14:46 -0800 Subject: [PATCH 1/4] Cache & hash image dir listing for performance --- plugin/library.py | 40 +++++++++++++++++++++++++++++++--------- plugin/loginusers.py | 5 +++-- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/plugin/library.py b/plugin/library.py index a6a2b79..f114787 100644 --- a/plugin/library.py +++ b/plugin/library.py @@ -23,6 +23,7 @@ def games(self): Return a list of games in this library. """ games = [] + image_dir = LibraryImageDir(Path(self.steam.path).joinpath('appcache', 'librarycache')) for appmanifest in Path(self.path).joinpath('steamapps').glob('appmanifest_*.acf'): try: manifest = VDF(appmanifest) @@ -45,22 +46,47 @@ def games(self): path=Path(self.path).joinpath( manifest['AppState']['installdir']), id=manifest['AppState']['appid'], - image_dir=Path(self.steam.path).joinpath( - 'appcache', 'librarycache'), + image_dir=image_dir, ) ) return games +class LibraryImageDir: + """ + Caches the filesystem access of a library image directory + """ + + def __init__(self, image_dir: Union[str, Path]): + image_dir = Path(image_dir) + self.grid = image_dir.name == 'grid' + self._files_cache = {} + self._iterdir = image_dir.iterdir() + + def get_image(self, id: str, type: str, sep='_') -> Path: + if self.grid: + # Grid images use short ID format + id = self.short_id() + + prefix = f'{id}{sep}{type}' + if prefix in self._files_cache: + return self._files_cache[prefix] + else: + for file in self._iterdir: + haystack_prefix = file.name.split(".", 1)[0] + self._files_cache[haystack_prefix] = file + if prefix == haystack_prefix: + return file + return None class LibraryItem: """ Base class for all library items. """ - def __init__(self, name: str, path: Union[str, Path], image_dir: Union[str, Path], id: str = None): + def __init__(self, name: str, path: Union[str, Path], image_dir: LibraryImageDir, id: str = None): self.name = name self.path = Path(path) - self.image_dir = Path(image_dir) + self.image_dir = image_dir self._id = id self._image_id = self.id @@ -87,11 +113,7 @@ def launch(self) -> None: webbrowser.open(self.uri()) def get_image(self, type: str, sep='_') -> Path: - id = self.id - if Path(self.image_dir).name == 'grid': - # Grid images use short ID format - id = self.short_id() - return next(Path(self.image_dir).glob(f'{id}{sep}{type}.*'), None) + return self.image_dir.get_image(self.id, type, sep) @cached_property def icon(self) -> Path: diff --git a/plugin/loginusers.py b/plugin/loginusers.py index d2bc673..0daef4b 100644 --- a/plugin/loginusers.py +++ b/plugin/loginusers.py @@ -5,7 +5,7 @@ from collections import UserList from .vdfs import VDF -from .library import LibraryItem +from .library import LibraryItem, LibraryImageDir if TYPE_CHECKING: from steam import Steam @@ -75,12 +75,13 @@ def shortcuts(self) -> list: split = _shortcuts.split(b'AppName\x00')[1:] if len(split) == 0: return _list + image_dir = LibraryImageDir(self.grid_path) for shortcut in _shortcuts.split(b'AppName\x00')[1:]: _list.append( LibraryItem( name=shortcut.split(b'\x00')[0].decode('utf-8'), path=shortcut.split(b'\x00')[2].decode('utf-8'), - image_dir=self.grid_path + image_dir=image_dir ) ) return _list From a321a77ded1a0726b6522d89a27bd0cabb5245ef Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 15 Feb 2023 16:25:50 -0500 Subject: [PATCH 2/4] Pass short ID for grid images --- plugin/library.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugin/library.py b/plugin/library.py index f114787..41c712d 100644 --- a/plugin/library.py +++ b/plugin/library.py @@ -63,9 +63,6 @@ def __init__(self, image_dir: Union[str, Path]): self._iterdir = image_dir.iterdir() def get_image(self, id: str, type: str, sep='_') -> Path: - if self.grid: - # Grid images use short ID format - id = self.short_id() prefix = f'{id}{sep}{type}' if prefix in self._files_cache: @@ -113,7 +110,11 @@ def launch(self) -> None: webbrowser.open(self.uri()) def get_image(self, type: str, sep='_') -> Path: - return self.image_dir.get_image(self.id, type, sep) + id = self.id + if self.image_dir.grid: + # Grid images use the short version ID + id = self.short_id() + return self.image_dir.get_image(id, type, sep) @cached_property def icon(self) -> Path: From fed2a983df6dc0067b8cf7619a2c6f5d00e3318e Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 15 Feb 2023 16:26:36 -0500 Subject: [PATCH 3/4] Fix comment typo --- plugin/library.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/library.py b/plugin/library.py index 41c712d..48a2177 100644 --- a/plugin/library.py +++ b/plugin/library.py @@ -112,7 +112,7 @@ def launch(self) -> None: def get_image(self, type: str, sep='_') -> Path: id = self.id if self.image_dir.grid: - # Grid images use the short version ID + # Grid images use the short ID id = self.short_id() return self.image_dir.get_image(id, type, sep) From cadc194b9a70bed84984dae081d8a929579b00c8 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 15 Feb 2023 16:29:50 -0500 Subject: [PATCH 4/4] Major version update --- plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin.json b/plugin.json index 14c4c1f..4b89ab9 100644 --- a/plugin.json +++ b/plugin.json @@ -4,7 +4,7 @@ "Name": "Steam Search", "Description": "Search and launch your Steam Game library", "Author": "Garulf", - "Version": "7.2.0", + "Version": "8.0.0", "Language": "executable", "Website": "https://github.com/Garulf/Steam-Search", "IcoPath": "run.exe",