From 32088167c3819b69296d2ff8118e4dbe1de443b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Sun, 7 Nov 2021 23:51:08 +0200 Subject: [PATCH 1/2] Refactor: Make Walker methods async --- plextraktsync/plan/Walker.py | 72 ++++++++++++++----------- plextraktsync/sync/Sync.py | 4 +- plextraktsync/sync/SyncRatingsPlugin.py | 2 +- 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/plextraktsync/plan/Walker.py b/plextraktsync/plan/Walker.py index bff6307e62..7c0e9ec99f 100644 --- a/plextraktsync/plan/Walker.py +++ b/plextraktsync/plan/Walker.py @@ -12,7 +12,7 @@ from plextraktsync.trakt.TraktItem import TraktItem if TYPE_CHECKING: - from typing import Any, Generator, Iterable + from typing import Any, AsyncGenerator, AsyncIterable, Generator, Iterable from plexapi.video import Episode @@ -69,7 +69,7 @@ def print_plan(self, print): if self.plan.episodes: print(f"Sync Episodes: {[x.title for x in self.plan.episodes]}") - def get_plex_movies(self) -> Generator[PlexLibraryItem, Any, None]: + async def get_plex_movies(self) -> Generator[PlexLibraryItem, Any, None]: """ Iterate over movie sections unless specific movie is requested """ @@ -80,33 +80,36 @@ def get_plex_movies(self) -> Generator[PlexLibraryItem, Any, None]: else: return - yield from movies + async for m in movies: + yield m - def find_movies(self) -> Generator[Media, Any, None]: - for plex in self.get_plex_movies(): + async def find_movies(self) -> Generator[Media, Any, None]: + async for plex in self.get_plex_movies(): movie = self.mf.resolve_any(plex) if not movie: continue yield movie - def get_plex_shows(self) -> Generator[PlexLibraryItem, Any, None]: + async def get_plex_shows(self) -> AsyncGenerator[PlexLibraryItem, Any, None]: if self.plan.shows: - shows = self.media_from_items("show", self.plan.shows) + it = self.media_from_items("show", self.plan.shows) elif self.plan.show_sections: - shows = self.media_from_sections(self.plan.show_sections) + it = self.media_from_sections(self.plan.show_sections) else: return - yield from shows + async for m in it: + yield m - def find_episodes(self): + async def find_episodes(self): if self.plan.episodes: - yield from self.get_plex_episodes(self.plan.episodes) + async for m in self.get_plex_episodes(self.plan.episodes): + yield m # Preload plex shows plex_shows: dict[int, PlexLibraryItem] = {} self.logger.info("Preload shows data") - for show in self.get_plex_shows(): + async for show in self.get_plex_shows(): plex_shows[show.key] = show self.logger.info(f"Preloaded shows data ({len(plex_shows)} shows)") @@ -114,11 +117,11 @@ def find_episodes(self): show_cache: dict[int, Media] = {} self.logger.info("Preload shows matches") it = self.progressbar(plex_shows.items(), desc="Processing show matches") - for show_id, ps in it: + async for show_id, ps in it: show_cache[show_id] = self.mf.resolve_any(ps) self.logger.info(f"Preloaded shows matches ({len(show_cache)} shows)") - for ep in self.episodes_from_sections(self.plan.show_sections): + async for ep in self.episodes_from_sections(self.plan.show_sections): show_id = ep.show_id ep.show = plex_shows[show_id] show = show_cache[show_id] if show_id in show_cache else None @@ -130,14 +133,15 @@ def find_episodes(self): show_cache[show_id] = m.show yield m - def walk_shows(self, shows: set[Media], title="Processing Shows"): + async def walk_shows(self, shows: set[Media], title="Processing Shows"): if not shows: return - yield from self.progressbar(shows, desc=title) + async for show in self.progressbar(shows, desc=title): + yield show - def get_plex_episodes(self, episodes: list[Episode]) -> Generator[Media, Any, None]: + async def get_plex_episodes(self, episodes: list[Episode]) -> Generator[Media, Any, None]: it = self.progressbar(episodes, desc="Processing episodes") - for pe in it: + async for pe in it: guid = PlexGuid(pe.grandparentGuid, "show") show = self.mf.resolve_guid(guid) if not show: @@ -149,7 +153,7 @@ def get_plex_episodes(self, episodes: list[Episode]) -> Generator[Media, Any, No me.show = show yield me - def media_from_sections(self, sections: list[PlexLibrarySection]) -> Generator[PlexLibraryItem, Any, None]: + async def media_from_sections(self, sections: list[PlexLibrarySection]) -> AsyncGenerator[PlexLibraryItem, Any, None]: for section in sections: with measure_time(f"{section.title_link} processed", extra={"markup": True}): self.set_window_title(f"Processing {section.title}") @@ -157,9 +161,10 @@ def media_from_sections(self, sections: list[PlexLibrarySection]) -> Generator[P section.pager(), desc=f"Processing {section.title_link}", ) - yield from it + async for m in it: + yield m - def episodes_from_sections(self, sections: list[PlexLibrarySection]) -> Generator[PlexLibraryItem, Any, None]: + async def episodes_from_sections(self, sections: list[PlexLibrarySection]) -> Generator[PlexLibraryItem, Any, None]: for section in sections: with measure_time(f"{section.title_link} processed", extra={"markup": True}): self.set_window_title(f"Processing {section.title}") @@ -167,14 +172,15 @@ def episodes_from_sections(self, sections: list[PlexLibrarySection]) -> Generato section.pager("episode"), desc=f"Processing {section.title_link}", ) - yield from it + async for m in it: + yield m - def media_from_items(self, libtype: str, items: list) -> Generator[PlexLibraryItem, Any, None]: + async def media_from_items(self, libtype: str, items: list) -> AsyncGenerator[PlexLibraryItem, Any, None]: it = self.progressbar(items, desc=f"Processing {libtype}s") - for m in it: + async for m in it: yield PlexLibraryItem(m, plex=self.plex) - def episode_from_show(self, show: Media) -> Generator[Media, Any, None]: + async def episode_from_show(self, show: Media) -> Generator[Media, Any, None]: for pe in show.plex.episodes(): me = self.mf.resolve_any(pe, show) if not me: @@ -183,24 +189,26 @@ def episode_from_show(self, show: Media) -> Generator[Media, Any, None]: me.show = show yield me - def progressbar(self, iterable: Iterable, **kwargs): + async def progressbar(self, iterable: AsyncIterable | Iterable, **kwargs): if self._progressbar: pb = self._progressbar(iterable, **kwargs) with pb as it: - yield from it + async for m in it: + yield m else: - yield from iterable + async for m in iterable: + yield m - def media_from_traktlist(self, items: Iterable, title="Trakt watchlist") -> Generator[Media, Any, None]: + async def media_from_traktlist(self, items: AsyncIterable, title="Trakt watchlist") -> Generator[Media, Any, None]: it = self.progressbar(items, desc=f"Processing {title}") - for media in it: + async for media in it: tm = TraktItem(media) m = self.mf.resolve_trakt(tm) yield m - def media_from_plexlist(self, items: Iterable) -> Generator[Media, Any, None]: + async def media_from_plexlist(self, items: AsyncIterable) -> Generator[Media, Any, None]: it = self.progressbar(items, desc="Processing Plex watchlist") - for media in it: + async for media in it: pm = PlexLibraryItem(media, plex=self.plex) m = self.mf.resolve_any(pm) if not m: diff --git a/plextraktsync/sync/Sync.py b/plextraktsync/sync/Sync.py index 82730c69ed..51a2f642de 100644 --- a/plextraktsync/sync/Sync.py +++ b/plextraktsync/sync/Sync.py @@ -37,10 +37,10 @@ async def sync(self, walker: Walker, dry_run=False): pm.hook.init(sync=self, pm=pm, is_partial=is_partial, dry_run=dry_run) if self.config.need_library_walk: - for movie in walker.find_movies(): + async for movie in walker.find_movies(): await pm.ahook.walk_movie(movie=movie, dry_run=dry_run) - for episode in walker.find_episodes(): + async for episode in walker.find_episodes(): await pm.ahook.walk_episode(episode=episode, dry_run=dry_run) await pm.ahook.fini(walker=walker, dry_run=dry_run) diff --git a/plextraktsync/sync/SyncRatingsPlugin.py b/plextraktsync/sync/SyncRatingsPlugin.py index 3b217248f7..af7ac364e5 100644 --- a/plextraktsync/sync/SyncRatingsPlugin.py +++ b/plextraktsync/sync/SyncRatingsPlugin.py @@ -32,7 +32,7 @@ def init(self): @hookimpl async def fini(self, walker: Walker, dry_run: bool): - for show in walker.walk_shows(self.shows, title="Syncing show ratings"): + async for show in walker.walk_shows(self.shows, title="Syncing show ratings"): self.sync_ratings(show, dry_run=dry_run) @hookimpl From 9968a100d075be849b3ce11bec17d9778738ab32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 30 Apr 2024 20:30:55 +0300 Subject: [PATCH 2/2] Make plugin submethods async --- plextraktsync/sync/AddCollectionPlugin.py | 6 +++--- plextraktsync/sync/SyncRatingsPlugin.py | 8 ++++---- plextraktsync/sync/SyncWatchedPlugin.py | 6 +++--- plextraktsync/sync/WatchProgressPlugin.py | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/plextraktsync/sync/AddCollectionPlugin.py b/plextraktsync/sync/AddCollectionPlugin.py index 1f48cf93a2..e49866f93c 100644 --- a/plextraktsync/sync/AddCollectionPlugin.py +++ b/plextraktsync/sync/AddCollectionPlugin.py @@ -22,13 +22,13 @@ def factory(cls, sync): @hookimpl async def walk_movie(self, movie: Media, dry_run: bool): - self.sync_collection(movie, dry_run=dry_run) + await self.sync_collection(movie, dry_run=dry_run) @hookimpl async def walk_episode(self, episode: Media, dry_run: bool): - self.sync_collection(episode, dry_run=dry_run) + await self.sync_collection(episode, dry_run=dry_run) - def sync_collection(self, m: Media, dry_run: bool): + async def sync_collection(self, m: Media, dry_run: bool): if m.is_collected: return diff --git a/plextraktsync/sync/SyncRatingsPlugin.py b/plextraktsync/sync/SyncRatingsPlugin.py index af7ac364e5..c7a93cd55f 100644 --- a/plextraktsync/sync/SyncRatingsPlugin.py +++ b/plextraktsync/sync/SyncRatingsPlugin.py @@ -33,20 +33,20 @@ def init(self): @hookimpl async def fini(self, walker: Walker, dry_run: bool): async for show in walker.walk_shows(self.shows, title="Syncing show ratings"): - self.sync_ratings(show, dry_run=dry_run) + await self.sync_ratings(show, dry_run=dry_run) @hookimpl async def walk_movie(self, movie: Media, dry_run: bool): - self.sync_ratings(movie, dry_run=dry_run) + await self.sync_ratings(movie, dry_run=dry_run) @hookimpl async def walk_episode(self, episode: Media, dry_run: bool): - self.sync_ratings(episode, dry_run=dry_run) + await self.sync_ratings(episode, dry_run=dry_run) if episode.show: self.shows.add(episode.show) - def sync_ratings(self, m: Media, dry_run: bool): + async def sync_ratings(self, m: Media, dry_run: bool): if m.plex_rating == m.trakt_rating: return diff --git a/plextraktsync/sync/SyncWatchedPlugin.py b/plextraktsync/sync/SyncWatchedPlugin.py index 0e6325b2ef..ce4eaf4c50 100644 --- a/plextraktsync/sync/SyncWatchedPlugin.py +++ b/plextraktsync/sync/SyncWatchedPlugin.py @@ -26,13 +26,13 @@ def factory(cls, sync: Sync): @hookimpl async def walk_movie(self, movie: Media, dry_run: bool): - self.sync_watched(movie, dry_run=dry_run) + await self.sync_watched(movie, dry_run=dry_run) @hookimpl async def walk_episode(self, episode: Media, dry_run: bool): - self.sync_watched(episode, dry_run=dry_run) + await self.sync_watched(episode, dry_run=dry_run) - def sync_watched(self, m: Media, dry_run: bool): + async def sync_watched(self, m: Media, dry_run: bool): if m.watched_on_plex is m.watched_on_trakt: return diff --git a/plextraktsync/sync/WatchProgressPlugin.py b/plextraktsync/sync/WatchProgressPlugin.py index 4805f9ed23..84969c85b0 100644 --- a/plextraktsync/sync/WatchProgressPlugin.py +++ b/plextraktsync/sync/WatchProgressPlugin.py @@ -29,13 +29,13 @@ def factory(cls, sync: Sync): @hookimpl async def walk_movie(self, movie: Media, dry_run: bool): - self.sync_progress(movie, dry_run=dry_run) + await self.sync_progress(movie, dry_run=dry_run) @hookimpl async def walk_episode(self, episode: Media, dry_run: bool): - self.sync_progress(episode, dry_run=dry_run) + await self.sync_progress(episode, dry_run=dry_run) - def sync_progress(self, m: Media, dry_run=False): + async def sync_progress(self, m: Media, dry_run=False): p = self.trakt.watch_progress.match(m) if not p: return