Merge pull request #729 from JonnyWong16/feature/smart_collections

Add new collection attributes
This commit is contained in:
JonnyWong16 2021-05-09 19:44:27 -07:00 committed by GitHub
commit ecd9309383
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 32 additions and 8 deletions

View file

@ -328,13 +328,14 @@ class Album(Audio, ArtMixin, PosterMixin, UnmatchMatchMixin,
@utils.registerPlexObject
class Track(Audio, Playable, ArtUrlMixin, PosterUrlMixin, MoodMixin):
class Track(Audio, Playable, ArtUrlMixin, PosterUrlMixin, CollectionMixin, MoodMixin):
""" Represents a single Track.
Attributes:
TAG (str): 'Directory'
TYPE (str): 'track'
chapterSource (str): Unknown
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
duration (int): Length of the track in milliseconds.
grandparentArt (str): URL to album artist artwork (/library/metadata/<grandparentRatingKey>/art/<artid>).
grandparentGuid (str): Plex GUID for the album artist (plex://artist/5d07bcb0403c64029053ac4c).
@ -364,6 +365,7 @@ class Track(Audio, Playable, ArtUrlMixin, PosterUrlMixin, MoodMixin):
Audio._loadData(self, data)
Playable._loadData(self, data)
self.chapterSource = data.attrib.get('chapterSource')
self.collections = self.findItems(data, media.Collection)
self.duration = utils.cast(int, data.attrib.get('duration'))
self.grandparentArt = data.attrib.get('grandparentArt')
self.grandparentGuid = data.attrib.get('grandparentGuid')

View file

@ -9,7 +9,7 @@ from plexapi.utils import deprecated
@utils.registerPlexObject
class Collections(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
class Collection(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
""" Represents a single Collection.
Attributes:
@ -20,7 +20,9 @@ class Collections(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
artBlurHash (str): BlurHash string for artwork image.
childCount (int): Number of items in the collection.
collectionMode (str): How the items in the collection are displayed.
collectionPublished (bool): True if the collection is published to the Plex homepage.
collectionSort (str): How to sort the items in the collection.
content (str): The filter URI string for smart collections.
contentRating (str) Content rating (PG-13; NR; TV-G).
fields (List<:class:`~plexapi.media.Field`>): List of field objects.
guid (str): Plex GUID for the collection (collection://XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX).
@ -32,7 +34,9 @@ class Collections(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
librarySectionTitle (str): :class:`~plexapi.library.LibrarySection` title.
maxYear (int): Maximum year for the items in the collection.
minYear (int): Minimum year for the items in the collection.
ratingCount (int): The number of ratings.
ratingKey (int): Unique key identifying the collection.
smart (bool): True if the collection is a smart collection.
subtype (str): Media type of the items in the collection (movie, show, artist, or album).
summary (str): Summary of the collection.
thumb (str): URL to thumbnail image (/library/metadata/<ratingKey>/thumb/<thumbid>).
@ -52,7 +56,9 @@ class Collections(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
self.artBlurHash = data.attrib.get('artBlurHash')
self.childCount = utils.cast(int, data.attrib.get('childCount'))
self.collectionMode = utils.cast(int, data.attrib.get('collectionMode', '-1'))
self.collectionPublished = utils.cast(bool, data.attrib.get('collectionPublished', '0'))
self.collectionSort = utils.cast(int, data.attrib.get('collectionSort', '0'))
self.content = data.attrib.get('content')
self.contentRating = data.attrib.get('contentRating')
self.fields = self.findItems(data, media.Field)
self.guid = data.attrib.get('guid')
@ -64,7 +70,9 @@ class Collections(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
self.librarySectionTitle = data.attrib.get('librarySectionTitle')
self.maxYear = utils.cast(int, data.attrib.get('maxYear'))
self.minYear = utils.cast(int, data.attrib.get('minYear'))
self.ratingCount = utils.cast(int, data.attrib.get('ratingCount'))
self.ratingKey = utils.cast(int, data.attrib.get('ratingKey'))
self.smart = utils.cast(bool, data.attrib.get('smart', '0'))
self.subtype = data.attrib.get('subtype')
self.summary = data.attrib.get('summary')
self.thumb = data.attrib.get('thumb')
@ -119,7 +127,7 @@ class Collections(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
showItems (Show this Collection and its Items)
Example:
collection = 'plexapi.library.Collections'
collection = 'plexapi.collection.Collection'
collection.updateMode(mode="hide")
"""
mode_dict = {'default': -1,
@ -142,7 +150,7 @@ class Collections(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
Example:
colleciton = 'plexapi.library.Collections'
colleciton = 'plexapi.collection.Collection'
collection.updateSort(mode="alpha")
"""
sort_dict = {'release': 0,

View file

@ -585,12 +585,13 @@ class Show(Video, AdvancedSettingsMixin, ArtMixin, BannerMixin, PosterMixin, Spl
@utils.registerPlexObject
class Season(Video, ArtMixin, PosterMixin):
class Season(Video, ArtMixin, PosterMixin, CollectionMixin):
""" Represents a single Show Season (including all episodes).
Attributes:
TAG (str): 'Directory'
TYPE (str): 'season'
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
guids (List<:class:`~plexapi.media.Guid`>): List of guid objects.
index (int): Season number.
key (str): API URL (/library/metadata/<ratingkey>).
@ -611,6 +612,7 @@ class Season(Video, ArtMixin, PosterMixin):
def _loadData(self, data):
""" Load attribute values from Plex XML response. """
Video._loadData(self, data)
self.collections = self.findItems(data, media.Collection)
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
@ -713,8 +715,7 @@ class Season(Video, ArtMixin, PosterMixin):
@utils.registerPlexObject
class Episode(Video, Playable, ArtMixin, PosterMixin,
DirectorMixin, WriterMixin):
class Episode(Video, Playable, ArtMixin, PosterMixin, CollectionMixin, DirectorMixin, WriterMixin):
""" Represents a single Shows Episode.
Attributes:
@ -724,6 +725,7 @@ class Episode(Video, Playable, ArtMixin, PosterMixin,
audienceRatingImage (str): Key to audience rating image (tmdb://image.rating).
chapters (List<:class:`~plexapi.media.Chapter`>): List of Chapter objects.
chapterSource (str): Chapter source (agent; media; mixed).
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
contentRating (str) Content rating (PG-13; NR; TV-G).
directors (List<:class:`~plexapi.media.Director`>): List of director objects.
duration (int): Duration of the episode in milliseconds.
@ -765,6 +767,7 @@ class Episode(Video, Playable, ArtMixin, PosterMixin,
self.audienceRatingImage = data.attrib.get('audienceRatingImage')
self.chapters = self.findItems(data, media.Chapter)
self.chapterSource = data.attrib.get('chapterSource')
self.collections = self.findItems(data, media.Collection)
self.contentRating = data.attrib.get('contentRating')
self.directors = self.findItems(data, media.Director)
self.duration = utils.cast(int, data.attrib.get('duration'))

View file

@ -290,6 +290,7 @@ def test_audio_Track_mixins_images(track):
def test_audio_Track_mixins_tags(track):
test_mixins.edit_collection(track)
test_mixins.edit_mood(track)

View file

@ -12,7 +12,9 @@ def test_Collection_attrs(collection):
assert collection.artBlurHash is None
assert collection.childCount == 1
assert collection.collectionMode == -1
assert collection.collectionPublished is False
assert collection.collectionSort == 0
assert collection.content is None
assert collection.contentRating
assert not collection.fields
assert collection.guid.startswith("collection://")
@ -24,7 +26,9 @@ def test_Collection_attrs(collection):
assert collection.librarySectionTitle == "Movies"
assert utils.is_int(collection.maxYear)
assert utils.is_int(collection.minYear)
assert utils.is_int(collection.ratingCount)
assert utils.is_int(collection.ratingKey)
assert collection.smart is False
assert collection.subtype == "movie"
assert collection.summary == ""
assert collection.thumb.startswith("/library/collections/%s/composite" % collection.ratingKey)

View file

@ -395,7 +395,7 @@ def test_server_system_devices(plex):
devices = plex.systemDevices()
assert len(devices)
device = devices[-1]
assert device.clientIdentifier or device.clientIdentifier is None
assert device.clientIdentifier or device.clientIdentifier == ""
assert utils.is_datetime(device.createdAt)
assert utils.is_int(device.id)
assert len(device.key)

View file

@ -876,6 +876,7 @@ def test_video_Episode_mixins_images(episode):
def test_video_Episode_mixins_tags(episode):
test_mixins.edit_collection(episode)
test_mixins.edit_director(episode)
test_mixins.edit_writer(episode)
@ -992,6 +993,11 @@ def test_video_Season_mixins_images(show):
test_mixins.attr_posterUrl(season)
def test_video_Season_mixins_tags(show):
season = show.season(season=1)
test_mixins.edit_collection(season)
def test_that_reload_return_the_same_object(plex):
# we want to check this that all the urls are correct
movie_library_search = plex.library.section("Movies").search("Elephants Dream")[0]