Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LabelMixin to Season, Episode, Artist, and Track objects #872

Merged
merged 7 commits into from
Feb 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions plexapi/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,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 @@ -137,6 +137,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 @@ -152,6 +153,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 @@ -332,7 +334,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 @@ -348,6 +350,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 @@ -377,6 +380,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 @@ -2216,16 +2216,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 @@ -2255,8 +2296,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 @@ -2265,7 +2308,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 @@ -2291,19 +2334,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 @@ -2314,8 +2364,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