Move _find function from PlexPartialObject to generic utility functions

This commit is contained in:
Michael Shepanski 2016-04-03 23:17:29 -04:00
parent 3889c49b30
commit e81f2506e9
7 changed files with 87 additions and 92 deletions

View file

@ -1,22 +0,0 @@
# Python-PlexAPI Change Log #
### Version 2.0.0 ###
* Added support for audio.
* Ability to compare NA value with None.
* Use a session for requests to get advantages of keepalive.
* Add tagging to tests to more easily run tests for a specific category.
* Bugfix: Level for a media object might not always be an integer.
### NAME CHANGES IN VERSION 2.0.0 (this will only ever happen on a major version increment) ###
* myplex.MyPlexResource.fetch_resources() renamed to myplex.MyPlexResource.fetchResources()
* myplex.MyPlexDevice.fetch_resources() renamed to myplex.MyPlexDevice.fetchResources()
* myplex.MyPlexResource.fetch_resources() renamed to myplex.MyPlexResource.fetchResources()
* media.VideoTag() renamed to media.MediaTag()
* media.MediaPart.select_stream() renamed to media.MediaPart.selectedStream()
* video.iter_parts() was renamed to video.iterParts()
* config.PlexConfig._as_dict() renamed to config.PlexConfig._asDict()
* build_item() renamed to buildItem() and moved to utils.py
* list_items() renamed to listItems() and moved to utils.py
* find_item() renamed to findItem() and moved to utils.py
* find_key() renamed to findKey() and moved to utils.py
* search_type() renamed to searchType() and moved to utils.py

View file

@ -33,7 +33,7 @@ class Artist(Audio):
self.art = data.attrib.get('art', NA)
self.guid = data.attrib.get('guid', NA)
self.key = self.key.replace('/children', '') # plex bug? http://bit.ly/1Sc2J3V
self.location = self._findLocation(data)
self.location = utils.findLocation(data)
if self.isFullObject():
self.countries = [media.Country(self.server, e) for e in data if e.tag == media.Country.TYPE]
self.genres = [media.Genre(self.server, e) for e in data if e.tag == media.Genre.TYPE]
@ -141,9 +141,9 @@ class Track(Audio):
self.media = [media.Media(self.server, e, self.initpath, self) for e in data if e.tag == media.Media.TYPE]
# data for active sessions
self.sessionKey = utils.cast(int, data.attrib.get('sessionKey', NA))
self.user = self._findUser(data)
self.player = self._findPlayer(data)
self.transcodeSession = self._findTranscodeSession(data)
self.user = utils.findUser(data, self.initpath)
self.player = utils.findPlayer(self.server, data)
self.transcodeSession = utils.findTranscodeSession(self.server, data)
@property
def thumbUrl(self):

View file

@ -45,7 +45,6 @@ class MyPlexUser(object):
self.subscriptionFeatures = None # renamed on server
self.roles = None
self.entitlements = None
def devices(self):
return _listItems(MyPlexDevice.DEVICES, self.authenticationToken, MyPlexDevice)

View file

@ -39,13 +39,16 @@ NA = _NA()
class PlexPartialObject(object):
def __init__(self, server, data, initpath):
self.server = server
self.server = server # TODO: This should not be needed here..
self.initpath = initpath
self._loadData(data)
# TODO: Make this work with objects that contain id instead of key (MyPlex objects)
def __eq__(self, other):
return other is not None and self.type == other.type and self.key == other.key
# TODO: This shouldn't be here, move downstream
# or make it work with MyPlex objects..
def __repr__(self):
title = self.title.replace(' ','.')[0:20]
return '<%s:%s:%s>' % (self.__class__.__name__, self.ratingKey, title.encode('utf8'))
@ -59,10 +62,12 @@ class PlexPartialObject(object):
if value != NA:
super(PlexPartialObject, self).__setattr__(attr, value)
# TODO: This shouldn't be here, move downstream
@property
def thumbUrl(self):
return self.server.url(self.thumb)
# TODO: Move to Playable()
def _getStreamURL(self, **params):
if self.TYPE not in ('movie', 'episode', 'track'):
raise Unsupported('Fetching stream URL for %s is unsupported.' % self.TYPE)
@ -82,42 +87,6 @@ class PlexPartialObject(object):
streamtype = 'audio' if self.TYPE in ('track', 'album') else 'video'
return self.server.url('/%s/:/transcode/universal/start.m3u8?%s' % (streamtype, urlencode(params)))
def _findLocation(self, data):
elem = data.find('Location')
if elem is not None:
return elem.attrib.get('path')
return None
def _findPlayer(self, data):
elem = data.find('Player')
if elem is not None:
from plexapi.client import PlexClient
return PlexClient(self.server, elem)
return None
def _findStreams(self, streamtype):
streams = []
for media in self.media:
for part in media.parts:
for stream in part.streams:
if stream.TYPE == streamtype:
streams.append(stream)
return streams
def _findTranscodeSession(self, data):
elem = data.find('TranscodeSession')
if elem is not None:
from plexapi import media
return media.TranscodeSession(self.server, elem)
return None
def _findUser(self, data):
elem = data.find('User')
if elem is not None:
from plexapi.myplex import MyPlexUser
return MyPlexUser(elem, self.initpath)
return None
def _loadData(self, data):
raise Exception('Abstract method not implemented.')
@ -127,14 +96,17 @@ class PlexPartialObject(object):
def isPartialObject(self):
return not self.isFullObject()
# TODO: Move to Playable()
def iterParts(self):
for item in self.media:
for part in item.parts:
yield part
# TODO: Move to Playable()
def play(self, client):
client.playMedia(self)
# TODO: This shouldn't be here, move downstream
def refresh(self):
self.server.query('%s/refresh' % self.key, method=put)
@ -183,6 +155,47 @@ def findItem(server, path, title):
raise NotFound('Unable to find item: %s' % title)
def findLocation(data):
elem = data.find('Location')
if elem is not None:
return elem.attrib.get('path')
return None
def findPlayer(server, data):
elem = data.find('Player')
if elem is not None:
from plexapi.client import PlexClient
return PlexClient(server, elem)
return None
def findStreams(media, streamtype):
streams = []
for mediaitem in media:
for part in mediaitem.parts:
for stream in part.streams:
if stream.TYPE == streamtype:
streams.append(stream)
return streams
def findTranscodeSession(server, data):
elem = data.find('TranscodeSession')
if elem is not None:
from plexapi import media
return media.TranscodeSession(server, elem)
return None
def findUser(data, initpath):
elem = data.find('User')
if elem is not None:
from plexapi.myplex import MyPlexUser
return MyPlexUser(elem, initpath)
return None
def isInt(string):
try:
int(string)

View file

@ -79,14 +79,14 @@ class Movie(Video):
self.producers = [media.Producer(self.server, e) for e in data if e.tag == media.Producer.TYPE]
self.roles = [media.Role(self.server, e) for e in data if e.tag == media.Role.TYPE]
self.writers = [media.Writer(self.server, e) for e in data if e.tag == media.Writer.TYPE]
self.videoStreams = self._findStreams('videostream')
self.audioStreams = self._findStreams('audiostream')
self.subtitleStreams = self._findStreams('subtitlestream')
self.videoStreams = utils.findStreams(self.media, 'videostream')
self.audioStreams = utils.findStreams(self.media, 'audiostream')
self.subtitleStreams = utils.findStreams(self.media, 'subtitlestream')
# data for active sessions
self.sessionKey = utils.cast(int, data.attrib.get('sessionKey', NA))
self.user = self._findUser(data)
self.player = self._findPlayer(data)
self.transcodeSession = self._findTranscodeSession(data)
self.user = utils.findUser(data, self.initpath)
self.player = utils.findPlayer(self.server, data)
self.transcodeSession = utils.findTranscodeSession(self.server, data)
@property
def actors(self):
@ -113,7 +113,7 @@ class Show(Video):
self.duration = utils.cast(int, data.attrib.get('duration', NA))
self.guid = data.attrib.get('guid', NA)
self.leafCount = utils.cast(int, data.attrib.get('leafCount', NA))
self.location = self._findLocation(data)
self.location = utils.findLocation(data)
self.originallyAvailableAt = utils.toDatetime(data.attrib.get('originallyAvailableAt', NA), '%Y-%m-%d')
self.rating = utils.cast(float, data.attrib.get('rating', NA))
self.studio = data.attrib.get('studio', NA)
@ -226,14 +226,14 @@ class Episode(Video):
self.directors = [media.Director(self.server, e) for e in data if e.tag == media.Director.TYPE]
self.media = [media.Media(self.server, e, self.initpath, self) for e in data if e.tag == media.Media.TYPE]
self.writers = [media.Writer(self.server, e) for e in data if e.tag == media.Writer.TYPE]
self.videoStreams = self._findStreams('videostream')
self.audioStreams = self._findStreams('audiostream')
self.subtitleStreams = self._findStreams('subtitlestream')
self.videoStreams = utils.findStreams(self.media, 'videostream')
self.audioStreams = utils.findStreams(self.media, 'audiostream')
self.subtitleStreams = utils.findStreams(self.media, 'subtitlestream')
# data for active sessions
self.sessionKey = utils.cast(int, data.attrib.get('sessionKey', NA))
self.user = self._findUser(data)
self.player = self._findPlayer(data)
self.transcodeSession = self._findTranscodeSession(data)
self.user = utils.findUser(data, self.initpath)
self.player = utils.findPlayer(self.server, data)
self.transcodeSession = utils.findTranscodeSession(self.server, data)
@property
def isWatched(self):

View file

@ -10,9 +10,8 @@ run this test suite with the following command:
import argparse, sys, time
from os.path import dirname, abspath
sys.path.append(dirname(dirname(abspath(__file__))))
from utils import log, register, run_tests
from plexapi.client import PlexClient
from plexapi.exceptions import NotFound
from utils import log, register, safe_client, run_tests
from plexapi.myplex import MyPlexUser
from plexapi.utils import NA
SHOW_SECTION = 'TV Shows'
@ -25,9 +24,9 @@ AUDIO_SECTION = 'Music'
AUDIO_ARTIST = 'Beastie Boys'
AUDIO_ALBUM = 'Licensed To Ill'
AUDIO_TRACK = 'Brass Monkey'
CLIENT = 'pkkid-home'
CLIENT_BASEURL = 'http://192.168.1.131:3005'
PLEX_CLIENT = 'pkkid-home'
PLEX_CLIENT_BASEURL = 'http://192.168.1.131:3005'
#-----------------------
# Core
@ -390,17 +389,13 @@ def test_list_clients(plex, user=None):
@register('client')
def test_client_navigation(plex, user=None):
try:
client = plex.client(PLEX_CLIENT)
except NotFound as err:
log(2, 'Warning: %s' % err)
client = PlexClient(PLEX_CLIENT_BASEURL, server=plex)
client = safe_client(CLIENT, CLIENT_BASEURL, plex)
_navigate(plex, client)
# @register('client')
def test_client_navigation_via_proxy(plex, user=None):
client = plex.client(PLEX_CLIENT)
client = safe_client(CLIENT, CLIENT_BASEURL, plex)
client.proxyThroughServer()
_navigate(plex, client)
@ -439,13 +434,13 @@ def _navigate(plex, client):
@register('client')
def test_video_playback(plex, user=None):
client = plex.client(PLEX_CLIENT)
client = safe_client(CLIENT, CLIENT_BASEURL, plex)
_video_playback(plex, client)
# @register('client')
def test_video_playback_via_proxy(plex, user=None):
client = plex.client(PLEX_CLIENT)
client = safe_client(CLIENT, CLIENT_BASEURL, plex)
client.proxyThroughServer()
_video_playback(plex, client)
@ -477,7 +472,7 @@ def _video_playback(plex, client):
@register('client')
def test_client_timeline(plex, user=None):
mtype = 'video'
client = plex.client(PLEX_CLIENT)
client = safe_client(CLIENT, CLIENT_BASEURL, plex)
movie = plex.library.section(MOVIE_SECTION).get(MOVIE_TITLE)
playing = client.isPlayingMedia()
log(2, 'Playing Media: %s' % playing)
@ -539,7 +534,7 @@ def test_myplex_devices(plex, user=None):
@register('myplex,devices')
def test_myplex_connect_to_device(plex, user=None):
assert user, 'Must specify username, password & resource to run this test.'
device = user.device(PLEX_CLIENT)
device = user.device(CLIENT)
client = device.connect()
log(2, 'Connected to client: %s (%s)' % (client.title, client.product))
assert client, 'Unable to connect to device'

View file

@ -5,6 +5,8 @@ Test Library Functions
import sys, traceback
import datetime, time
from plexapi import server
from plexapi.client import PlexClient
from plexapi.exceptions import NotFound
from plexapi.myplex import MyPlexUser
COLORS = {'blue':'\033[94m', 'green':'\033[92m', 'red':'\033[91m', 'yellow':'\033[93m', 'end':'\033[0m'}
@ -39,6 +41,14 @@ def fetch_server(args):
return server.PlexServer(), None
def safe_client(name, baseurl, server):
try:
return server.client(name)
except NotFound as err:
log(2, 'Warning: %s' % err)
return PlexClient(baseurl, server=server)
def iter_tests(query):
tags = query[5:].split(',') if query and query.startswith('tags:') else ''
for test in registered: