Skip to content

Commit

Permalink
Add LabelMixin to Season, Episode, Artist, and Track objects (#872)
Browse files Browse the repository at this point in the history
* Add LabelMixin to Episode class

* Add test_mixins.edit_label(episode) test

* Add Label Mixin to Season, Artist,and Track

* fix tests

* Load manual FilteringFields for labels

* Load manual FilteringFilters for labels

Co-authored-by: Elan Ruusamäe <[email protected]>
Co-authored-by: JonnyWong16 <[email protected]>
  • Loading branch information
3 people authored Feb 27, 2022
1 parent 158dd37 commit 2f101e3
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 14 deletions.
8 changes: 6 additions & 2 deletions plexapi/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def sync(self, bitrate, client=None, clientId=None, limit=None, title=None):

@utils.registerPlexObject
class Artist(Audio, AdvancedSettingsMixin, ArtMixin, PosterMixin, RatingMixin, SplitMergeMixin, UnmatchMatchMixin,
CollectionMixin, CountryMixin, GenreMixin, MoodMixin, SimilarArtistMixin, StyleMixin):
CollectionMixin, CountryMixin, GenreMixin, LabelMixin, MoodMixin, SimilarArtistMixin, StyleMixin):
""" Represents a single Artist.
Attributes:
Expand All @@ -138,6 +138,7 @@ class Artist(Audio, AdvancedSettingsMixin, ArtMixin, PosterMixin, RatingMixin, S
countries (List<:class:`~plexapi.media.Country`>): List country objects.
genres (List<:class:`~plexapi.media.Genre`>): List of genre objects.
key (str): API URL (/library/metadata/<ratingkey>).
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
locations (List<str>): List of folder paths where the artist is found on disk.
similar (List<:class:`~plexapi.media.Similar`>): List of similar objects.
styles (List<:class:`~plexapi.media.Style`>): List of style objects.
Expand All @@ -153,6 +154,7 @@ def _loadData(self, data):
self.countries = self.findItems(data, media.Country)
self.genres = self.findItems(data, media.Genre)
self.key = self.key.replace('/children', '') # FIX_BUG_50
self.labels = self.findItems(data, media.Label)
self.locations = self.listAttrs(data, 'path', etag='Location')
self.similar = self.findItems(data, media.Similar)
self.styles = self.findItems(data, media.Style)
Expand Down Expand Up @@ -338,7 +340,7 @@ def _defaultSyncTitle(self):

@utils.registerPlexObject
class Track(Audio, Playable, ArtUrlMixin, PosterUrlMixin, RatingMixin,
CollectionMixin, MoodMixin):
CollectionMixin, LabelMixin, MoodMixin):
""" Represents a single Track.
Attributes:
Expand All @@ -354,6 +356,7 @@ class Track(Audio, Playable, ArtUrlMixin, PosterUrlMixin, RatingMixin,
grandparentThumb (str): URL to album artist thumbnail image
(/library/metadata/<grandparentRatingKey>/thumb/<thumbid>).
grandparentTitle (str): Name of the album artist for the track.
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
media (List<:class:`~plexapi.media.Media`>): List of media objects.
originalTitle (str): The artist for the track.
parentGuid (str): Plex GUID for the album (plex://album/5d07cd8e403c640290f180f9).
Expand Down Expand Up @@ -383,6 +386,7 @@ def _loadData(self, data):
self.grandparentRatingKey = utils.cast(int, data.attrib.get('grandparentRatingKey'))
self.grandparentThumb = data.attrib.get('grandparentThumb')
self.grandparentTitle = data.attrib.get('grandparentTitle')
self.labels = self.findItems(data, media.Label)
self.media = self.findItems(data, media.Media)
self.originalTitle = data.attrib.get('originalTitle')
self.parentGuid = data.attrib.get('parentGuid')
Expand Down
72 changes: 62 additions & 10 deletions plexapi/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -2236,16 +2236,57 @@ def _loadData(self, data):
self.title = data.attrib.get('title')
self.type = data.attrib.get('type')

# Add additional manual sorts and fields which are available
self._librarySectionID = self._parent().key

# Add additional manual filters, sorts, and fields which are available
# but not exposed on the Plex server
self.filters += self._manualFilters()
self.sorts += self._manualSorts()
self.fields += self._manualFields()

def _manualFilters(self):
""" Manually add additional filters which are available
but not exposed on the Plex server.
"""
# Filters: (filter, type, title)
additionalFilters = [
]

if self.type == 'season':
additionalFilters.extend([
('label', 'string', 'Labels')
])
elif self.type == 'episode':
additionalFilters.extend([
('label', 'string', 'Labels')
])
elif self.type == 'artist':
additionalFilters.extend([
('label', 'string', 'Labels')
])
elif self.type == 'track':
additionalFilters.extend([
('label', 'string', 'Labels')
])

manualFilters = []
for filterTag, filterType, filterTitle in additionalFilters:
filterKey = '/library/sections/%s/%s?type=%s' % (
self._librarySectionID, filterTag, utils.searchType(self.type)
)
filterXML = (
'<Filter filter="%s" filterType="%s" key="%s" title="%s" type="filter" />'
% (filterTag, filterType, filterKey, filterTitle)
)
manualFilters.append(self._manuallyLoadXML(filterXML, FilteringFilter))

return manualFilters

def _manualSorts(self):
""" Manually add additional sorts which are available
but not exposed on the Plex server.
"""
# Sorts: key, dir, title
# Sorts: (key, dir, title)
additionalSorts = [
('guid', 'asc', 'Guid'),
('id', 'asc', 'Rating Key'),
Expand Down Expand Up @@ -2275,8 +2316,10 @@ def _manualSorts(self):

manualSorts = []
for sortField, sortDir, sortTitle in additionalSorts:
sortXML = ('<Sort defaultDirection="%s" descKey="%s:desc" key="%s" title="%s" />'
% (sortDir, sortField, sortField, sortTitle))
sortXML = (
'<Sort defaultDirection="%s" descKey="%s:desc" key="%s" title="%s" />'
% (sortDir, sortField, sortField, sortTitle)
)
manualSorts.append(self._manuallyLoadXML(sortXML, FilteringSort))

return manualSorts
Expand All @@ -2285,7 +2328,7 @@ def _manualFields(self):
""" Manually add additional fields which are available
but not exposed on the Plex server.
"""
# Fields: key, type, title
# Fields: (key, type, title)
additionalFields = [
('guid', 'string', 'Guid'),
('id', 'integer', 'Rating Key'),
Expand All @@ -2311,19 +2354,26 @@ def _manualFields(self):
additionalFields.extend([
('addedAt', 'date', 'Date Season Added'),
('unviewedLeafCount', 'integer', 'Episode Unplayed Count'),
('year', 'integer', 'Season Year')
('year', 'integer', 'Season Year'),
('label', 'tag', 'Label')
])
elif self.type == 'episode':
additionalFields.extend([
('audienceRating', 'integer', 'Audience Rating'),
('duration', 'integer', 'Duration'),
('rating', 'integer', 'Critic Rating'),
('viewOffset', 'integer', 'View Offset')
('viewOffset', 'integer', 'View Offset'),
('label', 'tag', 'Label')
])
elif self.type == 'artist':
additionalFields.extend([
('label', 'tag', 'Label')
])
elif self.type == 'track':
additionalFields.extend([
('duration', 'integer', 'Duration'),
('viewOffset', 'integer', 'View Offset')
('viewOffset', 'integer', 'View Offset'),
('label', 'tag', 'Label')
])
elif self.type == 'collection':
additionalFields.extend([
Expand All @@ -2334,8 +2384,10 @@ def _manualFields(self):

manualFields = []
for field, fieldType, fieldTitle in additionalFields:
fieldXML = ('<Field key="%s%s" title="%s" type="%s"/>'
% (prefix, field, fieldTitle, fieldType))
fieldXML = (
'<Field key="%s%s" title="%s" type="%s"/>'
% (prefix, field, fieldTitle, fieldType)
)
manualFields.append(self._manuallyLoadXML(fieldXML, FilteringField))

return manualFields
Expand Down
8 changes: 6 additions & 2 deletions plexapi/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ def download(self, savepath=None, keep_original_name=False, subfolders=False, **


@utils.registerPlexObject
class Season(Video, ArtMixin, PosterMixin, RatingMixin, CollectionMixin):
class Season(Video, ArtMixin, PosterMixin, RatingMixin, CollectionMixin, LabelMixin):
""" Represents a single Show Season (including all episodes).
Attributes:
Expand All @@ -584,6 +584,7 @@ class Season(Video, ArtMixin, PosterMixin, RatingMixin, CollectionMixin):
guids (List<:class:`~plexapi.media.Guid`>): List of guid objects.
index (int): Season number.
key (str): API URL (/library/metadata/<ratingkey>).
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
leafCount (int): Number of items in the season view.
parentGuid (str): Plex GUID for the show (plex://show/5d9c086fe9d5a1001f4d9fe6).
parentIndex (int): Plex index number for the show.
Expand All @@ -607,6 +608,7 @@ def _loadData(self, data):
self.guids = self.findItems(data, media.Guid)
self.index = utils.cast(int, data.attrib.get('index'))
self.key = self.key.replace('/children', '') # FIX_BUG_50
self.labels = self.findItems(data, media.Label)
self.leafCount = utils.cast(int, data.attrib.get('leafCount'))
self.parentGuid = data.attrib.get('parentGuid')
self.parentIndex = utils.cast(int, data.attrib.get('parentIndex'))
Expand Down Expand Up @@ -710,7 +712,7 @@ def _defaultSyncTitle(self):

@utils.registerPlexObject
class Episode(Video, Playable, ArtMixin, PosterMixin, RatingMixin,
CollectionMixin, DirectorMixin, WriterMixin):
CollectionMixin, DirectorMixin, LabelMixin, WriterMixin):
""" Represents a single Shows Episode.
Attributes:
Expand All @@ -733,6 +735,7 @@ class Episode(Video, Playable, ArtMixin, PosterMixin, RatingMixin,
grandparentTitle (str): Name of the show for the episode.
guids (List<:class:`~plexapi.media.Guid`>): List of guid objects.
index (int): Episode number.
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
markers (List<:class:`~plexapi.media.Marker`>): List of marker objects.
media (List<:class:`~plexapi.media.Media`>): List of media objects.
originallyAvailableAt (datetime): Datetime the episode was released.
Expand Down Expand Up @@ -777,6 +780,7 @@ def _loadData(self, data):
self.grandparentTitle = data.attrib.get('grandparentTitle')
self.guids = self.findItems(data, media.Guid)
self.index = utils.cast(int, data.attrib.get('index'))
self.labels = self.findItems(data, media.Label)
self.markers = self.findItems(data, media.Marker)
self.media = self.findItems(data, media.Media)
self.originallyAvailableAt = utils.toDatetime(data.attrib.get('originallyAvailableAt'), '%Y-%m-%d')
Expand Down
2 changes: 2 additions & 0 deletions tests/test_audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def test_audio_Artist_mixins_tags(artist):
test_mixins.edit_collection(artist)
test_mixins.edit_country(artist)
test_mixins.edit_genre(artist)
test_mixins.edit_label(artist)
test_mixins.edit_mood(artist)
test_mixins.edit_similar_artist(artist)
test_mixins.edit_style(artist)
Expand Down Expand Up @@ -368,6 +369,7 @@ def test_audio_Track_mixins_rating(track):

def test_audio_Track_mixins_tags(track):
test_mixins.edit_collection(track)
test_mixins.edit_label(track)
test_mixins.edit_mood(track)


Expand Down
2 changes: 2 additions & 0 deletions tests/test_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,7 @@ def test_video_Season_mixins_rating(show):
def test_video_Season_mixins_tags(show):
season = show.season(season=1)
test_mixins.edit_collection(season)
test_mixins.edit_label(season)


def test_video_Season_PlexWebURL(plex, season):
Expand Down Expand Up @@ -1149,6 +1150,7 @@ def test_video_Episode_mixins_tags(episode):
test_mixins.edit_collection(episode)
test_mixins.edit_director(episode)
test_mixins.edit_writer(episode)
test_mixins.edit_label(episode)


def test_video_Episode_media_tags(episode):
Expand Down

0 comments on commit 2f101e3

Please sign in to comment.