Audio tests passing

This commit is contained in:
Michael Shepanski 2017-02-08 00:36:22 -05:00
parent 82bd1753e2
commit e3abfeeb0f
7 changed files with 44 additions and 42 deletions

View file

@ -32,7 +32,7 @@ BASE_HEADERS = reset_base_headers()
log = logging.getLogger('plexapi')
logfile = CONFIG.get('logging.path')
logformat = CONFIG.get('logging.format', '%(asctime)s %(module)12s:%(lineno)-4s %(levelname)-9s %(message)s')
loglevel = CONFIG.get('logging.level', 'INFO')
loglevel = CONFIG.get('logging.level', 'INFO').upper()
loghandler = logging.NullHandler()
if logfile:
logbackups = CONFIG.get('logging.backup_count', 3, int)

View file

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
from plexapi import media, utils
from plexapi.base import Playable, PlexPartialObject
from plexapi.exceptions import NotFound
class Audio(PlexPartialObject):
@ -91,9 +90,9 @@ class Artist(Audio):
self.guid = data.attrib.get('guid')
self.key = self.key.replace('/children', '') # FIX_BUG_50
self.location = utils.findLocations(data, single=True)
self.countries = self._buildItems(data, media.Country)
self.genres = self._buildItems(data, media.Genre)
self.similar = self._buildItems(data, media.Similar)
self.countries = self._buildItems(data, media.Country, bytag=True)
self.genres = self._buildItems(data, media.Genre, bytag=True)
self.similar = self._buildItems(data, media.Similar, bytag=True)
def album(self, title):
""" Returns the :class:`~plexapi.audio.Album` that matches the specified title.
@ -101,15 +100,13 @@ class Artist(Audio):
Parameters:
title (str): Title of the album to return.
"""
for album in self.albums():
if album.title.lower() == title.lower():
return album
raise NotFound('Unable to find album %s' % title)
key = '%s/children' % self.key
return self.fetchItem(key, title=title)
def albums(self):
""" Returns a list of :class:`~plexapi.audio.Album` objects by this artist. """
key = '%s/children' % self.key
return self.fetchItems(key, tag=Album.TYPE)
return self.fetchItems(key)
def track(self, title):
""" Returns the :class:`~plexapi.audio.Track` that matches the specified title.
@ -117,10 +114,8 @@ class Artist(Audio):
Parameters:
title (str): Title of the track to return.
"""
for track in self.tracks():
if track.title.lower() == title.lower():
return track
raise NotFound('Unable to find track %s' % title)
key = '%s/allLeaves' % self.key
return self.fetchItem(key, title=title)
def tracks(self):
""" Returns a list of :class:`~plexapi.audio.Track` objects by this artist. """
@ -186,7 +181,7 @@ class Album(Audio):
self.parentTitle = data.attrib.get('parentTitle')
self.studio = data.attrib.get('studio')
self.year = utils.cast(int, data.attrib.get('year'))
self.genres = self._buildItems(data, media.Genre)
self.genres = self._buildItems(data, media.Genre, bytag=True)
def track(self, title):
""" Returns the :class:`~plexapi.audio.Track` that matches the specified title.
@ -194,10 +189,8 @@ class Album(Audio):
Parameters:
title (str): Title of the track to return.
"""
for track in self.tracks():
if track.title.lower() == title.lower():
return track
raise NotFound('Unable to find track %s' % title)
key = '%s/children' % self.key
return self.fetchItem(key, title=title)
def tracks(self):
""" Returns a list of :class:`~plexapi.audio.Track` objects in this album. """
@ -293,8 +286,8 @@ class Track(Audio, Playable):
self.ratingCount = utils.cast(int, data.attrib.get('ratingCount'))
self.viewOffset = utils.cast(int, data.attrib.get('viewOffset', 0))
self.year = utils.cast(int, data.attrib.get('year'))
self.media = self._buildItems(data, media.Media)
self.moods = self._buildItems(data, media.Mood)
self.media = self._buildItems(data, media.Media, bytag=True)
self.moods = self._buildItems(data, media.Mood, bytag=True)
# data for active sessions and history
self.sessionKey = utils.cast(int, data.attrib.get('sessionKey'))
self.username = utils.findUsername(data)

View file

@ -25,7 +25,7 @@ class PlexObject(object):
] if p])
def __setattr__(self, attr, value):
if value is not None or attr.startswith('_'):
if value is not None or attr.startswith('_') or attr not in self.__dict__:
self.__dict__[attr] = value
def __firstattr(self, *attrs):
@ -37,10 +37,11 @@ class PlexObject(object):
def _buildItem(self, elem, cls=None, initpath=None, bytag=False):
""" Factory function to build objects based on registered LIBRARY_TYPES. """
initpath = initpath or self._initpath
if cls: return cls(self._root, elem, initpath)
libtype = elem.tag if bytag else elem.attrib.get('type')
if libtype == 'photo' and elem.tag == 'Directory':
libtype = 'photoalbum'
if cls and libtype == cls.TYPE:
return cls(self._root, elem, initpath)
if libtype in utils.LIBRARY_TYPES:
cls = utils.LIBRARY_TYPES[libtype]
return cls(self._root, elem, initpath)
@ -123,8 +124,9 @@ class PlexPartialObject(PlexObject):
return other is not None and self.key == other.key
def __getattribute__(self, attr):
# Dragons inside.. :-/
value = utils.getattributeOrNone(PlexPartialObject, self, attr)
# Check a few cases where we dont want to reload
value = super(PlexPartialObject, self).__getattribute__(attr)
if attr == 'key' or attr.startswith('_'): return value
if value not in (None, []): return value
if self.isFullObject(): return value
@ -135,7 +137,7 @@ class PlexPartialObject(PlexObject):
log.warn("Reloading %s for attr '%s'" % (objname, attr))
# Reload and return the value
self.reload()
return super(PlexPartialObject, self).__getattribute__(attr)
return utils.getattributeOrNone(PlexPartialObject, self, attr)
def isFullObject(self):
""" Retruns True if this is already a full object. A full object means all attributes
@ -246,9 +248,9 @@ class Playable(object):
if kwargs:
download_url = self.getStreamURL(**kwargs)
else:
download_url = self._root.url('%s?download=1' % location.key)
download_url = self._root._url('%s?download=1' % location.key)
filepath = utils.download(download_url, filename=filename,
savepath=savepath, session=self._root.session)
savepath=savepath, session=self._root._session)
if filepath:
filepaths.append(filepath)
return filepaths

View file

@ -52,7 +52,7 @@ class Media(PlexObject):
self.videoFrameRate = data.attrib.get('videoFrameRate')
self.videoResolution = data.attrib.get('videoResolution')
self.width = cast(int, data.attrib.get('width'))
self.parts = self._buildItems(data, MediaPart)
self.parts = self._buildItems(data, MediaPart, bytag=True)
class MediaPart(PlexObject):

View file

@ -135,6 +135,13 @@ def findUsername(data):
return None
def getattributeOrNone(obj, self, attr):
try:
return super(obj, self).__getattribute__(attr)
except AttributeError:
return None
def isInt(str):
""" Returns True if the specified string passes as an int. """
try:

View file

@ -93,14 +93,14 @@ class Movie(Video, Playable):
self.viewOffset = utils.cast(int, data.attrib.get('viewOffset', 0))
self.year = utils.cast(int, data.attrib.get('year'))
self.collections = self._buildItems(data, media.Collection)
self.countries = self._buildItems(data, media.Country)
self.directors = self._buildItems(data, media.Director)
self.fields = self._buildItems(data, media.Field)
self.genres = self._buildItems(data, media.Genre)
self.media = self._buildItems(data, media.Media)
self.producers = self._buildItems(data, media.Producer)
self.roles = self._buildItems(data, media.Role)
self.writers = self._buildItems(data, media.Writer)
self.countries = self._buildItems(data, media.Country, bytag=True)
self.directors = self._buildItems(data, media.Director, bytag=True)
self.fields = self._buildItems(data, media.Field, bytag=True)
self.genres = self._buildItems(data, media.Genre, bytag=True)
self.media = self._buildItems(data, media.Media, bytag=True)
self.producers = self._buildItems(data, media.Producer, bytag=True)
self.roles = self._buildItems(data, media.Role, bytag=True)
self.writers = self._buildItems(data, media.Writer, bytag=True)
@property
def actors(self):
@ -164,8 +164,8 @@ class Show(Video):
self.theme = data.attrib.get('theme')
self.viewedLeafCount = utils.cast(int, data.attrib.get('viewedLeafCount'))
self.year = utils.cast(int, data.attrib.get('year'))
self.genres = self._buildItems(data, media.Genre)
self.roles = self._buildItems(data, media.Role)
self.genres = self._buildItems(data, media.Genre, bytag=True)
self.roles = self._buildItems(data, media.Role, bytag=True)
@property
def actors(self):
@ -393,9 +393,9 @@ class Episode(Video, Playable):
self.rating = utils.cast(float, data.attrib.get('rating'))
self.viewOffset = utils.cast(int, data.attrib.get('viewOffset', 0))
self.year = utils.cast(int, data.attrib.get('year'))
self.directors = self._buildItems(data, media.Director)
self.media = self._buildItems(data, media.Media)
self.writers = self._buildItems(data, media.Writer)
self.directors = self._buildItems(data, media.Director, bytag=True)
self.media = self._buildItems(data, media.Media, bytag=True)
self.writers = self._buildItems(data, media.Writer, bytag=True)
# data for active sessions and history
self.sessionKey = utils.cast(int, data.attrib.get('sessionKey'))
self.username = utils.findUsername(data)

View file

@ -55,7 +55,7 @@ def test_audio_Album_attrs(a_music_album):
assert str(m.addedAt.date()) == '2017-01-17'
assert [i.tag for i in m.genres] == ['Electronic']
assert m.index == '1'
assert m._initpath == '/library/metadata/21'
assert m._initpath == '/library/metadata/20/children'
assert m.key == '/library/metadata/21'
assert m.librarySectionID == '3'
assert m.listType == 'audio'