Tighten up download code a bit; downloadLogs and DownloadDatabases were reversed (oops)

This commit is contained in:
Michael Shepanski 2017-02-26 23:59:46 -05:00
parent 55a38bead7
commit 43444459e3
4 changed files with 81 additions and 103 deletions

View file

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Python 2/3 compatability
# Always try Py3 first
import os
try:
string_type = basestring
@ -36,3 +37,12 @@ try:
from xml.etree import cElementTree as ElementTree
except ImportError:
from xml.etree import ElementTree
def makedirs(name, mode=0o777, exist_ok=False):
""" Mimicks os.makedirs() from Python 3. """
try:
os.makedirs(name, mode)
except OSError:
if not os.path.isdir(name) or not exist_ok:
raise

View file

@ -175,7 +175,6 @@ class PlexServer(PlexObject):
def clients(self):
""" Returns a list of all :class:`~plexapi.client.PlexClient` objects
connected to this server."""
items = []
cache_resource = None
from plexapi.myplex import MyPlexResource
@ -193,7 +192,6 @@ class PlexServer(PlexObject):
if conn.local is True:
port = conn.port
break
baseurl = 'http://%s:%s' % (elem.attrib['host'], port)
items.append(PlexClient(baseurl=baseurl, server=self, data=elem))
return items
@ -231,6 +229,16 @@ class PlexServer(PlexObject):
"""
return PlayQueue.create(self, item, **kwargs)
def downloadDatabases(self, savepath=None, unpack=False):
url = self.url('/diagnostics/databases')
filepath = utils.download(url, None, savepath, self._session, unpack=unpack)
return filepath
def downloadLogs(self, savepath=None, unpack=False):
url = self.url('/diagnostics/logs')
filepath = utils.download(url, None, savepath, self._session, unpack=unpack)
return filepath
def history(self):
""" Returns a list of media items from watched history. """
return self.fetchItems('/status/sessions/history/all')
@ -341,17 +349,7 @@ class PlexServer(PlexObject):
delim = '&' if '?' in key else '?'
return '%s%s%sX-Plex-Token=%s' % (self._baseurl, key, delim, self._token)
return '%s%s' % (self._baseurl, key)
def downloadLogs(self, savepath=None, unpack=False):
url = self.url('/diagnostics/databases')
fp = utils.download(url, filename=None, savepath=savepath, unpack=unpack, session=self._session)
return fp
def downloadDBS(self, savepath=None, unpack=False):
url = self.url('/diagnostics/logs')
fp = utils.download(url, filename=None, savepath=savepath, unpack=unpack, session=self._session)
return fp
class Account(PlexObject):
""" Contains the locally cached MyPlex account information. The properties provided don't

View file

@ -7,8 +7,8 @@ import time
import zipfile
from datetime import datetime
from threading import Thread
from plexapi.compat import quote, string_type
from plexapi.exceptions import NotFound
from plexapi import compat
from plexapi.exceptions import NotFound, PlexApiException
# Search Types - Plex uses these to filter specific media types when searching.
@ -31,7 +31,7 @@ class SecretsFilter(logging.Filter):
def filter(self, record):
cleanargs = list(record.args)
for i in range(len(cleanargs)):
if isinstance(cleanargs[i], string_type):
if isinstance(cleanargs[i], compat.string_type):
for secret in self.secrets:
cleanargs[i] = cleanargs[i].replace(secret, '<hidden>')
record.args = tuple(cleanargs)
@ -92,7 +92,7 @@ def joinArgs(args):
arglist = []
for key in sorted(args, key=lambda x: x.lower()):
value = str(args[key])
arglist.append('%s=%s' % (key, quote(value)))
arglist.append('%s=%s' % (key, compat.quote(value)))
return '?%s' % '&'.join(arglist)
@ -215,15 +215,15 @@ def downloadSessionImages(server, filename=None, height=150, width=150, opacity=
for part in media.iterParts():
if media.thumb:
url = media.thumb
if part.indexes: # Always use bif images if available.
if part.indexes: # always use bif images if available.
url = '/library/parts/%s/indexes/%s/%s' % (part.id, part.indexes.lower(), media.viewOffset)
if url:
if filename is None:
prettyname = media._prettyfilename()
filename = 'session_transcode_%s_%s_%s' % (media.usernames[0], prettyname, int(time.time()))
url = server.transcodeImage(url, height=height, width=width, opacity=opacity, saturation=saturation)
dfp = download(url, filename=filename)
info['username'] = {'filepath': dfp, 'url': url}
url = server.transcodeImage(url, height, width, opacity, saturation)
filepath = download(url, filename=filename)
info['username'] = {'filepath': filepath, 'url': url}
return info
@ -243,61 +243,37 @@ def download(url, filename=None, savepath=None, session=None, chunksize=4024, mo
>>> download(a_episode.getStreamURL(), a_episode.location)
/path/to/file
"""
# TODO: Review this; It should be properly logging and raising exceptions..
from plexapi import log
# fetch the data to be saved
session = session or requests.Session()
if savepath is None:
savepath = os.getcwd()
else:
# Make sure the user supplied path exists
try:
os.makedirs(savepath)
except OSError:
if not os.path.isdir(savepath): # pragma: no cover
raise
try:
response = session.get(url, stream=True)
# Lets grab the name if we dont supply one.
# This will be used for downloading logs/db etc.
if filename is None and response.headers.get('Content-Disposition'):
filename = re.findall(r'filename=\"(.+)\"', response.headers.get('Content-Disposition'))
if filename:
filename = filename[0]
filename = os.path.basename(filename)
fullpath = os.path.join(savepath, filename)
# images dont have a extention so we try
# to guess it from content-type
ext = os.path.splitext(fullpath)[-1]
if ext:
ext = ''
else:
cp = response.headers.get('content-type')
if cp:
if 'image' in cp:
ext = '.%s' % cp.split('/')[1]
fullpath = '%s%s' % (fullpath, ext)
if mocked:
log.debug('Mocked download %s', fullpath)
return fullpath
with open(fullpath, 'wb') as f:
for chunk in response.iter_content(chunk_size=chunksize):
if chunk:
f.write(chunk)
if fullpath.endswith('zip') and unpack is True:
with zipfile.ZipFile(fullpath, 'r') as zp:
zp.extractall(savepath)
# log.debug('Downloaded %s to %s from %s' % (filename, fullpath, url))
response = session.get(url, stream=True)
# make sure the savepath directory exists
savepath = savepath or os.getcwd()
compat.makedirs(savepath, exist_ok=True)
# try getting filename from header if not specified in arguments (used for logs, db)
if not filename and response.headers.get('Content-Disposition'):
filename = re.findall(r'filename=\"(.+)\"', response.headers.get('Content-Disposition'))
filename = filename[0] if filename[0] else None
filename = os.path.basename(filename)
fullpath = os.path.join(savepath, filename)
# append file.ext from content-type if not already there
extension = os.path.splitext(fullpath)[-1]
if not extension:
contenttype = response.headers.get('content-type')
if contenttype and 'image' in contenttype:
fullpath += contenttype.split('/')[1]
# check this is a mocked download (testing)
if mocked:
log.debug('Mocked download %s', fullpath)
return fullpath
except Exception as err: # pragma: no cover
log.exception('Error downloading file: %s' % err)
raise
# log.exception('Failed to download %s to %s %s' % (url, fullpath, e))
# save the file to disk
log.info('Downloading: %s', fullpath)
with open(fullpath, 'wb') as handle:
for chunk in response.iter_content(chunk_size=chunksize):
handle.write(chunk)
# check we want to unzip the contents
if fullpath.endswith('zip') and unpack:
with zipfile.ZipFile(fullpath, 'r') as handle:
handle.extractall(savepath)
# finished; return fillpath
return fullpath

View file

@ -159,22 +159,20 @@ class Movie(Video, Playable):
a friendlier is generated.
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
"""
downloaded = []
locs = [i for i in self.iterParts() if i]
for loc in locs:
if keep_orginal_name is False:
name = '%s.%s' % (self.title.replace(' ', '.'), loc.container)
filepaths = []
locations = [i for i in self.iterParts() if i]
for location in locations:
name = location.file
if not keep_orginal_name:
title = self.title.replace(' ', '.')
name = '%s.%s' % (title, location.container)
if kwargs is not None:
url = self.getStreamURL(**kwargs)
else:
name = loc.file
# So this seems to be a alot slower but allows transcode.
if kwargs:
download_url = self.getStreamURL(**kwargs)
else:
download_url = self._server.url('%s?download=1' % loc.key)
dl = utils.download(download_url, filename=name, savepath=savepath, session=self._server._session)
if dl:
downloaded.append(dl)
return downloaded
self._server.url('%s?download=1' % location.key)
filepath = utils.download(url, filename=name, savepath=savepath, session=self._server._session)
filepaths.append(filepath)
return filepaths
@utils.registerPlexObject
@ -303,12 +301,10 @@ class Show(Video):
a friendlier is generated.
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
"""
downloaded = []
for ep in self.episodes():
dl = ep.download(savepath=savepath, keep_orginal_name=keep_orginal_name, **kwargs)
if dl:
downloaded.extend(dl)
return downloaded
filepaths = []
for episode in self.episodes():
filepaths += episode.download(savepath, keep_orginal_name, **kwargs)
return filepaths
@utils.registerPlexObject
@ -401,12 +397,10 @@ class Season(Video):
a friendlier is generated.
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.getStreamURL()`.
"""
downloaded = []
for ep in self.episodes():
dl = ep.download(savepath=savepath, keep_orginal_name=keep_orginal_name, **kwargs)
if dl:
downloaded.extend(dl)
return downloaded
filepaths = []
for episode in self.episodes():
filepaths += episode.download(savepath, keep_orginal_name, **kwargs)
return filepaths
@utils.registerPlexObject