diff --git a/plexapi/audio.py b/plexapi/audio.py index f1c88a1d..686073a3 100644 --- a/plexapi/audio.py +++ b/plexapi/audio.py @@ -193,6 +193,7 @@ class Artist( similar (List<:class:`~plexapi.media.Similar`>): List of similar objects. styles (List<:class:`~plexapi.media.Style`>): List of style objects. theme (str): URL to theme resource (/library/metadata//theme/). + ultraBlurColors (:class:`~plexapi.media.UltraBlurColors`): Ultra blur color object. """ TAG = 'Directory' TYPE = 'artist' @@ -213,6 +214,7 @@ class Artist( self.similar = self.findItems(data, media.Similar) self.styles = self.findItems(data, media.Style) self.theme = data.attrib.get('theme') + self.ultraBlurColors = self.findItem(data, media.UltraBlurColors) def __iter__(self): for album in self.albums(): @@ -340,6 +342,7 @@ class Album( studio (str): Studio that released the album. styles (List<:class:`~plexapi.media.Style`>): List of style objects. subformats (List<:class:`~plexapi.media.Subformat`>): List of subformat objects. + ultraBlurColors (:class:`~plexapi.media.UltraBlurColors`): Ultra blur color object. viewedLeafCount (int): Number of items marked as played in the album view. year (int): Year the album was released. """ @@ -369,6 +372,7 @@ class Album( self.studio = data.attrib.get('studio') self.styles = self.findItems(data, media.Style) self.subformats = self.findItems(data, media.Subformat) + self.ultraBlurColors = self.findItem(data, media.UltraBlurColors) self.viewedLeafCount = utils.cast(int, data.attrib.get('viewedLeafCount')) self.year = utils.cast(int, data.attrib.get('year')) diff --git a/plexapi/collection.py b/plexapi/collection.py index d71ddf2f..1c3ba3f7 100644 --- a/plexapi/collection.py +++ b/plexapi/collection.py @@ -60,6 +60,7 @@ class Collection( title (str): Name of the collection. titleSort (str): Title to use when sorting (defaults to title). type (str): 'collection' + ultraBlurColors (:class:`~plexapi.media.UltraBlurColors`): Ultra blur color object. updatedAt (datetime): Datetime the collection was updated. userRating (float): Rating of the collection (0.0 - 10.0) equaling (0 stars - 5 stars). """ @@ -102,6 +103,7 @@ class Collection( self.title = data.attrib.get('title') self.titleSort = data.attrib.get('titleSort', self.title) self.type = data.attrib.get('type') + self.ultraBlurColors = self.findItem(data, media.UltraBlurColors) self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt')) self.userRating = utils.cast(float, data.attrib.get('userRating')) self._items = None # cache for self.items diff --git a/plexapi/media.py b/plexapi/media.py index 36020791..2f76d722 100644 --- a/plexapi/media.py +++ b/plexapi/media.py @@ -1003,6 +1003,28 @@ class Review(PlexObject): self.text = data.attrib.get('text') +@utils.registerPlexObject +class UltraBlurColors(PlexObject): + """ Represents a single UltraBlurColors media tag. + + Attributes: + TAG (str): 'UltraBlurColors' + bottomLeft (str): The bottom left hex color. + bottomRight (str): The bottom right hex color. + topLeft (str): The top left hex color. + topRight (str): The top right hex color. + """ + TAG = 'UltraBlurColors' + + def _loadData(self, data): + """ Load attribute values from Plex XML response. """ + self._data = data + self.bottomLeft = data.attrib.get('bottomLeft') + self.bottomRight = data.attrib.get('bottomRight') + self.topLeft = data.attrib.get('topLeft') + self.topRight = data.attrib.get('topRight') + + class BaseResource(PlexObject): """ Base class for all Art, Poster, and Theme objects. diff --git a/plexapi/video.py b/plexapi/video.py index 8622d4a7..15755415 100644 --- a/plexapi/video.py +++ b/plexapi/video.py @@ -375,6 +375,7 @@ class Movie( studio (str): Studio that created movie (Di Bonaventura Pictures; 21 Laps Entertainment). tagline (str): Movie tag line (Back 2 Work; Who says men can't change?). theme (str): URL to theme resource (/library/metadata//theme/). + ultraBlurColors (:class:`~plexapi.media.UltraBlurColors`): Ultra blur color object. useOriginalTitle (int): Setting that indicates if the original title is used for the movie (-1 = Library default, 0 = No, 1 = Yes). viewOffset (int): View offset in milliseconds. @@ -420,6 +421,7 @@ class Movie( self.studio = data.attrib.get('studio') self.tagline = data.attrib.get('tagline') self.theme = data.attrib.get('theme') + self.ultraBlurColors = self.findItem(data, media.UltraBlurColors) self.useOriginalTitle = utils.cast(int, data.attrib.get('useOriginalTitle', '-1')) self.viewOffset = utils.cast(int, data.attrib.get('viewOffset', 0)) self.writers = self.findItems(data, media.Writer) @@ -543,6 +545,7 @@ class Show( (-1 = Account default, 0 = Manually selected, 1 = Shown with foreign audio, 2 = Always enabled). tagline (str): Show tag line. theme (str): URL to theme resource (/library/metadata//theme/). + ultraBlurColors (:class:`~plexapi.media.UltraBlurColors`): Ultra blur color object. useOriginalTitle (int): Setting that indicates if the original title is used for the show (-1 = Library default, 0 = No, 1 = Yes). viewedLeafCount (int): Number of items marked as played in the show view. @@ -592,6 +595,7 @@ class Show( self.subtitleMode = utils.cast(int, data.attrib.get('subtitleMode', '-1')) self.tagline = data.attrib.get('tagline') self.theme = data.attrib.get('theme') + self.ultraBlurColors = self.findItem(data, media.UltraBlurColors) self.useOriginalTitle = utils.cast(int, data.attrib.get('useOriginalTitle', '-1')) self.viewedLeafCount = utils.cast(int, data.attrib.get('viewedLeafCount')) self.year = utils.cast(int, data.attrib.get('year')) @@ -735,6 +739,7 @@ class Season( subtitleLanguage (str): Setting that indicates the preferred subtitle language. subtitleMode (int): Setting that indicates the auto-select subtitle mode. (-1 = Series default, 0 = Manually selected, 1 = Shown with foreign audio, 2 = Always enabled). + ultraBlurColors (:class:`~plexapi.media.UltraBlurColors`): Ultra blur color object. viewedLeafCount (int): Number of items marked as played in the season view. year (int): Year the season was released. """ @@ -766,6 +771,7 @@ class Season( self.ratings = self.findItems(data, media.Rating) self.subtitleLanguage = data.attrib.get('subtitleLanguage', '') self.subtitleMode = utils.cast(int, data.attrib.get('subtitleMode', '-1')) + self.ultraBlurColors = self.findItem(data, media.UltraBlurColors) self.viewedLeafCount = utils.cast(int, data.attrib.get('viewedLeafCount')) self.year = utils.cast(int, data.attrib.get('year')) @@ -914,6 +920,7 @@ class Episode( skipParent (bool): True if the show's seasons are set to hidden. sourceURI (str): Remote server URI (server:///com.plexapp.plugins.library) (remote playlist item only). + ultraBlurColors (:class:`~plexapi.media.UltraBlurColors`): Ultra blur color object. viewOffset (int): View offset in milliseconds. writers (List<:class:`~plexapi.media.Writer`>): List of writers objects. year (int): Year the episode was released. @@ -958,6 +965,7 @@ class Episode( self.roles = self.findItems(data, media.Role) self.skipParent = utils.cast(bool, data.attrib.get('skipParent', '0')) self.sourceURI = data.attrib.get('source') # remote playlist item + self.ultraBlurColors = self.findItem(data, media.UltraBlurColors) self.viewOffset = utils.cast(int, data.attrib.get('viewOffset', 0)) self.writers = self.findItems(data, media.Writer) self.year = utils.cast(int, data.attrib.get('year')) diff --git a/tests/test_audio.py b/tests/test_audio.py index 4f9b5403..6440c702 100644 --- a/tests/test_audio.py +++ b/tests/test_audio.py @@ -44,6 +44,7 @@ def test_audio_Artist_attr(artist): assert artist.title == "Broke For Free" assert artist.titleSort == "Broke For Free" assert artist.type == "artist" + assert artist.ultraBlurColors is None assert utils.is_datetime(artist.updatedAt) assert utils.is_int(artist.viewCount, gte=0) @@ -185,6 +186,7 @@ def test_audio_Album_attrs(album): assert album.title == "Layers" assert album.titleSort == "Layers" assert album.type == "album" + assert album.ultraBlurColors is not None assert utils.is_datetime(album.updatedAt) assert utils.is_int(album.viewCount, gte=0) assert album.year in (2012,) diff --git a/tests/test_collection.py b/tests/test_collection.py index 6226a5fa..8134d93e 100644 --- a/tests/test_collection.py +++ b/tests/test_collection.py @@ -40,6 +40,7 @@ def test_Collection_attrs(collection): assert collection.title == "Test Collection" assert collection.titleSort == collection.title assert collection.type == "collection" + assert utils.is_composite(collection.thumb, prefix="/library/collections") and collection.ultraBlurColors is None assert utils.is_datetime(collection.updatedAt) assert collection.listType == "video" assert collection.metadataType == collection.subtype diff --git a/tests/test_video.py b/tests/test_video.py index fe00a115..963ac273 100644 --- a/tests/test_video.py +++ b/tests/test_video.py @@ -102,6 +102,7 @@ def test_video_Movie_attrs(movies): assert movie.title == "Sita Sings the Blues" assert movie.titleSort == "Sita Sings the Blues" assert movie.type == "movie" + assert movie.ultraBlurColors is not None assert movie.updatedAt > datetime(2017, 1, 1) assert movie.useOriginalTitle == -1 assert movie.userRating is None @@ -669,6 +670,14 @@ def test_video_Movie_batchEdits(movie): movie.saveEdits() +def test_video_Movie_ultraBlurColors(movie): + ultraBlurColors = movie.ultraBlurColors + assert ultraBlurColors.bottomLeft + assert ultraBlurColors.bottomRight + assert ultraBlurColors.topLeft + assert ultraBlurColors.topRight + + def test_video_Movie_mixins_edit_advanced_settings(movie): test_mixins.edit_advanced_settings(movie) @@ -817,6 +826,7 @@ def test_video_Show_attrs(show): assert show.title == "Game of Thrones" assert show.titleSort == "Game of Thrones" assert show.type == "show" + assert show.ultraBlurColors is not None assert show.useOriginalTitle == -1 assert show.userRating is None assert utils.is_datetime(show.updatedAt) @@ -1044,6 +1054,7 @@ def test_video_Season_attrs(show): assert season.title == "Season 1" assert season.titleSort == "Season 1" assert season.type == "season" + assert season.ultraBlurColors is not None assert utils.is_datetime(season.updatedAt) assert utils.is_int(season.viewCount, gte=0) assert utils.is_int(season.viewedLeafCount, gte=0) @@ -1247,6 +1258,7 @@ def test_video_Episode_attrs(episode): assert episode.title == "Winter Is Coming" assert episode.titleSort == "Winter Is Coming" assert episode.type == "episode" + assert episode.ultraBlurColors is not None assert utils.is_datetime(episode.updatedAt) assert episode.userRating is None assert utils.is_int(episode.viewCount, gte=0)