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 new collection attributes #729

Merged
merged 5 commits into from
May 10, 2021
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
4 changes: 3 additions & 1 deletion plexapi/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,13 +328,14 @@ def _defaultSyncTitle(self):


@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).
Expand Down Expand Up @@ -364,6 +365,7 @@ def _loadData(self, data):
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')
Expand Down
14 changes: 11 additions & 3 deletions plexapi/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


@utils.registerPlexObject
class Collections(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
class Collection(PlexPartialObject, ArtMixin, PosterMixin, LabelMixin):
""" Represents a single Collection.

Attributes:
Expand All @@ -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).
Expand All @@ -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>).
Expand All @@ -52,7 +56,9 @@ def _loadData(self, data):
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')
Expand All @@ -64,7 +70,9 @@ def _loadData(self, data):
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')
Expand Down Expand Up @@ -119,7 +127,7 @@ def modeUpdate(self, mode=None):
showItems (Show this Collection and its Items)
Example:

collection = 'plexapi.library.Collections'
collection = 'plexapi.collection.Collection'
collection.updateMode(mode="hide")
"""
mode_dict = {'default': -1,
Expand All @@ -142,7 +150,7 @@ def sortUpdate(self, sort=None):

Example:

colleciton = 'plexapi.library.Collections'
colleciton = 'plexapi.collection.Collection'
collection.updateSort(mode="alpha")
"""
sort_dict = {'release': 0,
Expand Down
9 changes: 6 additions & 3 deletions plexapi/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,12 +585,13 @@ def download(self, savepath=None, keep_original_name=False, **kwargs):


@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>).
Expand All @@ -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
Expand Down Expand Up @@ -713,8 +715,7 @@ def _defaultSyncTitle(self):


@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:
Expand All @@ -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.
Expand Down Expand Up @@ -765,6 +767,7 @@ def _loadData(self, data):
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'))
Expand Down
1 change: 1 addition & 0 deletions tests/test_audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
4 changes: 4 additions & 0 deletions tests/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -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://")
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions tests/test_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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]
Expand Down