Skip to content

Commit 90bfaf1

Browse files
authored
Merge pull request #832 from JonnyWong16/feature/album_types
Add album formats and subformats
2 parents a3178f3 + bf3f0c1 commit 90bfaf1

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed

plexapi/audio.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ class Album(Audio, ArtMixin, PosterMixin, RatingMixin, UnmatchMatchMixin,
234234
TAG (str): 'Directory'
235235
TYPE (str): 'album'
236236
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
237+
formats (List<:class:`~plexapi.media.Format`>): List of format objects.
237238
genres (List<:class:`~plexapi.media.Genre`>): List of genre objects.
238239
key (str): API URL (/library/metadata/<ratingkey>).
239240
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
@@ -248,6 +249,7 @@ class Album(Audio, ArtMixin, PosterMixin, RatingMixin, UnmatchMatchMixin,
248249
rating (float): Album rating (7.9; 9.8; 8.1).
249250
studio (str): Studio that released the album.
250251
styles (List<:class:`~plexapi.media.Style`>): List of style objects.
252+
subformats (List<:class:`~plexapi.media.Subformat`>): List of subformat objects.
251253
viewedLeafCount (int): Number of items marked as played in the album view.
252254
year (int): Year the album was released.
253255
"""
@@ -258,6 +260,7 @@ def _loadData(self, data):
258260
""" Load attribute values from Plex XML response. """
259261
Audio._loadData(self, data)
260262
self.collections = self.findItems(data, media.Collection)
263+
self.formats = self.findItems(data, media.Format)
261264
self.genres = self.findItems(data, media.Genre)
262265
self.key = self.key.replace('/children', '') # FIX_BUG_50
263266
self.labels = self.findItems(data, media.Label)
@@ -272,6 +275,7 @@ def _loadData(self, data):
272275
self.rating = utils.cast(float, data.attrib.get('rating'))
273276
self.studio = data.attrib.get('studio')
274277
self.styles = self.findItems(data, media.Style)
278+
self.subformats = self.findItems(data, media.Subformat)
275279
self.viewedLeafCount = utils.cast(int, data.attrib.get('viewedLeafCount'))
276280
self.year = utils.cast(int, data.attrib.get('year'))
277281

plexapi/media.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ def subtitleStreams(self):
174174
return [stream for stream in self.streams if isinstance(stream, SubtitleStream)]
175175

176176
def lyricStreams(self):
177-
""" Returns a list of :class:`~plexapi.media.SubtitleStream` objects in this MediaPart. """
177+
""" Returns a list of :class:`~plexapi.media.LyricStream` objects in this MediaPart. """
178178
return [stream for stream in self.streams if isinstance(stream, LyricStream)]
179179

180180
def setDefaultAudioStream(self, stream):
@@ -731,6 +731,18 @@ class Director(MediaTag):
731731
FILTER = 'director'
732732

733733

734+
@utils.registerPlexObject
735+
class Format(MediaTag):
736+
""" Represents a single Format media tag.
737+
738+
Attributes:
739+
TAG (str): 'Format'
740+
FILTER (str): 'format'
741+
"""
742+
TAG = 'Format'
743+
FILTER = 'format'
744+
745+
734746
@utils.registerPlexObject
735747
class Genre(MediaTag):
736748
""" Represents a single Genre media tag.
@@ -815,6 +827,18 @@ class Style(MediaTag):
815827
FILTER = 'style'
816828

817829

830+
@utils.registerPlexObject
831+
class Subformat(MediaTag):
832+
""" Represents a single Subformat media tag.
833+
834+
Attributes:
835+
TAG (str): 'Subformat'
836+
FILTER (str): 'subformat'
837+
"""
838+
TAG = 'Subformat'
839+
FILTER = 'subformat'
840+
841+
818842
@utils.registerPlexObject
819843
class Tag(MediaTag):
820844
""" Represents a single Tag media tag.

tests/test_audio.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# -*- coding: utf-8 -*-
22
from urllib.parse import quote_plus
33

4+
import pytest
5+
from plexapi.exceptions import BadRequest
6+
47
from . import conftest as utils
58
from . import test_media, test_mixins
69

@@ -38,9 +41,9 @@ def test_audio_Artist_attr(artist):
3841
assert utils.is_int(artist.viewCount, gte=0)
3942

4043

41-
def test_audio_Artist_get(artist, music):
42-
artist == music.searchArtists(**{"title": "Broke For Free"})[0]
43-
artist.title == "Broke For Free"
44+
def test_audio_Artist_get(artist):
45+
track = artist.get(album="Layers", title="As Colourful as Ever")
46+
assert track.title == "As Colourful as Ever"
4447

4548

4649
def test_audio_Artist_history(artist):
@@ -54,6 +57,8 @@ def test_audio_Artist_track(artist):
5457
track = artist.track(album="Layers", track=1)
5558
assert track.parentTitle == "Layers"
5659
assert track.index == 1
60+
with pytest.raises(BadRequest):
61+
artist.track()
5762

5863

5964
def test_audio_Artist_tracks(artist):
@@ -71,6 +76,11 @@ def test_audio_Artist_albums(artist):
7176
assert len(albums) == 1 and albums[0].title == "Layers"
7277

7378

79+
def test_audio_Artist_hubs(artist):
80+
hubs = artist.hubs()
81+
assert isinstance(hubs, list)
82+
83+
7484
def test_audio_Artist_mixins_edit_advanced_settings(artist):
7585
test_mixins.edit_advanced_settings(artist)
7686

@@ -119,6 +129,7 @@ def test_audio_Album_attrs(album):
119129
assert utils.is_datetime(album.addedAt)
120130
if album.art:
121131
assert utils.is_art(album.art)
132+
assert isinstance(album.formats, list)
122133
assert isinstance(album.genres, list)
123134
assert album.index == 1
124135
assert utils.is_metadata(album._initpath)
@@ -136,6 +147,7 @@ def test_audio_Album_attrs(album):
136147
assert album.ratingKey >= 1
137148
assert album._server._baseurl == utils.SERVER_BASEURL
138149
assert album.studio == "[no label]"
150+
assert isinstance(album.subformats, list)
139151
assert album.summary == ""
140152
if album.thumb:
141153
assert utils.is_thumb(album.thumb)
@@ -167,6 +179,8 @@ def test_audio_Album_track(album, track=None):
167179
track = track or album.track("As Colourful As Ever")
168180
track2 = album.track(track=1)
169181
assert track == track2
182+
with pytest.raises(BadRequest):
183+
album.track()
170184

171185

172186
def test_audio_Album_get(album):
@@ -233,6 +247,7 @@ def test_audio_Track_attrs(album):
233247
assert utils.is_thumb(track.grandparentThumb)
234248
assert track.grandparentTitle == "Broke For Free"
235249
assert track.guid.startswith("mbid://") or track.guid.startswith("plex://track/")
250+
assert track.hasSonicAnalysis is False
236251
assert track.index == 1
237252
assert track.trackNumber == track.index
238253
assert utils.is_metadata(track._initpath)
@@ -271,6 +286,7 @@ def test_audio_Track_attrs(album):
271286
assert track.viewOffset == 0
272287
assert track.viewedAt is None
273288
assert track.year is None
289+
assert track.url(None) is None
274290
assert media.aspectRatio is None
275291
assert media.audioChannels == 2
276292
assert media.audioCodec == "mp3"

tests/test_library.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,14 +306,18 @@ def test_library_MusicSection_albums(music):
306306
assert len(music.albums())
307307

308308

309-
def test_library_MusicSection_searchTracks(music):
310-
assert len(music.searchTracks(title="As Colourful As Ever"))
309+
def test_library_MusicSection_searchArtists(music):
310+
assert len(music.searchArtists(title="Broke for Free"))
311311

312312

313313
def test_library_MusicSection_searchAlbums(music):
314314
assert len(music.searchAlbums(title="Layers"))
315315

316316

317+
def test_library_MusicSection_searchTracks(music):
318+
assert len(music.searchTracks(title="As Colourful As Ever"))
319+
320+
317321
def test_library_MusicSection_recentlyAdded(music, artist):
318322
album = artist.albums()[0]
319323
track = album.tracks()[0]

0 commit comments

Comments
 (0)