Add delete

Supports media elements and librarys
This commit is contained in:
Hellowlol 2017-02-11 00:16:23 +01:00
parent 454a858b7d
commit 6be7fa8a29
4 changed files with 72 additions and 25 deletions

View file

@ -2,26 +2,25 @@
import re
from plexapi import log, utils
from plexapi.compat import urlencode
from plexapi.exceptions import BadRequest, NotFound
from plexapi.exceptions import UnknownType, Unsupported
from plexapi.exceptions import BadRequest, NotFound, UnknownType, Unsupported
OPERATORS = {
'exact': lambda v,q: v == q,
'iexact': lambda v,q: v.lower() == q.lower(),
'contains': lambda v,q: q in v,
'icontains': lambda v,q: q.lower() in v.lower(),
'in': lambda v,q: v in q,
'gt': lambda v,q: v > q,
'gte': lambda v,q: v >= q,
'lt': lambda v,q: v < q,
'lte': lambda v,q: v <= q,
'startswith': lambda v,q: v.startswith(q),
'istartswith': lambda v,q: v.lower().startswith(q),
'endswith': lambda v,q: v.endswith(q),
'iendswith': lambda v,q: v.lower().endswith(q),
'exact': lambda v, q: v == q,
'iexact': lambda v, q: v.lower() == q.lower(),
'contains': lambda v, q: q in v,
'icontains': lambda v, q: q.lower() in v.lower(),
'in': lambda v, q: v in q,
'gt': lambda v, q: v > q,
'gte': lambda v, q: v >= q,
'lt': lambda v, q: v < q,
'lte': lambda v, q: v <= q,
'startswith': lambda v, q: v.startswith(q),
'istartswith': lambda v, q: v.lower().startswith(q),
'endswith': lambda v, q: v.endswith(q),
'iendswith': lambda v, q: v.lower().endswith(q),
'ismissing': None, # special case in _checkAttrs
'regex': lambda v,q: re.match(q, v),
'iregex': lambda v,q: re.match(q, v, flags=re.IGNORECASE),
'regex': lambda v, q: re.match(q, v),
'iregex': lambda v, q: re.match(q, v, flags=re.IGNORECASE),
}
@ -52,9 +51,10 @@ class PlexObject(object):
for attr in attrs:
value = self.__dict__.get(attr)
if value:
value = str(value).replace(' ','-')
value = value.replace('/library/metadata/','')
value = value.replace('/children','')
value = value.encode('utf-8')
value = str(value).replace(' ', '-')
value = value.replace('/library/metadata/', '')
value = value.replace('/children', '')
return value[:20]
def _buildItem(self, elem, cls=None, initpath=None, bytag=False):
@ -103,7 +103,7 @@ class PlexObject(object):
in, the key will be translated to /library/metadata/<key>. This allows
fetching an item only knowing its key-id.
cls (:class:`~plexapi.base.PlexObject`): If you know the class of the
items to be fetched, passing this in will help the parser ensure
items to be fetched, passing this in will help the parser ensure
it only returns those items. By default we convert the xml elements
to the best guess PlexObjects based on the type attr or tag.
bytag (bool): Setting this to True tells the build-items function to guess
@ -161,7 +161,9 @@ class PlexObject(object):
def reload(self, safe=False):
""" Reload the data for this object from self.key. """
if not self.key:
if safe: return None
if safe:
return None
raise Unsupported('Cannot reload an object not built from a URL.')
self._initpath = self.key
data = self._server.query(self.key)
@ -221,6 +223,14 @@ class PlexObject(object):
def _loadData(self, data):
raise NotImplementedError('Abstract method not implemented.')
def delete(self):
try:
return self._server.query(self.key, method=self._server._session.delete)
except BadRequest:
log.error('Failed to delete %s. This could be because you havnt allowed '
'items to be deleted' % self.key)
raise
class PlexPartialObject(PlexObject):
""" Not all objects in the Plex listings return the complete list of elements
@ -306,6 +316,15 @@ class PlexPartialObject(PlexObject):
""" Returns the :class:`~plexapi.library.LibrarySection` this item belongs to. """
return self._server.library.sectionByID(self.librarySectionID)
def delete(self):
"""Delete a media elemeent. This has to be enabled under settings > server > library in plex webui."""
try:
return self._server.query(self.key, method=self._server._session.delete)
except BadRequest: # pragma: no cover
log.error('Failed to delete %s. This could be because you havnt allowed '
'items to be deleted' % self.key)
raise
class Playable(object):
""" This is a general place to store functions specific to media that is Playable.
@ -382,7 +401,7 @@ class Playable(object):
def download(self, savepath=None, keep_orginal_name=False, **kwargs):
""" Downloads this items media to the specified location. Returns a list of
filepaths that have been saved to disk.
Parameters:
savepath (str): Title of the track to return.
keep_orginal_name (bool): Set True to keep the original filename as stored in

View file

@ -186,8 +186,15 @@ class LibrarySection(PlexObject):
self.uuid = data.attrib.get('uuid')
def __repr__(self):
return '<%s>' % ':'.join([p for p in [self.__class__.__name__,
self.key, self.librarySectionTitle] if p])
return '<%s>' % ':'.join([p for p in [self.__class__.__name__, self.key, self.librarySectionTitle] if p])
def delete(self):
"""Delete a library section."""
try:
return self._server.query('/library/sections/%s' % self.key, method=self._server._session.delete)
log.error('Failed to delete library %s. This could be because you havnt allowed '
'items to be deleted' % self.key)
raise
def get(self, title):
""" Returns the media item with the specified title.

View file

@ -47,9 +47,20 @@ def test_library_section_get_movie(pms): # fix me
assert m
def test_library_section_delete(monkeypatch, pms):
m = pms.library.section('Movies')
monkeypatch.delattr("requests.sessions.Session.request")
try:
m.delete()
except AttributeError:
pass # this will always raise because there is no request anymore.
def test_library_fetchItem(pms):
m = pms.library.fetchItem('/library/metadata/1')
f = pms.library.fetchItem(1)
assert m.title == '16 Blocks'
assert f == m
def test_library_onDeck(pms):

View file

@ -7,6 +7,16 @@ def test_video_Movie(a_movie_section):
m = a_movie_section.get('Cars')
assert m.title == 'Cars'
def test_video_Movie_delete(monkeypatch, pms):
m = pms.library.section('Movies').get('16 blocks')
monkeypatch.delattr("requests.sessions.Session.request")
try:
m.delete()
except AttributeError:
# Silence this because it will always raise beause of monkeypatch
pass
def test_video_Movie_getStreamURL(a_movie):
assert a_movie.getStreamURL() == "http://138.68.157.5:32400/video/:/transcode/universal/start.m3u8?X-Plex-Platform=Chrome&copyts=1&mediaIndex=0&offset=0&path=%2Flibrary%2Fmetadata%2F1&X-Plex-Token={0}".format(os.environ.get('PLEX_TEST_TOKEN'))