Skip to content

Commit b57a528

Browse files
authored
Change Episode parent* attributes to properties (#1251)
* Change Episode parent* attributes to cached_property * This is to avoid the problems with auto-reloading when Episode objects are built with seasons hidden. * Change Episode.seasonNumber to cached_property
1 parent b129fa3 commit b57a528

File tree

1 file changed

+38
-20
lines changed

1 file changed

+38
-20
lines changed

plexapi/video.py

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22
import os
3+
from functools import cached_property
34
from pathlib import Path
45
from urllib.parse import quote_plus
56

@@ -676,7 +677,7 @@ class Season(
676677
ArtMixin, PosterMixin, ThemeUrlMixin,
677678
SeasonEditMixins
678679
):
679-
""" Represents a single Show Season (including all episodes).
680+
""" Represents a single Season.
680681
681682
Attributes:
682683
TAG (str): 'Directory'
@@ -835,7 +836,7 @@ class Episode(
835836
ArtMixin, PosterMixin, ThemeUrlMixin,
836837
EpisodeEditMixins
837838
):
838-
""" Represents a single Shows Episode.
839+
""" Represents a single Episode.
839840
840841
Attributes:
841842
TAG (str): 'Video'
@@ -864,7 +865,7 @@ class Episode(
864865
parentGuid (str): Plex GUID for the season (plex://season/5d9c09e42df347001e3c2a72).
865866
parentIndex (int): Season number of episode.
866867
parentKey (str): API URL of the season (/library/metadata/<parentRatingKey>).
867-
parentRatingKey (int): Unique key identifying the season.
868+
parentRatingKey (int): Unique key identifying the season.
868869
parentThumb (str): URL to season thumbnail image (/library/metadata/<parentRatingKey>/thumb/<thumbid>).
869870
parentTitle (str): Name of the season for the episode.
870871
parentYear (int): Year the season was released.
@@ -885,7 +886,6 @@ def _loadData(self, data):
885886
""" Load attribute values from Plex XML response. """
886887
Video._loadData(self, data)
887888
Playable._loadData(self, data)
888-
self._seasonNumber = None # cached season number
889889
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
890890
self.audienceRatingImage = data.attrib.get('audienceRatingImage')
891891
self.chapters = self.findItems(data, media.Chapter)
@@ -909,9 +909,6 @@ def _loadData(self, data):
909909
self.originallyAvailableAt = utils.toDatetime(data.attrib.get('originallyAvailableAt'), '%Y-%m-%d')
910910
self.parentGuid = data.attrib.get('parentGuid')
911911
self.parentIndex = utils.cast(int, data.attrib.get('parentIndex'))
912-
self.parentKey = data.attrib.get('parentKey')
913-
self.parentRatingKey = utils.cast(int, data.attrib.get('parentRatingKey'))
914-
self.parentThumb = data.attrib.get('parentThumb')
915912
self.parentTitle = data.attrib.get('parentTitle')
916913
self.parentYear = utils.cast(int, data.attrib.get('parentYear'))
917914
self.producers = self.findItems(data, media.Producer)
@@ -925,15 +922,38 @@ def _loadData(self, data):
925922

926923
# If seasons are hidden, parentKey and parentRatingKey are missing from the XML response.
927924
# https://forums.plex.tv/t/parentratingkey-not-in-episode-xml-when-seasons-are-hidden/300553
928-
if self.skipParent and data.attrib.get('parentRatingKey') is None:
929-
# Parse the parentRatingKey from the parentThumb
930-
if self.parentThumb and self.parentThumb.startswith('/library/metadata/'):
931-
self.parentRatingKey = utils.cast(int, self.parentThumb.split('/')[3])
932-
# Get the parentRatingKey from the season's ratingKey
933-
if not self.parentRatingKey and self.grandparentRatingKey:
934-
self.parentRatingKey = self.show().season(season=self.parentIndex).ratingKey
935-
if self.parentRatingKey:
936-
self.parentKey = f'/library/metadata/{self.parentRatingKey}'
925+
# Use cached properties below to return the correct values if they are missing to avoid auto-reloading.
926+
self._parentKey = data.attrib.get('parentKey')
927+
self._parentRatingKey = utils.cast(int, data.attrib.get('parentRatingKey'))
928+
self._parentThumb = data.attrib.get('parentThumb')
929+
930+
@cached_property
931+
def parentKey(self):
932+
""" Returns the parentKey. Refer to the Episode attributes. """
933+
return self._parentKey or f'/library/metadata/{self.parentRatingKey}'
934+
935+
@cached_property
936+
def parentRatingKey(self):
937+
""" Returns the parentRatingKey. Refer to the Episode attributes. """
938+
if self._parentRatingKey is not None:
939+
return self._parentRatingKey
940+
# Parse the parentRatingKey from the parentThumb
941+
if self._parentThumb and self._parentThumb.startswith('/library/metadata/'):
942+
return utils.cast(int, self._parentThumb.split('/')[3])
943+
# Get the parentRatingKey from the season's ratingKey
944+
return self._season.ratingKey
945+
946+
@cached_property
947+
def parentThumb(self):
948+
""" Returns the parentThumb. Refer to the Episode attributes. """
949+
return self._parentThumb or self._season.thumb
950+
951+
@cached_property
952+
def _season(self):
953+
""" Returns the :class:`~plexapi.video.Season` object by querying for the show's children. """
954+
return self.fetchItem(
955+
f'{self.grandparentKey}/children?excludeAllLeaves=1&index={self.parentIndex}'
956+
)
937957

938958
def __repr__(self):
939959
return '<{}>'.format(
@@ -968,12 +988,10 @@ def episodeNumber(self):
968988
""" Returns the episode number. """
969989
return self.index
970990

971-
@property
991+
@cached_property
972992
def seasonNumber(self):
973993
""" Returns the episode's season number. """
974-
if self._seasonNumber is None:
975-
self._seasonNumber = self.parentIndex if isinstance(self.parentIndex, int) else self.season().seasonNumber
976-
return utils.cast(int, self._seasonNumber)
994+
return self.parentIndex if isinstance(self.parentIndex, int) else self._season.seasonNumber
977995

978996
@property
979997
def seasonEpisode(self):

0 commit comments

Comments
 (0)