From f3fd0fa5d95cb83d3fafc6f127878a108af8eae2 Mon Sep 17 00:00:00 2001 From: DevilXD Date: Thu, 14 Apr 2022 07:55:39 +0200 Subject: [PATCH] Create more oppurtinities for state saving; for image cache and settings --- cache.py | 8 +++++++- settings.py | 5 ++++- twitch.py | 10 +++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/cache.py b/cache.py index 5dc7199..fb4a081 100644 --- a/cache.py +++ b/cache.py @@ -42,6 +42,7 @@ class ImageCache: self._images: dict[ImageHash, Image] = {} self._photos: dict[tuple[ImageHash, ImageSize], PhotoImage] = {} self._lock = asyncio.Lock() + self._altered: bool = False # cleanup the URLs hash_counts: dict[ImageHash, int] = {} now = datetime.now(timezone.utc) @@ -51,6 +52,7 @@ class ImageCache: hash_counts[img_hash] = 0 if now >= hash_dict["expires"]: del self._hashes[url] + self._altered = True else: hash_counts[img_hash] += 1 for img_hash, count in hash_counts.items(): @@ -60,7 +62,8 @@ class ImageCache: file.unlink() def save(self) -> None: - json_save(CACHE_DB, self._hashes) + if self._altered: + json_save(CACHE_DB, self._hashes) def _new_expires(self) -> datetime: return datetime.now(timezone.utc) + self.LIFETIME @@ -94,6 +97,9 @@ class ImageCache: "hash": img_hash, "expires": self._new_expires() } + # NOTE: If self._hashes ever stops being updated in both above if cases, + # this will need to be moved + self._altered = True if size is None: size = image.size photo_key = (img_hash, size) diff --git a/settings.py b/settings.py index fd7771a..84122fc 100644 --- a/settings.py +++ b/settings.py @@ -50,6 +50,7 @@ class Settings: def __init__(self, args: ParsedArgs): self._settings: SettingsFile = json_load(SETTINGS_PATH, default_settings) self._args: ParsedArgs = args + self._altered: bool = False # default logic of reading settings is to check args first, then the settings file def __getattr__(self, name: str, /) -> Any: @@ -65,6 +66,7 @@ class Settings: return super().__setattr__(name, value) elif name in self._settings: self._settings[name] = value # type: ignore[literal-required] + self._altered = True return raise TypeError(f"{name} is missing a custom setter") @@ -72,4 +74,5 @@ class Settings: raise RuntimeError("settings can't be deleted") def save(self) -> None: - json_save(SETTINGS_PATH, self._settings) + if self._altered: + json_save(SETTINGS_PATH, self._settings) diff --git a/twitch.py b/twitch.py index bdfa1d0..8b39f8d 100644 --- a/twitch.py +++ b/twitch.py @@ -149,6 +149,13 @@ class Twitch: """ self.gui.print(*args, **kwargs) + def save(self) -> None: + """ + Saves the application state. + """ + self.gui.save() + self.settings.save() + @staticmethod def _viewers_key(channel: Channel) -> int: if (viewers := channel.viewers) is not None: @@ -205,6 +212,8 @@ class Twitch: self._mnt_task = asyncio.create_task(self._maintenance_task()) await self.fetch_inventory() self.gui.set_games(set(campaign.game for campaign in self.inventory)) + # Save state on every inventory fetch + self.save() self.change_state(State.GAMES_UPDATE) elif self._state is State.GAMES_UPDATE: # Figure out which games to watch, and claim the drops we can @@ -925,7 +934,6 @@ class Twitch: self._drops.update((drop.id, drop) for drop in campaign.drops) await self.gui.inv.add_campaign(campaign) self.inventory.append(campaign) - self.gui.save() def get_active_drop(self, channel: Channel | None = None) -> TimedDrop | None: if not self.games: