Skip to content

Commit

Permalink
Merge pull request #760 from JonnyWong16/bugfix/cleanup_findItems
Browse files Browse the repository at this point in the history
Cleanup usage of base PlexObject methods
  • Loading branch information
JonnyWong16 authored Jun 6, 2021
2 parents f90698f + 6448837 commit 90c1e46
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 217 deletions.
8 changes: 2 additions & 6 deletions plexapi/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,7 @@ def __iter__(self):
def hubs(self):
""" Returns a list of :class:`~plexapi.library.Hub` objects. """
data = self._server.query(self._details_key)
directory = data.find('Directory')
if directory:
related = directory.find('Related')
if related:
return self.findItems(related, library.Hub)
return self.findItems(data, library.Hub, rtag='Related')

def album(self, title):
""" Returns the :class:`~plexapi.audio.Album` that matches the specified title.
Expand Down Expand Up @@ -406,7 +402,7 @@ def locations(self):
""" This does not exist in plex xml response but is added to have a common
interface to get the locations of the track.
Retruns:
Returns:
List<str> of file paths where the track is found on disk.
"""
return [part.file for part in self.iterParts() if part]
Expand Down
12 changes: 7 additions & 5 deletions plexapi/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from plexapi import log, utils
from plexapi.exceptions import BadRequest, NotFound, UnknownType, Unsupported
from plexapi.utils import tag_plural, tag_helper

DONT_RELOAD_FOR_KEYS = {'key', 'session'}
DONT_OVERWRITE_SESSION_KEYS = {'usernames', 'players', 'transcodeSessions', 'session'}
Expand Down Expand Up @@ -263,7 +262,7 @@ def fetchItems(self, ekey, cls=None, container_start=None, container_size=None,
item.librarySectionID = librarySectionID
return items

def findItems(self, data, cls=None, initpath=None, **kwargs):
def findItems(self, data, cls=None, initpath=None, rtag=None, **kwargs):
""" Load the specified data to find and build all items with the specified tag
and attrs. See :func:`~plexapi.base.PlexObject.fetchItem` for more details
on how this is used.
Expand All @@ -273,6 +272,9 @@ def findItems(self, data, cls=None, initpath=None, **kwargs):
kwargs['etag'] = cls.TAG
if cls and cls.TYPE and 'type' not in kwargs:
kwargs['type'] = cls.TYPE
# rtag to iter on a specific root tag
if rtag:
data = next(data.iter(rtag), [])
# loop through all data elements to find matches
items = []
for elem in data:
Expand Down Expand Up @@ -478,7 +480,7 @@ def analyze(self):
self._server.query(key, method=self._server._session.put)

def isFullObject(self):
""" Retruns True if this is already a full object. A full object means all attributes
""" Returns True if this is already a full object. A full object means all attributes
were populated from the api path representing only this item. For example, the
search result for a movie often only contain a portion of the attributes a full
object (main url) for that movie would contain.
Expand Down Expand Up @@ -521,9 +523,9 @@ def _edit_tags(self, tag, items, locked=True, remove=False):
"""
if not isinstance(items, list):
items = [items]
value = getattr(self, tag_plural(tag))
value = getattr(self, utils.tag_plural(tag))
existing_tags = [t.tag for t in value if t and remove is False]
tag_edits = tag_helper(tag, existing_tags + items, locked, remove)
tag_edits = utils.tag_helper(tag, existing_tags + items, locked, remove)
self.edit(**tag_edits)

def refresh(self):
Expand Down
10 changes: 3 additions & 7 deletions plexapi/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,17 +603,13 @@ def _loadFilters(self):

key = _key % (self.key, 'all')
data = self._server.query(key)
meta = data.find('Meta')
if meta:
self._filterTypes = self.findItems(meta, FilteringType)
self._fieldTypes = self.findItems(meta, FilteringFieldType)
self._filterTypes = self.findItems(data, FilteringType, rtag='Meta')
self._fieldTypes = self.findItems(data, FilteringFieldType, rtag='Meta')

if self.TYPE != 'photo': # No collections for photo library
key = _key % (self.key, 'collections')
data = self._server.query(key)
meta = data.find('Meta')
if meta:
self._filterTypes.extend(self.findItems(meta, FilteringType))
self._filterTypes.extend(self.findItems(data, FilteringType, rtag='Meta'))

def filterTypes(self):
""" Returns a list of available :class:`~plexapi.library.FilteringType` for this library section. """
Expand Down
181 changes: 90 additions & 91 deletions plexapi/media.py

Large diffs are not rendered by default.

9 changes: 1 addition & 8 deletions plexapi/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,8 @@ class AdvancedSettingsMixin(object):

def preferences(self):
""" Returns a list of :class:`~plexapi.settings.Preferences` objects. """
items = []
data = self._server.query(self._details_key)
for item in data.iter('Preferences'):
for elem in item:
setting = settings.Preferences(data=elem, server=self._server)
setting._initpath = self.key
items.append(setting)

return items
return self.findItems(data, settings.Preferences, rtag='Preferences')

def preference(self, pref):
""" Returns a :class:`~plexapi.settings.Preferences` object for the specified pref.
Expand Down
29 changes: 7 additions & 22 deletions plexapi/myplex.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from plexapi.server import PlexServer
from plexapi.sonos import PlexSonosClient
from plexapi.sync import SyncItem, SyncList
from plexapi.utils import joinArgs
from requests.status_codes import _codes as codes


Expand Down Expand Up @@ -128,26 +127,18 @@ def _loadData(self, data):
self.title = data.attrib.get('title')
self.username = data.attrib.get('username')
self.uuid = data.attrib.get('uuid')
subscription = data.find('subscription')

subscription = data.find('subscription')
self.subscriptionActive = utils.cast(bool, subscription.attrib.get('active'))
self.subscriptionStatus = subscription.attrib.get('status')
self.subscriptionPlan = subscription.attrib.get('plan')

self.subscriptionFeatures = []
for feature in subscription.iter('feature'):
self.subscriptionFeatures.append(feature.attrib.get('id'))
self.subscriptionFeatures = self.listAttrs(subscription, 'id', etag='feature')

roles = data.find('roles')
self.roles = []
if roles is not None:
for role in roles.iter('role'):
self.roles.append(role.attrib.get('id'))
self.roles = self.listAttrs(roles, 'id', etag='role')

entitlements = data.find('entitlements')
self.entitlements = []
for entitlement in entitlements.iter('entitlement'):
self.entitlements.append(entitlement.attrib.get('id'))
self.entitlements = self.listAttrs(entitlements, 'id', etag='entitlement')

# TODO: Fetch missing MyPlexAccount attributes
self.profile_settings = None
Expand Down Expand Up @@ -460,7 +451,7 @@ def updateFriend(self, user, server, sections=None, removeSections=False, allowS
if isinstance(allowChannels, dict):
params['filterMusic'] = self._filterDictToStr(filterMusic or {})
if params:
url += joinArgs(params)
url += utils.joinArgs(params)
response_filters = self.query(url, self._session.put)
return response_servers, response_filters

Expand Down Expand Up @@ -885,13 +876,7 @@ def sections(self):
"""
url = MyPlexAccount.FRIENDSERVERS.format(machineId=self.machineIdentifier, serverId=self.id)
data = self._server.query(url)
sections = []

for section in data.iter('Section'):
if ElementTree.iselement(section):
sections.append(Section(self, section, url))

return sections
return self.findItems(data, Section, rtag='SharedServer')

def history(self, maxresults=9999999, mindate=None):
""" Get all Play History for a user in this shared server.
Expand Down Expand Up @@ -1076,7 +1061,7 @@ def _loadData(self, data):
self.screenDensity = data.attrib.get('screenDensity')
self.createdAt = utils.toDatetime(data.attrib.get('createdAt'))
self.lastSeenAt = utils.toDatetime(data.attrib.get('lastSeenAt'))
self.connections = [connection.attrib.get('uri') for connection in data.iter('Connection')]
self.connections = self.listAttrs(data, 'uri', etag='Connection')

def connect(self, timeout=None):
""" Returns a new :class:`~plexapi.client.PlexClient` or :class:`~plexapi.server.PlexServer`
Expand Down
2 changes: 1 addition & 1 deletion plexapi/photo.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def locations(self):
""" This does not exist in plex xml response but is added to have a common
interface to get the locations of the photo.
Retruns:
Returns:
List<str> of file paths where the photo is found on disk.
"""
return [part.file for item in self.media for part in item.parts if part]
Expand Down
18 changes: 9 additions & 9 deletions plexapi/playlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from plexapi.library import LibrarySection
from plexapi.mixins import ArtMixin, PosterMixin
from plexapi.playqueue import PlayQueue
from plexapi.utils import cast, deprecated, toDatetime
from plexapi.utils import deprecated


@utils.registerPlexObject
Expand Down Expand Up @@ -42,23 +42,23 @@ class Playlist(PlexPartialObject, Playable, ArtMixin, PosterMixin):
def _loadData(self, data):
""" Load attribute values from Plex XML response. """
Playable._loadData(self, data)
self.addedAt = toDatetime(data.attrib.get('addedAt'))
self.allowSync = cast(bool, data.attrib.get('allowSync'))
self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
self.allowSync = utils.cast(bool, data.attrib.get('allowSync'))
self.composite = data.attrib.get('composite') # url to thumbnail
self.content = data.attrib.get('content')
self.duration = cast(int, data.attrib.get('duration'))
self.durationInSeconds = cast(int, data.attrib.get('durationInSeconds'))
self.duration = utils.cast(int, data.attrib.get('duration'))
self.durationInSeconds = utils.cast(int, data.attrib.get('durationInSeconds'))
self.icon = data.attrib.get('icon')
self.guid = data.attrib.get('guid')
self.key = data.attrib.get('key', '').replace('/items', '') # FIX_BUG_50
self.leafCount = cast(int, data.attrib.get('leafCount'))
self.leafCount = utils.cast(int, data.attrib.get('leafCount'))
self.playlistType = data.attrib.get('playlistType')
self.ratingKey = cast(int, data.attrib.get('ratingKey'))
self.smart = cast(bool, data.attrib.get('smart'))
self.ratingKey = utils.cast(int, data.attrib.get('ratingKey'))
self.smart = utils.cast(bool, data.attrib.get('smart'))
self.summary = data.attrib.get('summary')
self.title = data.attrib.get('title')
self.type = data.attrib.get('type')
self.updatedAt = toDatetime(data.attrib.get('updatedAt'))
self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))
self._items = None # cache for self.items
self._section = None # cache for self.section

Expand Down
Loading

0 comments on commit 90c1e46

Please sign in to comment.