mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-25 21:20:18 +00:00
Add delete
Supports media elements and librarys
This commit is contained in:
parent
454a858b7d
commit
6be7fa8a29
4 changed files with 72 additions and 25 deletions
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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©ts=1&mediaIndex=0&offset=0&path=%2Flibrary%2Fmetadata%2F1&X-Plex-Token={0}".format(os.environ.get('PLEX_TEST_TOKEN'))
|
||||
|
|
Loading…
Reference in a new issue