diff --git a/TorrentToMedia.py b/TorrentToMedia.py index 06d36e1a..51a257c8 100755 --- a/TorrentToMedia.py +++ b/TorrentToMedia.py @@ -1,16 +1,22 @@ #!/usr/bin/env python # coding=utf-8 -import eol -eol.check() - -import cleanup -cleanup.clean(cleanup.FOLDER_STRUCTURE) +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) import datetime import os import sys +import eol +import cleanup +eol.check() +cleanup.clean(cleanup.FOLDER_STRUCTURE) + import core from core import logger, main_db from core.auto_process import comics, games, movies, music, tv, books @@ -18,7 +24,11 @@ from core.auto_process.common import ProcessResult from core.plugins.plex import plex_update from core.user_scripts import external_script from core.utils import char_replace, convert_to_ascii, replace_links -from six import text_type + +try: + text_type = unicode +except NameError: + text_type = str def process_torrent(input_directory, input_name, input_category, input_hash, input_id, client_agent): @@ -60,13 +70,13 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp input_category = 'UNCAT' usercat = input_category - #try: + # try: # input_name = input_name.encode(core.SYS_ENCODING) - #except UnicodeError: + # except UnicodeError: # pass - #try: + # try: # input_directory = input_directory.encode(core.SYS_ENCODING) - #except UnicodeError: + # except UnicodeError: # pass logger.debug('Determined Directory: {0} | Name: {1} | Category: {2}'.format @@ -125,9 +135,9 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp else: output_destination = os.path.normpath( core.os.path.join(core.OUTPUT_DIRECTORY, input_category)) - #try: + # try: # output_destination = output_destination.encode(core.SYS_ENCODING) - #except UnicodeError: + # except UnicodeError: # pass if output_destination in input_directory: @@ -170,9 +180,9 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp core.os.path.join(output_destination, os.path.basename(file_path)), full_file_name) logger.debug('Setting outputDestination to {0} to preserve folder structure'.format (os.path.dirname(target_file))) - #try: + # try: # target_file = target_file.encode(core.SYS_ENCODING) - #except UnicodeError: + # except UnicodeError: # pass if root == 1: if not found_file: @@ -259,7 +269,6 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp elif section_name == 'LazyLibrarian': result = books.process(section_name, output_destination, input_name, status, client_agent, input_category) - plex_update(input_category) if result.status_code != 0: @@ -279,7 +288,7 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp # remove torrent if core.USE_LINK == 'move-sym' and not core.DELETE_ORIGINAL == 1: logger.debug('Checking for sym-links to re-direct in: {0}'.format(input_directory)) - for dirpath, dirs, files in os.walk(input_directory): + for dirpath, _, files in os.walk(input_directory): for file in files: logger.debug('Checking symlink: {0}'.format(os.path.join(dirpath, file))) replace_links(os.path.join(dirpath, file)) @@ -353,14 +362,14 @@ def main(args): if client_agent.lower() not in core.TORRENT_CLIENTS: continue - #try: + # try: # dir_name = dir_name.encode(core.SYS_ENCODING) - #except UnicodeError: + # except UnicodeError: # pass input_name = os.path.basename(dir_name) - #try: + # try: # input_name = input_name.encode(core.SYS_ENCODING) - #except UnicodeError: + # except UnicodeError: # pass results = process_torrent(dir_name, input_name, subsection, input_hash or None, input_id or None, diff --git a/cleanup.py b/cleanup.py index d313f2b4..70c9ce29 100644 --- a/cleanup.py +++ b/cleanup.py @@ -1,6 +1,11 @@ #!/usr/bin/env python -from __future__ import print_function +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) import os import subprocess @@ -25,6 +30,7 @@ FOLDER_STRUCTURE = { class WorkingDirectory(object): """Context manager for changing current working directory.""" + def __init__(self, new, original=None): self.working_directory = new self.original_directory = os.getcwd() if original is None else original @@ -43,7 +49,7 @@ class WorkingDirectory(object): original_directory=self.original_directory, error=error, working_directory=self.working_directory, - ) + ), ) diff --git a/core/__init__.py b/core/__init__.py index d9cad1fd..7fb32140 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -1,6 +1,11 @@ # coding=utf-8 -from __future__ import print_function +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) import itertools import locale @@ -108,9 +113,9 @@ FORKS = { FORK_SICKCHILL: {'proc_dir': None, 'failed': None, 'process_method': None, 'force': None, 'delete_on': None, 'force_next': None}, FORK_SICKBEARD_API: {'path': None, 'failed': None, 'process_method': None, 'force_replace': None, 'return_data': None, 'type': None, 'delete': None, 'force_next': None}, FORK_MEDUSA: {'proc_dir': None, 'failed': None, 'process_method': None, 'force': None, 'delete_on': None, 'ignore_subs': None}, - FORK_MEDUSA_API: {'path': None, 'failed': None, 'process_method': None, 'force_replace': None, 'return_data': None, 'type': None, 'delete_files': None, 'is_priority': None}, + FORK_MEDUSA_API: {'path': None, 'failed': None, 'process_method': None, 'force_replace': None, 'return_data': None, 'type': None, 'delete_files': None, 'is_priority': None}, FORK_SICKGEAR: {'dir': None, 'failed': None, 'process_method': None, 'force': None}, - FORK_STHENO: {"proc_dir": None, "failed": None, "process_method": None, "force": None, "delete_on": None, "ignore_subs": None} + FORK_STHENO: {'proc_dir': None, 'failed': None, 'process_method': None, 'force': None, 'delete_on': None, 'ignore_subs': None}, } ALL_FORKS = {k: None for k in set(list(itertools.chain.from_iterable([FORKS[x].keys() for x in FORKS.keys()])))} @@ -656,7 +661,7 @@ def configure_transcoder(): codec_alias = { 'libx264': ['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], 'libmp3lame': ['libmp3lame', 'mp3'], - 'libfaac': ['libfaac', 'aac', 'faac'] + 'libfaac': ['libfaac', 'aac', 'faac'], } transcode_defaults = { 'iPad': { @@ -665,7 +670,7 @@ def configure_transcoder(): 'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': None, 'ACHANNELS': 2, 'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'iPad-1080p': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -673,7 +678,7 @@ def configure_transcoder(): 'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': None, 'ACHANNELS': 2, 'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'iPad-720p': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -681,7 +686,7 @@ def configure_transcoder(): 'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': None, 'ACHANNELS': 2, 'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'Apple-TV': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -689,7 +694,7 @@ def configure_transcoder(): 'ACODEC': 'ac3', 'ACODEC_ALLOW': ['ac3'], 'ABITRATE': None, 'ACHANNELS': 6, 'ACODEC2': 'aac', 'ACODEC2_ALLOW': ['libfaac'], 'ABITRATE2': None, 'ACHANNELS2': 2, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'iPod': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -697,7 +702,7 @@ def configure_transcoder(): 'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2, 'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'iPhone': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -705,7 +710,7 @@ def configure_transcoder(): 'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2, 'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'PS3': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -713,7 +718,7 @@ def configure_transcoder(): 'ACODEC': 'ac3', 'ACODEC_ALLOW': ['ac3'], 'ABITRATE': None, 'ACHANNELS': 6, 'ACODEC2': 'aac', 'ACODEC2_ALLOW': ['libfaac'], 'ABITRATE2': None, 'ACHANNELS2': 2, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'xbox': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -721,7 +726,7 @@ def configure_transcoder(): 'ACODEC': 'ac3', 'ACODEC_ALLOW': ['ac3'], 'ABITRATE': None, 'ACHANNELS': 6, 'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'Roku-480p': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -729,7 +734,7 @@ def configure_transcoder(): 'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2, 'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'Roku-720p': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -737,7 +742,7 @@ def configure_transcoder(): 'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2, 'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'Roku-1080p': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -745,7 +750,7 @@ def configure_transcoder(): 'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 160000, 'ACHANNELS': 2, 'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'mkv': { 'VEXTENSION': '.mkv', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None, @@ -761,7 +766,7 @@ def configure_transcoder(): 'ACODEC': 'dts', 'ACODEC_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE': None, 'ACHANNELS': 8, 'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None, 'ACODEC3': 'ac3', 'ACODEC3_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE3': None, 'ACHANNELS3': 8, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'mp4-scene-release': { 'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': 19, 'VLEVEL': '3.1', @@ -769,7 +774,7 @@ def configure_transcoder(): 'ACODEC': 'dts', 'ACODEC_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE': None, 'ACHANNELS': 8, 'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None, 'ACODEC3': 'ac3', 'ACODEC3_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE3': None, 'ACHANNELS3': 8, - 'SCODEC': 'mov_text' + 'SCODEC': 'mov_text', }, 'MKV-SD': { 'VEXTENSION': '.mkv', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': '1200k', 'VCRF': None, 'VLEVEL': None, @@ -777,8 +782,8 @@ def configure_transcoder(): 'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2, 'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6, 'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None, - 'SCODEC': 'mov_text' - } + 'SCODEC': 'mov_text', + }, } if DEFAULTS and DEFAULTS in transcode_defaults: VEXTENSION = transcode_defaults[DEFAULTS]['VEXTENSION'] @@ -881,7 +886,7 @@ def configure_utility_locations(): else: if SYS_PATH: - os.environ['PATH'] += ':'+SYS_PATH + os.environ['PATH'] += ':' + SYS_PATH try: SEVENZIP = subprocess.Popen(['which', '7z'], stdout=subprocess.PIPE).communicate()[0].strip().decode() except Exception: @@ -968,7 +973,7 @@ def check_python(): major=sys.version_info[0], minor=sys.version_info[1], x=days_left, - ) + ), ) if days_left <= grace_period: logger.warning('Please upgrade to a more recent Python version.') diff --git a/core/auto_process/books.py b/core/auto_process/books.py index c029d06f..9c908a94 100644 --- a/core/auto_process/books.py +++ b/core/auto_process/books.py @@ -1,14 +1,23 @@ # coding=utf-8 -import os -import shutil +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) import requests import core from core import logger from core.auto_process.common import ProcessResult -from core.utils import convert_to_ascii, server_responding +from core.utils import ( + convert_to_ascii, + remote_dir, + server_responding, +) + requests.packages.urllib3.disable_warnings() @@ -24,6 +33,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', ssl = int(cfg.get('ssl', 0)) web_root = cfg.get('web_root', '') protocol = 'https://' if ssl else 'http://' + remote_path = int(cfg.get('remote_path', 0)) url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root) if not server_responding(url): @@ -38,7 +48,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', params = { 'apikey': apikey, 'cmd': 'forceProcess', - 'dir': dir_name, + 'dir': remote_dir(dir_name) if remote_path else dir_name, } logger.debug('Opening URL: {0} with params: {1}'.format(url, params), section) @@ -52,7 +62,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', ) logger.postprocess('{0}'.format(r.text), section) - + if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error('Server returned status {0}'.format(r.status_code), section) return ProcessResult( diff --git a/core/auto_process/comics.py b/core/auto_process/comics.py index 7049704b..bb884404 100644 --- a/core/auto_process/comics.py +++ b/core/auto_process/comics.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import requests @@ -60,7 +67,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', logger.error('Unable to open URL', section) return ProcessResult( message='{0}: Failed to post-process - Unable to connect to {0}'.format(section), - status_code=1 + status_code=1, ) if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]: logger.error('Server returned status {0}'.format(r.status_code), section) diff --git a/core/auto_process/common.py b/core/auto_process/common.py index 8da83485..c083414c 100644 --- a/core/auto_process/common.py +++ b/core/auto_process/common.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import requests from core import logger @@ -17,7 +24,7 @@ class ProcessResult(object): def __str__(self): return 'Processing {0}: {1}'.format( 'succeeded' if bool(self) else 'failed', - self.message + self.message, ) def __repr__(self): diff --git a/core/auto_process/games.py b/core/auto_process/games.py index c412a690..73907d25 100644 --- a/core/auto_process/games.py +++ b/core/auto_process/games.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import shutil @@ -46,7 +53,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', 'api_key': apikey, 'mode': 'UPDATEREQUESTEDSTATUS', 'db_id': gamez_id, - 'status': download_status + 'status': download_status, } logger.debug('Opening URL: {0}'.format(url), section) diff --git a/core/auto_process/movies.py b/core/auto_process/movies.py index b7fe3a66..2661edd1 100644 --- a/core/auto_process/movies.py +++ b/core/auto_process/movies.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import json import os import time @@ -256,7 +263,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', return ProcessResult( message='{0}: Sending failed download back to {0}'.format(section), status_code=1, # Return as failed to flag this in the downloader. - ) # Return failed flag, but log the event as successful. + ) # Return failed flag, but log the event as successful. if delete_failed and os.path.isdir(dir_name) and not os.path.dirname(dir_name) == dir_name: logger.postprocess('Deleting failed files and folder {0}'.format(dir_name), section) @@ -373,22 +380,22 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', except Exception: pass elif scan_id: - url = '{0}/{1}'.format(base_url, scan_id) - command_status = command_complete(url, params, headers, section) - if command_status: - logger.debug('The Scan command return status: {0}'.format(command_status), section) - if command_status in ['completed']: - logger.debug('The Scan command has completed successfully. Renaming was successful.', section) - return ProcessResult( - message='{0}: Successfully post-processed {1}'.format(section, input_name), - status_code=0, - ) - elif command_status in ['failed']: - logger.debug('The Scan command has failed. Renaming was not successful.', section) - # return ProcessResult( - # message='{0}: Failed to post-process {1}'.format(section, input_name), - # status_code=1, - # ) + url = '{0}/{1}'.format(base_url, scan_id) + command_status = command_complete(url, params, headers, section) + if command_status: + logger.debug('The Scan command return status: {0}'.format(command_status), section) + if command_status in ['completed']: + logger.debug('The Scan command has completed successfully. Renaming was successful.', section) + return ProcessResult( + message='{0}: Successfully post-processed {1}'.format(section, input_name), + status_code=0, + ) + elif command_status in ['failed']: + logger.debug('The Scan command has failed. Renaming was not successful.', section) + # return ProcessResult( + # message='{0}: Failed to post-process {1}'.format(section, input_name), + # status_code=1, + # ) if not os.path.isdir(dir_name): logger.postprocess('SUCCESS: Input Directory [{0}] has been processed and removed'.format( @@ -504,7 +511,7 @@ def get_release(base_url, imdb_id=None, download_id=None, release_id=None): # Narrow results by removing old releases by comparing their last_edit field if len(results) > 1: for id1, x1 in results.items(): - for id2, x2 in results.items(): + for x2 in results.values(): try: if x2['last_edit'] > x1['last_edit']: results.pop(id1) diff --git a/core/auto_process/music.py b/core/auto_process/music.py index 4f10c64e..e72d9b8c 100644 --- a/core/auto_process/music.py +++ b/core/auto_process/music.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import json import os import time @@ -73,7 +80,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', params = { 'apikey': apikey, 'cmd': 'forceProcess', - 'dir': remote_dir(dir_name) if remote_path else dir_name + 'dir': remote_dir(dir_name) if remote_path else dir_name, } res = force_process(params, url, apikey, input_name, dir_name, section, wait_for) @@ -83,7 +90,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', params = { 'apikey': apikey, 'cmd': 'forceProcess', - 'dir': os.path.split(remote_dir(dir_name))[0] if remote_path else os.path.split(dir_name)[0] + 'dir': os.path.split(remote_dir(dir_name))[0] if remote_path else os.path.split(dir_name)[0], } res = force_process(params, url, apikey, input_name, dir_name, section, wait_for) @@ -187,7 +194,7 @@ def get_status(url, apikey, dir_name): params = { 'apikey': apikey, - 'cmd': 'getHistory' + 'cmd': 'getHistory', } logger.debug('Opening URL: {0} with PARAMS: {1}'.format(url, params)) diff --git a/core/auto_process/tv.py b/core/auto_process/tv.py index c4a68f59..57fe2a1e 100644 --- a/core/auto_process/tv.py +++ b/core/auto_process/tv.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import copy import errno import json @@ -266,7 +273,7 @@ def process(section, dir_name, input_name=None, failed=False, client_agent='manu if apikey: url = '{0}{1}:{2}{3}/api/{4}/?cmd=postprocess'.format(protocol, host, port, web_root, apikey) elif fork == 'Stheno': - url = "{0}{1}:{2}{3}/home/postprocess/process_episode".format(protocol, host, port, web_root) + url = '{0}{1}:{2}{3}/home/postprocess/process_episode'.format(protocol, host, port, web_root) else: url = '{0}{1}:{2}{3}/home/postprocess/processEpisode'.format(protocol, host, port, web_root) elif section == 'NzbDrone': diff --git a/core/configuration.py b/core/configuration.py index 216a1f05..c8e2a465 100644 --- a/core/configuration.py +++ b/core/configuration.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import copy import os import shutil @@ -13,17 +20,17 @@ from core import logger class Section(configobj.Section, object): - def isenabled(section): + def isenabled(self): # checks if subsection enabled, returns true/false if subsection specified otherwise returns true/false in {} - if not section.sections: + if not self.sections: try: - value = list(ConfigObj.find_key(section, 'enabled'))[0] + value = list(ConfigObj.find_key(self, 'enabled'))[0] except Exception: value = 0 if int(value) == 1: - return section + return self else: - to_return = copy.deepcopy(section) + to_return = copy.deepcopy(self) for section_name, subsections in to_return.items(): for subsection in subsections: try: @@ -40,8 +47,8 @@ class Section(configobj.Section, object): return to_return - def findsection(section, key): - to_return = copy.deepcopy(section) + def findsection(self, key): + to_return = copy.deepcopy(self) for subsection in to_return: try: value = list(ConfigObj.find_key(to_return[subsection], key))[0] @@ -136,10 +143,10 @@ class ConfigObj(configobj.ConfigObj, Section): subsections = {} # gather all new-style and old-style sub-sections - for newsection, newitems in CFG_NEW.items(): + for newsection in CFG_NEW: if CFG_NEW[newsection].sections: subsections.update({newsection: CFG_NEW[newsection].sections}) - for section, items in CFG_OLD.items(): + for section in CFG_OLD: if CFG_OLD[section].sections: subsections.update({section: CFG_OLD[section].sections}) for option, value in CFG_OLD[section].items(): diff --git a/core/databases.py b/core/databases.py index 07a78a4d..50e025f3 100644 --- a/core/databases.py +++ b/core/databases.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + from core import logger, main_db from core.utils import backup_versioned_file @@ -33,7 +40,7 @@ class InitialSchema(main_db.SchemaUpgrade): queries = [ 'CREATE TABLE db_version (db_version INTEGER);', 'CREATE TABLE downloads (input_directory TEXT, input_name TEXT, input_hash TEXT, input_id TEXT, client_agent TEXT, status INTEGER, last_update NUMERIC, CONSTRAINT pk_downloadID PRIMARY KEY (input_directory, input_name));', - 'INSERT INTO db_version (db_version) VALUES (2);' + 'INSERT INTO db_version (db_version) VALUES (2);', ] for query in queries: self.connection.action(query) @@ -59,7 +66,7 @@ class InitialSchema(main_db.SchemaUpgrade): 'INSERT INTO downloads2 SELECT * FROM downloads;', 'DROP TABLE IF EXISTS downloads;', 'ALTER TABLE downloads2 RENAME TO downloads;', - 'INSERT INTO db_version (db_version) VALUES (2);' + 'INSERT INTO db_version (db_version) VALUES (2);', ] for query in queries: self.connection.action(query) diff --git a/core/extractor/__init__.py b/core/extractor/__init__.py index 5d1c51a0..44be3102 100644 --- a/core/extractor/__init__.py +++ b/core/extractor/__init__.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import platform import shutil diff --git a/core/forks.py b/core/forks.py index be81a965..c1721aaf 100644 --- a/core/forks.py +++ b/core/forks.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import requests from six import iteritems @@ -42,7 +49,8 @@ def auto_fork(section, input_category): logger.info('Attempting to verify {category} fork'.format (category=input_category)) url = '{protocol}{host}:{port}{root}/api/rootfolder'.format( - protocol=protocol, host=host, port=port, root=web_root) + protocol=protocol, host=host, port=port, root=web_root, + ) headers = {'X-Api-Key': apikey} try: r = requests.get(url, headers=headers, stream=True, verify=False) @@ -65,10 +73,12 @@ def auto_fork(section, input_category): if apikey: url = '{protocol}{host}:{port}{root}/api/{apikey}/?cmd=help&subject=postprocess'.format( - protocol=protocol, host=host, port=port, root=web_root, apikey=apikey) + protocol=protocol, host=host, port=port, root=web_root, apikey=apikey, + ) else: url = '{protocol}{host}:{port}{root}/home/postprocess/'.format( - protocol=protocol, host=host, port=port, root=web_root) + protocol=protocol, host=host, port=port, root=web_root, + ) # attempting to auto-detect fork try: diff --git a/core/github_api.py b/core/github_api.py index 6e44f9f3..d61def2f 100644 --- a/core/github_api.py +++ b/core/github_api.py @@ -1,12 +1,17 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import requests class GitHub(object): - """ - Simple api wrapper for the Github API v3. - """ + """Simple api wrapper for the Github API v3.""" def __init__(self, github_repo_user, github_repo, branch='master'): @@ -15,16 +20,14 @@ class GitHub(object): self.branch = branch def _access_api(self, path, params=None): - """ - Access the API at the path given and with the optional params given. - """ + """Access API at given an API path and optional parameters.""" url = 'https://api.github.com/{path}'.format(path='/'.join(path)) data = requests.get(url, params=params, verify=False) return data.json() if data.ok else [] def commits(self): """ - Uses the API to get a list of the 100 most recent commits from the specified user/repo/branch, starting from HEAD. + Get the 100 most recent commits from the specified user/repo/branch, starting from HEAD. user: The github username of the person whose repo you're querying repo: The repo name to query @@ -39,7 +42,7 @@ class GitHub(object): def compare(self, base, head, per_page=1): """ - Uses the API to get a list of compares between base and head. + Get compares between base and head. user: The github username of the person whose repo you're querying repo: The repo name to query diff --git a/core/logger.py b/core/logger.py index 3305a96e..98b15432 100644 --- a/core/logger.py +++ b/core/logger.py @@ -1,11 +1,19 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import logging import os import sys import threading import core +import functools # number of log files to keep NUM_LOGS = 3 @@ -85,9 +93,9 @@ class NTMRotatingLogHandler(object): console.setFormatter(DispatchingFormatter( {'nzbtomedia': logging.Formatter('[%(asctime)s] [%(levelname)s]::%(message)s', '%H:%M:%S'), 'postprocess': logging.Formatter('[%(asctime)s] [%(levelname)s]::%(message)s', '%H:%M:%S'), - 'db': logging.Formatter('[%(asctime)s] [%(levelname)s]::%(message)s', '%H:%M:%S') + 'db': logging.Formatter('[%(asctime)s] [%(levelname)s]::%(message)s', '%H:%M:%S'), }, - logging.Formatter('%(message)s'), )) + logging.Formatter('%(message)s'))) # add the handler to the root logger logging.getLogger('nzbtomedia').addHandler(console) @@ -111,10 +119,7 @@ class NTMRotatingLogHandler(object): self.close_log(old_handler) def _config_handler(self): - """ - Configure a file handler to log at file_name and return it. - """ - + """Configure a file handler to log at file_name and return it.""" file_handler = logging.FileHandler(self.log_file_path, encoding='utf-8') file_handler.setLevel(DB) @@ -122,29 +127,29 @@ class NTMRotatingLogHandler(object): file_handler.setFormatter(DispatchingFormatter( {'nzbtomedia': logging.Formatter('%(asctime)s %(levelname)-8s::%(message)s', '%Y-%m-%d %H:%M:%S'), 'postprocess': logging.Formatter('%(asctime)s %(levelname)-8s::%(message)s', '%Y-%m-%d %H:%M:%S'), - 'db': logging.Formatter('%(asctime)s %(levelname)-8s::%(message)s', '%Y-%m-%d %H:%M:%S') + 'db': logging.Formatter('%(asctime)s %(levelname)-8s::%(message)s', '%Y-%m-%d %H:%M:%S'), }, - logging.Formatter('%(message)s'), )) + logging.Formatter('%(message)s'))) return file_handler def _log_file_name(self, i): """ - Returns a numbered log file name depending on i. If i==0 it just uses logName, if not it appends - it to the extension (blah.log.3 for i == 3) - + Return a numbered log file name depending on i. + + If i==0 it just uses logName, if not it appends it to the extension + e.g. (blah.log.3 for i == 3) + i: Log number to ues """ - return self.log_file_path + ('.{0}'.format(i) if i else '') def _num_logs(self): """ - Scans the log folder and figures out how many log files there are already on disk + Scan the log folder and figure out how many log files there are already on disk. Returns: The number of the last used file (eg. mylog.log.3 would return 3). If there are no logs it returns -1 """ - cur_log = 0 while os.path.isfile(self._log_file_name(cur_log)): cur_log += 1 @@ -202,9 +207,8 @@ class NTMRotatingLogHandler(object): ntm_logger = logging.getLogger('nzbtomedia') pp_logger = logging.getLogger('postprocess') db_logger = logging.getLogger('db') - setattr(pp_logger, 'postprocess', lambda *args: pp_logger.log(POSTPROCESS, *args)) - setattr(db_logger, 'db', lambda *args: db_logger.log(DB, *args)) - + pp_logger.postprocess = functools.partial(pp_logger.log, POSTPROCESS) + db_logger.db = functools.partial(db_logger.log, DB) try: if log_level == DEBUG: if core.LOG_DEBUG == 1: diff --git a/core/main_db.py b/core/main_db.py index 12c21c7e..d9d7c1b9 100644 --- a/core/main_db.py +++ b/core/main_db.py @@ -1,19 +1,52 @@ # coding=utf-8 -from __future__ import print_function +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) import re import sqlite3 import time -from six import text_type +from six import text_type, PY2 import core from core import logger +if PY2: + class Row(sqlite3.Row, object): + """ + Row factory that uses Byte Strings for keys. + + The sqlite3.Row in Python 2 does not support unicode keys. + This overrides __getitem__ to attempt to encode the key to bytes first. + """ + + def __getitem__(self, item): + """ + Get an item from the row by index or key. + + :param item: Index or Key of item to return. + :return: An item from the sqlite3.Row. + """ + try: + # sqlite3.Row column names should be Bytes in Python 2 + item = item.encode() + except AttributeError: + pass # assume item is a numeric index + + return super(Row, self).__getitem__(item) +else: + from sqlite3 import Row + def db_filename(filename='nzbtomedia.db', suffix=None): """ + Return the correct location of the database file. + @param filename: The sqlite database filename to use. If not specified, will be made to be nzbtomedia.db @param suffix: The suffix to append to the filename. A '.' will be added @@ -30,10 +63,7 @@ class DBConnection(object): self.filename = filename self.connection = sqlite3.connect(db_filename(filename), 20) - if row_type == 'dict': - self.connection.row_factory = self._dict_factory - else: - self.connection.row_factory = sqlite3.Row + self.connection.row_factory = Row def check_db_version(self): result = None @@ -183,9 +213,9 @@ class DBConnection(object): 'WHERE {conditions}'.format( table=table_name, params=', '.join(gen_params(value_dict)), - conditions=' AND '.join(gen_params(key_dict)) + conditions=' AND '.join(gen_params(key_dict)), ), - items + items, ) if self.connection.total_changes == changes_before: @@ -194,9 +224,9 @@ class DBConnection(object): 'VALUES ({values})'.format( table=table_name, columns=', '.join(map(text_type, value_dict.keys())), - values=', '.join(['?'] * len(value_dict.values())) + values=', '.join(['?'] * len(value_dict.values())), ), - list(value_dict.values()) + list(value_dict.values()), ) def table_info(self, table_name): @@ -207,13 +237,6 @@ class DBConnection(object): for column in cursor } - # http://stackoverflow.com/questions/3300464/how-can-i-get-dict-from-sqlite-query - def _dict_factory(self, cursor, row): - return { - col[0]: row[idx] - for idx, col in enumerate(cursor.description) - } - def sanity_check_database(connection, sanity_check): sanity_check(connection).check() diff --git a/core/plugins/downloaders/nzb/configuration.py b/core/plugins/downloaders/nzb/configuration.py index d0883d01..6acd4fc4 100644 --- a/core/plugins/downloaders/nzb/configuration.py +++ b/core/plugins/downloaders/nzb/configuration.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import core diff --git a/core/plugins/downloaders/nzb/utils.py b/core/plugins/downloaders/nzb/utils.py index 23061c96..f5dd29ba 100644 --- a/core/plugins/downloaders/nzb/utils.py +++ b/core/plugins/downloaders/nzb/utils.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import requests diff --git a/core/plugins/downloaders/torrent/configuration.py b/core/plugins/downloaders/torrent/configuration.py index 92001636..dd8e8ffa 100644 --- a/core/plugins/downloaders/torrent/configuration.py +++ b/core/plugins/downloaders/torrent/configuration.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import core from core.plugins.downloaders.torrent.utils import create_torrent_class diff --git a/core/plugins/downloaders/torrent/deluge.py b/core/plugins/downloaders/torrent/deluge.py index 69ae2000..86542a8a 100644 --- a/core/plugins/downloaders/torrent/deluge.py +++ b/core/plugins/downloaders/torrent/deluge.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + from synchronousdeluge.client import DelugeClient import core diff --git a/core/plugins/downloaders/torrent/qbittorrent.py b/core/plugins/downloaders/torrent/qbittorrent.py index ff92512c..0532b9a7 100644 --- a/core/plugins/downloaders/torrent/qbittorrent.py +++ b/core/plugins/downloaders/torrent/qbittorrent.py @@ -1,4 +1,10 @@ -from __future__ import absolute_import +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + from qbittorrent import Client as qBittorrentClient @@ -14,7 +20,7 @@ def configure_client(): password = core.QBITTORRENT_PASSWORD logger.debug( - 'Connecting to {0}: http://{1}:{2}'.format(agent, host, port) + 'Connecting to {0}: http://{1}:{2}'.format(agent, host, port), ) client = qBittorrentClient('http://{0}:{1}/'.format(host, port)) try: diff --git a/core/plugins/downloaders/torrent/transmission.py b/core/plugins/downloaders/torrent/transmission.py index d122aaf0..8c58eae2 100644 --- a/core/plugins/downloaders/torrent/transmission.py +++ b/core/plugins/downloaders/torrent/transmission.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + from transmissionrpc.client import Client as TransmissionClient import core diff --git a/core/plugins/downloaders/torrent/utils.py b/core/plugins/downloaders/torrent/utils.py index be2db4e8..0d2896d7 100644 --- a/core/plugins/downloaders/torrent/utils.py +++ b/core/plugins/downloaders/torrent/utils.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import time import core diff --git a/core/plugins/downloaders/torrent/utorrent.py b/core/plugins/downloaders/torrent/utorrent.py index 634e8ca5..e591c46b 100644 --- a/core/plugins/downloaders/torrent/utorrent.py +++ b/core/plugins/downloaders/torrent/utorrent.py @@ -1,4 +1,9 @@ -from __future__ import absolute_import +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) from utorrent.client import UTorrentClient diff --git a/core/plugins/plex.py b/core/plugins/plex.py index 6d851e85..5c3f0e8b 100644 --- a/core/plugins/plex.py +++ b/core/plugins/plex.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import requests import core diff --git a/core/plugins/subtitles.py b/core/plugins/subtitles.py index f62f90de..df37e532 100644 --- a/core/plugins/subtitles.py +++ b/core/plugins/subtitles.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + from babelfish import Language import subliminal diff --git a/core/scene_exceptions.py b/core/scene_exceptions.py index f2c53c45..f00eccd3 100644 --- a/core/scene_exceptions.py +++ b/core/scene_exceptions.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import platform import re @@ -25,7 +32,7 @@ media_list = [r'\.s\d{2}e\d{2}\.', r'\.1080[pi]\.', r'\.720p\.', r'\.576[pi]', r r'\.internal\.', r'\bac3\b', r'\.ntsc\.', r'\.pal\.', r'\.secam\.', r'\bdivx\b', r'\bxvid\b'] media_pattern = re.compile('|'.join(media_list), flags=re.IGNORECASE) garbage_name = re.compile(r'^[a-zA-Z0-9]*$') -char_replace = [[r'(\w)1\.(\w)', r'\1i\2'] +char_replace = [[r'(\w)1\.(\w)', r'\1i\2'], ] @@ -121,7 +128,7 @@ def reverse_filename(filename, dirname, name): def rename_script(dirname): rename_file = '' - for directory, directories, files in os.walk(dirname): + for directory, _, files in os.walk(dirname): for file in files: if re.search(r'(rename\S*\.(sh|bat)$)', file, re.IGNORECASE): rename_file = os.path.join(directory, file) @@ -171,7 +178,7 @@ def par2(dirname): cmd = '' for item in command: cmd = '{cmd} {item}'.format(cmd=cmd, item=item) - logger.debug('calling command:{0}'.format(cmd), 'PAR2') + logger.debug('calling command:{0}'.format(cmd), 'PAR2') try: proc = subprocess.Popen(command, stdout=bitbucket, stderr=bitbucket) proc.communicate() diff --git a/core/transcoder.py b/core/transcoder.py index 0648df5d..014f84c3 100644 --- a/core/transcoder.py +++ b/core/transcoder.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import errno import json import sys @@ -548,7 +555,7 @@ def get_subs(file): sub_ext = ['.srt', '.sub', '.idx'] name = os.path.splitext(os.path.split(file)[1])[0] path = os.path.split(file)[0] - for directory, directories, filenames in os.walk(path): + for directory, _, filenames in os.walk(path): for filename in filenames: filepaths.extend([os.path.join(directory, filename)]) subfiles = [item for item in filepaths if os.path.splitext(item)[1] in sub_ext and name in item] @@ -854,7 +861,7 @@ def combine_mts(mts_path): def combine_cd(combine): new_files = [] - for item in set([re.match('(.+)[cC][dD][0-9].', item).groups()[0] for item in combine]): + for item in {re.match('(.+)[cC][dD][0-9].', item).groups()[0] for item in combine}: concat = '' for n in range(99): files = [file for file in combine if @@ -920,7 +927,7 @@ def transcode_directory(dir_name): logger.info('Transcoding video: {0}'.format(newfile_path)) print_cmd(command) result = 1 # set result to failed in case call fails. - if True: + try: if isinstance(file, string_types): proc = subprocess.Popen(command, stdout=bitbucket, stderr=bitbucket) else: @@ -934,8 +941,8 @@ def transcode_directory(dir_name): procin.stdout.close() proc.communicate() result = proc.returncode - #except Exception: - # logger.error('Transcoding of video {0} has failed'.format(newfile_path)) + except Exception: + logger.error('Transcoding of video {0} has failed'.format(newfile_path)) if core.SUBSDIR and result == 0 and isinstance(file, string_types): for sub in get_subs(file): @@ -979,7 +986,7 @@ def transcode_directory(dir_name): if not os.listdir(text_type(new_dir)): # this is an empty directory and we didn't transcode into it. os.rmdir(new_dir) new_dir = dir_name - if not core.PROCESSOUTPUT and core.DUPLICATE: # We postprocess the original files to CP/SB + if not core.PROCESSOUTPUT and core.DUPLICATE: # We postprocess the original files to CP/SB new_dir = dir_name bitbucket.close() return final_result, new_dir diff --git a/core/user_scripts.py b/core/user_scripts.py index 5d447670..45adb45b 100644 --- a/core/user_scripts.py +++ b/core/user_scripts.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os from subprocess import Popen @@ -47,7 +54,7 @@ def external_script(output_destination, torrent_name, torrent_label, settings): logger.info('Corrupt video file found {0}. Deleting.'.format(video), 'USERSCRIPT') os.unlink(video) - for dirpath, dirnames, filenames in os.walk(output_destination): + for dirpath, _, filenames in os.walk(output_destination): for file in filenames: file_path = core.os.path.join(dirpath, file) @@ -102,7 +109,7 @@ def external_script(output_destination, torrent_name, torrent_label, settings): final_result += result num_files_new = 0 - for dirpath, dirnames, filenames in os.walk(output_destination): + for _, _, filenames in os.walk(output_destination): for file in filenames: file_name, file_extension = os.path.splitext(file) diff --git a/core/utils/__init__.py b/core/utils/__init__.py index 470fe4fd..202e7d19 100644 --- a/core/utils/__init__.py +++ b/core/utils/__init__.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import requests from core.utils import shutil_custom diff --git a/core/utils/common.py b/core/utils/common.py index 5ecdf830..2174644c 100644 --- a/core/utils/common.py +++ b/core/utils/common.py @@ -1,3 +1,9 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) import os.path diff --git a/core/utils/download_info.py b/core/utils/download_info.py index ce6e6717..2e30d35c 100644 --- a/core/utils/download_info.py +++ b/core/utils/download_info.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import datetime from six import text_type diff --git a/core/utils/encoding.py b/core/utils/encoding.py index ca19e054..bcc4994f 100644 --- a/core/utils/encoding.py +++ b/core/utils/encoding.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os from six import text_type @@ -68,14 +75,14 @@ def convert_to_ascii(input_name, dir_name): if 'NZBOP_SCRIPTDIR' in os.environ: print('[NZB] DIRECTORY={0}'.format(dir_name)) - for dirname, dirnames, filenames in os.walk(dir_name, topdown=False): + for dirname, dirnames, _ in os.walk(dir_name, topdown=False): for subdirname in dirnames: encoded, subdirname2 = char_replace(subdirname) if encoded: logger.info('Renaming directory to: {0}.'.format(subdirname2), 'ENCODER') os.rename(os.path.join(dirname, subdirname), os.path.join(dirname, subdirname2)) - for dirname, dirnames, filenames in os.walk(dir_name): + for dirname, _, filenames in os.walk(dir_name): for filename in filenames: encoded, filename2 = char_replace(filename) if encoded: diff --git a/core/utils/files.py b/core/utils/files.py index 895125e1..726d4209 100644 --- a/core/utils/files.py +++ b/core/utils/files.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import re import shutil @@ -88,7 +95,7 @@ def is_min_size(input_name, min_size): def is_archive_file(filename): - """Check if the filename is allowed for the Archive""" + """Check if the filename is allowed for the Archive.""" for regext in core.COMPRESSED_CONTAINER: if regext.search(filename): return regext.split(filename)[0] diff --git a/core/utils/identification.py b/core/utils/identification.py index 7a48ec87..365ea790 100644 --- a/core/utils/identification.py +++ b/core/utils/identification.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import re @@ -5,7 +12,6 @@ import guessit import requests from six import text_type -import core from core import logger from core.utils.naming import sanitize_name @@ -90,13 +96,13 @@ def find_imdbid(dir_name, input_name, omdb_api_key): def category_search(input_directory, input_name, input_category, root, categories): tordir = False - #try: + # try: # input_name = input_name.encode(core.SYS_ENCODING) - #except Exception: + # except Exception: # pass - #try: + # try: # input_directory = input_directory.encode(core.SYS_ENCODING) - #except Exception: + # except Exception: # pass if input_directory is None: # =Nothing to process here. diff --git a/core/utils/links.py b/core/utils/links.py index ab558e9b..1daa2441 100644 --- a/core/utils/links.py +++ b/core/utils/links.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import shutil diff --git a/core/utils/naming.py b/core/utils/naming.py index 8b3e6971..4d664036 100644 --- a/core/utils/naming.py +++ b/core/utils/naming.py @@ -1,9 +1,17 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import re -import core def sanitize_name(name): """ + Remove bad chars from the filename. + >>> sanitize_name('a/b/c') 'a-b-c' >>> sanitize_name('abc') @@ -13,29 +21,26 @@ def sanitize_name(name): >>> sanitize_name('.a.b..') 'a.b' """ - - # remove bad chars from the filename name = re.sub(r'[\\/*]', '-', name) name = re.sub(r'[:\'<>|?]', '', name) # remove leading/trailing periods and spaces name = name.strip(' .') - #try: + # try: # name = name.encode(core.SYS_ENCODING) - #except Exception: + # except Exception: # pass return name def clean_file_name(filename): - """Cleans up nzb name by removing any . and _ - characters, along with any trailing hyphens. + """ + Clean up nzb name by removing any . and _ characters and trailing hyphens. Is basically equivalent to replacing all _ and . with a space, but handles decimal numbers in string, for example: """ - filename = re.sub(r'(\D)\.(?!\s)(\D)', r'\1 \2', filename) filename = re.sub(r'(\d)\.(\d{4})', r'\1 \2', filename) # if it ends in a year then don't keep the dot filename = re.sub(r'(\D)\.(?!\s)', r'\1 ', filename) diff --git a/core/utils/network.py b/core/utils/network.py index 5a7a5758..bfb54381 100644 --- a/core/utils/network.py +++ b/core/utils/network.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import socket import struct import time diff --git a/core/utils/parsers.py b/core/utils/parsers.py index d5f6d933..981de146 100644 --- a/core/utils/parsers.py +++ b/core/utils/parsers.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import core diff --git a/core/utils/paths.py b/core/utils/paths.py index dba119f5..ee0a48db 100644 --- a/core/utils/paths.py +++ b/core/utils/paths.py @@ -1,3 +1,9 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) from functools import partial import os @@ -67,14 +73,14 @@ def remote_dir(path): def get_dir_size(input_path): prepend = partial(os.path.join, input_path) - return sum([ + return sum( (os.path.getsize(f) if os.path.isfile(f) else get_dir_size(f)) for f in map(prepend, os.listdir(text_type(input_path))) - ]) + ) def remove_empty_folders(path, remove_root=True): - """Function to remove empty folders""" + """Remove empty folders.""" if not os.path.isdir(path): return diff --git a/core/utils/processes.py b/core/utils/processes.py index 6edcfa44..23bb7a92 100644 --- a/core/utils/processes.py +++ b/core/utils/processes.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import socket import subprocess diff --git a/core/utils/shutil_custom.py b/core/utils/shutil_custom.py index 5525df1f..a6cb3af8 100644 --- a/core/utils/shutil_custom.py +++ b/core/utils/shutil_custom.py @@ -1,3 +1,10 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + from functools import partial import shutil from six import PY2 diff --git a/core/version_check.py b/core/version_check.py index 53945e1f..f1c05ba9 100644 --- a/core/version_check.py +++ b/core/version_check.py @@ -2,6 +2,13 @@ # Author: Nic Wolfe # Modified by: echel0n +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import platform import re @@ -19,9 +26,7 @@ from core import github_api as github, logger class CheckVersion(object): - """ - Version check class meant to run as a thread object with the SB scheduler. - """ + """Version checker that runs in a thread with the SB scheduler.""" def __init__(self): self.install_type = self.find_install_type() @@ -40,14 +45,13 @@ class CheckVersion(object): def find_install_type(self): """ - Determines how this copy of SB was installed. + Determine how this copy of SB was installed. returns: type of installation. Possible values are: 'win': any compiled windows build 'git': running from source using git 'source': running from source without git """ - # check if we're a windows build if os.path.isdir(os.path.join(core.APP_ROOT, u'.git')): install_type = 'git' @@ -58,13 +62,12 @@ class CheckVersion(object): def check_for_new_version(self, force=False): """ - Checks the internet for a newer version. + Check the internet for a newer version. returns: bool, True for new version or False for no new version. force: if true the VERSION_NOTIFY setting will be ignored and a check will be forced """ - if not core.VERSION_NOTIFY and not force: logger.log(u'Version checking is disabled, not checking for the newest version') return False @@ -199,8 +202,8 @@ class GitUpdateManager(UpdateManager): logger.log(u'{cmd} : returned successful'.format(cmd=cmd), logger.DEBUG) exit_status = 0 elif core.LOG_GIT and exit_status in (1, 128): - logger.log(u'{cmd} returned : {output}'.format - (cmd=cmd, output=output), logger.DEBUG) + logger.log(u'{cmd} returned : {output}'.format + (cmd=cmd, output=output), logger.DEBUG) else: if core.LOG_GIT: logger.log(u'{cmd} returned : {output}, treat as error for now'.format @@ -211,13 +214,12 @@ class GitUpdateManager(UpdateManager): def _find_installed_version(self): """ - Attempts to find the currently installed version of Sick Beard. + Attempt to find the currently installed version of Sick Beard. Uses git show to get commit version. Returns: True for success or False for failure """ - output, err, exit_status = self._run_git(self._git_path, 'rev-parse HEAD') # @UnusedVariable if exit_status == 0 and output: @@ -244,10 +246,12 @@ class GitUpdateManager(UpdateManager): def _check_github_for_update(self): """ - Uses git commands to check if there is a newer version that the provided - commit hash. If there is a newer version it sets _num_commits_behind. - """ + Check Github for a new version. + Uses git commands to check if there is a newer version than + the provided commit hash. If there is a newer version it + sets _num_commits_behind. + """ self._newest_commit_hash = None self._num_commits_behind = 0 self._num_commits_ahead = 0 @@ -324,10 +328,11 @@ class GitUpdateManager(UpdateManager): def update(self): """ - Calls git pull origin in order to update Sick Beard. Returns a bool depending - on the call's success. - """ + Check git for a new version. + Calls git pull origin in order to update Sick Beard. + Returns a bool depending on the call's success. + """ output, err, exit_status = self._run_git(self._git_path, 'pull origin {branch}'.format(branch=self.branch)) # @UnusedVariable if exit_status == 0: @@ -382,12 +387,14 @@ class SourceUpdateManager(UpdateManager): def _check_github_for_update(self): """ - Uses pygithub to ask github if there is a newer version that the provided - commit hash. If there is a newer version it sets Sick Beard's version text. + Check Github for a new version. + + Uses pygithub to ask github if there is a newer version than + the provided commit hash. If there is a newer version it sets + Sick Beard's version text. commit_hash: hash that we're checking against """ - self._num_commits_behind = 0 self._newest_commit_hash = None @@ -435,9 +442,7 @@ class SourceUpdateManager(UpdateManager): return def update(self): - """ - Downloads the latest source tarball from github and installs it over the existing version. - """ + """Download and install latest source tarball from github.""" tar_download_url = 'https://github.com/{org}/{repo}/tarball/{branch}'.format( org=self.github_repo_user, repo=self.github_repo, branch=self.branch) version_path = os.path.join(core.APP_ROOT, u'version.txt') @@ -489,7 +494,7 @@ class SourceUpdateManager(UpdateManager): # walk temp folder and move files to main folder logger.log(u'Moving files from {source} to {destination}'.format (source=content_dir, destination=core.APP_ROOT)) - for dirname, dirnames, filenames in os.walk(content_dir): # @UnusedVariable + for dirname, _, filenames in os.walk(content_dir): # @UnusedVariable dirname = dirname[len(content_dir) + 1:] for curfile in filenames: old_path = os.path.join(content_dir, dirname, curfile) diff --git a/eol.py b/eol.py index a67bfc9e..7310cfd6 100644 --- a/eol.py +++ b/eol.py @@ -1,5 +1,12 @@ #!/usr/bin/env python +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import datetime import sys import warnings @@ -157,7 +164,7 @@ def print_statuses(show_expired=False): major=python_version[0], minor=python_version[1], remaining=days_left, - ) + ), ) if not show_expired: return @@ -171,7 +178,7 @@ def print_statuses(show_expired=False): major=python_version[0], minor=python_version[1], remaining=-days_left, - ) + ), ) diff --git a/libs/__init__.py b/libs/__init__.py index 4405201d..6c9b28b4 100644 --- a/libs/__init__.py +++ b/libs/__init__.py @@ -1,4 +1,11 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import site import sys diff --git a/libs/__main__.py b/libs/__main__.py index 767f0d6e..b3d3d8e2 100644 --- a/libs/__main__.py +++ b/libs/__main__.py @@ -1,4 +1,11 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import shutil import os import time diff --git a/libs/autoload.py b/libs/autoload.py index 23205448..a44ac0fb 100644 --- a/libs/autoload.py +++ b/libs/autoload.py @@ -1,4 +1,11 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import libs __all__ = ['completed'] diff --git a/libs/custom/synchronousdeluge/__init__.py b/libs/custom/synchronousdeluge/__init__.py index fbafe6fe..fef43298 100644 --- a/libs/custom/synchronousdeluge/__init__.py +++ b/libs/custom/synchronousdeluge/__init__.py @@ -1,7 +1,8 @@ # coding=utf-8 -"""A synchronous implementation of the Deluge RPC protocol - based on gevent-deluge by Christopher Rosell. - +""" +A synchronous implementation of the Deluge RPC protocol. + +Based on gevent-deluge by Christopher Rosell: https://github.com/chrippa/gevent-deluge Example usage: @@ -15,9 +16,16 @@ Example usage: download_location = client.core.get_config_value("download_location").get() """ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + from .exceptions import DelugeRPCError -__title__ = "synchronous-deluge" -__version__ = "0.1" -__author__ = "Christian Dale" +__title__ = 'synchronous-deluge' +__version__ = '0.1' +__author__ = 'Christian Dale' diff --git a/libs/custom/synchronousdeluge/client.py b/libs/custom/synchronousdeluge/client.py index aa180bf7..191c70f6 100644 --- a/libs/custom/synchronousdeluge/client.py +++ b/libs/custom/synchronousdeluge/client.py @@ -1,4 +1,12 @@ # coding=utf-8 + +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import os import platform from collections import defaultdict @@ -9,7 +17,7 @@ from .exceptions import DelugeRPCError from .protocol import DelugeRPCRequest, DelugeRPCResponse from .transfer import DelugeTransfer -__all__ = ["DelugeClient"] +__all__ = ['DelugeClient'] RPC_RESPONSE = 1 RPC_ERROR = 2 @@ -18,41 +26,41 @@ RPC_EVENT = 3 class DelugeClient(object): def __init__(self): - """A deluge client session.""" + """Create a deluge client session.""" self.transfer = DelugeTransfer() self.modules = [] self._request_counter = 0 def _get_local_auth(self): - username = password = "" + username = password = '' if platform.system() in ('Windows', 'Microsoft'): - app_data_path = os.environ.get("APPDATA") + app_data_path = os.environ.get('APPDATA') if not app_data_path: from six.moves import winreg hkey = winreg.OpenKey( winreg.HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders', ) - app_data_reg = winreg.QueryValueEx(hkey, "AppData") + app_data_reg = winreg.QueryValueEx(hkey, 'AppData') app_data_path = app_data_reg[0] winreg.CloseKey(hkey) - auth_file = os.path.join(app_data_path, "deluge", "auth") + auth_file = os.path.join(app_data_path, 'deluge', 'auth') else: from xdg.BaseDirectory import save_config_path try: - auth_file = os.path.join(save_config_path("deluge"), "auth") + auth_file = os.path.join(save_config_path('deluge'), 'auth') except OSError: return username, password if os.path.exists(auth_file): for line in open(auth_file): - if line.startswith("#"): + if line.startswith('#'): # This is a comment line continue line = line.strip() try: - lsplit = line.split(":") + lsplit = line.split(':') except Exception: continue @@ -63,13 +71,13 @@ class DelugeClient(object): else: continue - if username == "localclient": + if username == 'localclient': return username, password - return "", "" + return '', '' def _create_module_method(self, module, method): - fullname = "{0}.{1}".format(module, method) + fullname = '{0}.{1}'.format(module, method) def func(obj, *args, **kwargs): return self.remote_call(fullname, *args, **kwargs) @@ -80,18 +88,18 @@ class DelugeClient(object): def _introspect(self): def splitter(value): - return value.split(".") + return value.split('.') self.modules = [] - methods = self.remote_call("daemon.get_method_list").get() + methods = self.remote_call('daemon.get_method_list').get() methodmap = defaultdict(dict) for module, method in imap(splitter, methods): methodmap[module][method] = self._create_module_method(module, method) for module, methods in methodmap.items(): - clsname = "DelugeModule{0}".format(module.capitalize()) + clsname = 'DelugeModule{0}'.format(module.capitalize()) cls = type(clsname, (), methods) setattr(self, module, cls()) self.modules.append(module) @@ -133,24 +141,23 @@ class DelugeClient(object): self._request_counter += 1 return response - def connect(self, host="127.0.0.1", port=58846, username="", password=""): - """Connects to a daemon process. + def connect(self, host='127.0.0.1', port=58846, username='', password=''): + """Connect to a daemon process. :param host: str, the hostname of the daemon :param port: int, the port of the daemon :param username: str, the username to login with :param password: str, the password to login with """ - # Connect transport self.transfer.connect((host, port)) # Attempt to fetch local auth info if needed - if not username and host in ("127.0.0.1", "localhost"): + if not username and host in ('127.0.0.1', 'localhost'): username, password = self._get_local_auth() # Authenticate - self.remote_call("daemon.login", username, password).get() + self.remote_call('daemon.login', username, password).get() # Introspect available methods self._introspect() diff --git a/libs/custom/synchronousdeluge/exceptions.py b/libs/custom/synchronousdeluge/exceptions.py index 6da4bdde..1a8693e6 100644 --- a/libs/custom/synchronousdeluge/exceptions.py +++ b/libs/custom/synchronousdeluge/exceptions.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + class DelugeRPCError(Exception): def __init__(self, name, msg, traceback): @@ -8,4 +15,4 @@ class DelugeRPCError(Exception): self.traceback = traceback def __str__(self): - return "{0}: {1}: {2}".format(self.__class__.__name__, self.name, self.msg) + return '{0}: {1}: {2}'.format(self.__class__.__name__, self.name, self.msg) diff --git a/libs/custom/synchronousdeluge/protocol.py b/libs/custom/synchronousdeluge/protocol.py index 6dcdb2a1..b71dafb4 100644 --- a/libs/custom/synchronousdeluge/protocol.py +++ b/libs/custom/synchronousdeluge/protocol.py @@ -1,5 +1,12 @@ # coding=utf-8 +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + class DelugeRPCRequest(object): def __init__(self, request_id, method, *args, **kwargs): diff --git a/libs/custom/synchronousdeluge/transfer.py b/libs/custom/synchronousdeluge/transfer.py index 42863b83..75228032 100644 --- a/libs/custom/synchronousdeluge/transfer.py +++ b/libs/custom/synchronousdeluge/transfer.py @@ -1,4 +1,12 @@ # coding=utf-8 + +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import socket import ssl import struct @@ -6,7 +14,7 @@ import zlib import rencode -__all__ = ["DelugeTransfer"] +__all__ = ['DelugeTransfer'] class DelugeTransfer(object): @@ -33,7 +41,7 @@ class DelugeTransfer(object): payload = zlib.compress(rencode.dumps(data)) self.conn.sendall(payload) - buf = b"" + buf = b'' while True: data = self.conn.recv(1024) diff --git a/libs/custom/utorrent/client.py b/libs/custom/utorrent/client.py index 2be51c6d..f5eaf93b 100644 --- a/libs/custom/utorrent/client.py +++ b/libs/custom/utorrent/client.py @@ -1,4 +1,12 @@ # coding=utf8 + +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import re from six import StringIO, iteritems @@ -31,8 +39,7 @@ class UTorrentClient(object): # TODO refresh token, when necessary def _make_opener(self, realm, base_url, username, password): - """uTorrent API need HTTP Basic Auth and cookie support for token verify.""" - + """HTTP Basic Auth and cookie support for token verification.""" auth_handler = HTTPBasicAuthHandler() auth_handler.add_password(realm=realm, uri=base_url, @@ -61,25 +68,25 @@ class UTorrentClient(object): return self._action(params) def start(self, *hashes): - params = [('action', 'start'), ] + params = [('action', 'start')] for cur_hash in hashes: params.append(('hash', cur_hash)) return self._action(params) def stop(self, *hashes): - params = [('action', 'stop'), ] + params = [('action', 'stop')] for cur_hash in hashes: params.append(('hash', cur_hash)) return self._action(params) def pause(self, *hashes): - params = [('action', 'pause'), ] + params = [('action', 'pause')] for cur_hash in hashes: params.append(('hash', cur_hash)) return self._action(params) def forcestart(self, *hashes): - params = [('action', 'forcestart'), ] + params = [('action', 'forcestart')] for cur_hash in hashes: params.append(('hash', cur_hash)) return self._action(params) @@ -95,8 +102,8 @@ class UTorrentClient(object): def setprops(self, cur_hash, **kvpairs): params = [('action', 'setprops'), ('hash', cur_hash)] for k, v in iteritems(kvpairs): - params.append(("s", k)) - params.append(("v", v)) + params.append(('s', k)) + params.append(('v', v)) return self._action(params) @@ -125,13 +132,13 @@ class UTorrentClient(object): self._action(params) def remove(self, *hashes): - params = [('action', 'remove'), ] + params = [('action', 'remove')] for cur_hash in hashes: params.append(('hash', cur_hash)) return self._action(params) def removedata(self, *hashes): - params = [('action', 'removedata'), ] + params = [('action', 'removedata')] for cur_hash in hashes: params.append(('hash', cur_hash)) return self._action(params) diff --git a/libs/custom/utorrent/upload.py b/libs/custom/utorrent/upload.py index 03d58bcc..6aa829a4 100644 --- a/libs/custom/utorrent/upload.py +++ b/libs/custom/utorrent/upload.py @@ -1,6 +1,13 @@ # coding=utf-8 # code copied from http://www.doughellmann.com/PyMOTW/urllib2/ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import itertools import mimetypes from email.generator import _make_boundary as choose_boundary @@ -36,7 +43,7 @@ class MultiPartForm(object): # Build a list of lists, each containing "lines" of the # request. Each part is separated by a boundary string. # Once the list is built, return a string where each - # line is separated by '\r\n'. + # line is separated by '\r\n'. parts = [] part_boundary = '--' + self.boundary diff --git a/libs/util.py b/libs/util.py index 5ac9f943..354b14cf 100644 --- a/libs/util.py +++ b/libs/util.py @@ -1,4 +1,11 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import subprocess import sys import os diff --git a/nzbToCouchPotato.py b/nzbToCouchPotato.py index 9e6042c5..862e7f78 100755 --- a/nzbToCouchPotato.py +++ b/nzbToCouchPotato.py @@ -99,7 +99,7 @@ # # Enter Mount points as LocalPath,RemotePath and separate each pair with '|' # e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\ -#mountPoints= +#mountPoints= ## Extensions @@ -134,7 +134,7 @@ # subLanguages. # -# subLanguages. create a list of languages in the order you want them in your subtitles. +# subLanguages. create a list of languages in the order you want them in your subtitles. #subLanguages=eng,spa,fra # Transcode (0, 1). @@ -216,7 +216,7 @@ # ffmpeg output settings. #outputVideoExtension=.mp4 #outputVideoCodec=libx264 -#VideoCodecAllow= +#VideoCodecAllow= #outputVideoResolution=720:-1 #outputVideoPreset=medium #outputVideoFramerate=24 @@ -227,7 +227,7 @@ #outputAudioBitrate=640k #outputQualityPercent= #outputAudioTrack2Codec=libfaac -#AudioCodec2Allow= +#AudioCodec2Allow= #outputAudioTrack2Channels=2 #outputAudioTrack2Bitrate=160k #outputAudioOtherCodec=libmp3lame @@ -255,6 +255,13 @@ ### NZBGET POST-PROCESSING SCRIPT ### ############################################################################## +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import sys import nzbToMedia diff --git a/nzbToGamez.py b/nzbToGamez.py index 42d0a2f5..39023421 100755 --- a/nzbToGamez.py +++ b/nzbToGamez.py @@ -100,6 +100,13 @@ ### NZBGET POST-PROCESSING SCRIPT ### ############################################################################## +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import sys import nzbToMedia diff --git a/nzbToHeadPhones.py b/nzbToHeadPhones.py index 34103b0c..a1917f10 100755 --- a/nzbToHeadPhones.py +++ b/nzbToHeadPhones.py @@ -101,7 +101,7 @@ # # Enter Mount points as LocalPath,RemotePath and separate each pair with '|' # e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\ -#mountPoints= +#mountPoints= ## WakeOnLan @@ -122,6 +122,13 @@ ### NZBGET POST-PROCESSING SCRIPT ### ############################################################################## +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import sys import nzbToMedia diff --git a/nzbToLazyLibrarian.py b/nzbToLazyLibrarian.py index 0a26013b..dd760709 100755 --- a/nzbToLazyLibrarian.py +++ b/nzbToLazyLibrarian.py @@ -59,6 +59,19 @@ # set this to where your LazyLibrarian completed downloads are. #llwatch_dir= +# LazyLibrarian and NZBGet are a different system (0, 1). +# +# Enable to replace local path with the path as per the mountPoints below. +#llremote_path=0 + +## Network + +# Network Mount Points (Needed for remote path above) +# +# Enter Mount points as LocalPath,RemotePath and separate each pair with '|' +# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\ +#mountPoints= + ## Posix # Niceness for external tasks Extractor and Transcoder. @@ -95,6 +108,13 @@ ### NZBGET POST-PROCESSING SCRIPT ### ############################################################################## +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import sys import nzbToMedia diff --git a/nzbToLidarr.py b/nzbToLidarr.py index a9b78306..c38f5975 100755 --- a/nzbToLidarr.py +++ b/nzbToLidarr.py @@ -84,7 +84,7 @@ # # Enter Mount points as LocalPath,RemotePath and separate each pair with '|' # e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\ -#mountPoints= +#mountPoints= ## Extensions @@ -119,7 +119,7 @@ # subLanguages. # -# subLanguages. create a list of languages in the order you want them in your subtitles. +# subLanguages. create a list of languages in the order you want them in your subtitles. #subLanguages = eng,spa,fra # Transcode (0, 1). @@ -145,7 +145,7 @@ # outputVideoPath. # # outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable. -#outputVideoPath = +#outputVideoPath = # processOutput (0,1). # @@ -201,20 +201,20 @@ # ffmpeg output settings. #outputVideoExtension=.mp4 #outputVideoCodec=libx264 -#VideoCodecAllow = +#VideoCodecAllow = #outputVideoResolution=720:-1 #outputVideoPreset=medium #outputVideoFramerate=24 #outputVideoBitrate=800k #outputAudioCodec=libmp3lame -#AudioCodecAllow = +#AudioCodecAllow = #outputAudioBitrate=128k #outputQualityPercent = 0 #outputAudioTrack2Codec = libfaac -#AudioCodec2Allow = +#AudioCodec2Allow = #outputAudioTrack2Bitrate = 128k #outputAudioOtherCodec = libmp3lame -#AudioOtherCodecAllow = +#AudioOtherCodecAllow = #outputAudioOtherBitrate = 128k #outputSubtitleCodec = @@ -237,6 +237,13 @@ ### NZBGET POST-PROCESSING SCRIPT ### ############################################################################## +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import sys import nzbToMedia diff --git a/nzbToMedia.py b/nzbToMedia.py index 2ae2726c..12a72ae6 100755 --- a/nzbToMedia.py +++ b/nzbToMedia.py @@ -444,13 +444,18 @@ # set this to where your LazyLibrarian completed downloads are. #llwatch_dir= +# LazyLibrarian and NZBGet are a different system (0, 1). +# +# Enable to replace local path with the path as per the mountPoints below. +#llremote_path=0 + ## Network # Network Mount Points (Needed for remote path above) # # Enter Mount points as LocalPath,RemotePath and separate each pair with '|' # e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\ -#mountPoints= +#mountPoints= ## Extensions @@ -485,7 +490,7 @@ # subLanguages. # -# subLanguages. create a list of languages in the order you want them in your subtitles. +# subLanguages. create a list of languages in the order you want them in your subtitles. #subLanguages=eng,spa,fra # Transcode (0, 1). @@ -567,7 +572,7 @@ # ffmpeg output settings. #outputVideoExtension=.mp4 #outputVideoCodec=libx264 -#VideoCodecAllow= +#VideoCodecAllow= #outputVideoResolution=720:-1 #outputVideoPreset=medium #outputVideoFramerate=24 @@ -578,7 +583,7 @@ #outputAudioBitrate=640k #outputQualityPercent= #outputAudioTrack2Codec=libfaac -#AudioCodec2Allow= +#AudioCodec2Allow= #outputAudioTrack2Channels=2 #outputAudioTrack2Bitrate=160k #outputAudioOtherCodec=libmp3lame @@ -655,18 +660,23 @@ ### NZBGET POST-PROCESSING SCRIPT ### ############################################################################## -from __future__ import print_function - -import eol -eol.check() - -import cleanup -cleanup.clean(cleanup.FOLDER_STRUCTURE) +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) import datetime import os import sys +import eol +import cleanup + +eol.check() +cleanup.clean(cleanup.FOLDER_STRUCTURE) + import core from core import logger, main_db from core.auto_process import comics, games, movies, music, tv, books @@ -777,11 +787,11 @@ def process(input_directory, input_name=None, status=0, client_agent='manual', d ) except Exception: logger.error('Remote Path {0} is not valid for {1}:{2} Please set this to either 0 to disable or 1 to enable!'.format( - core.get('remote_path'), section_name, input_category)) + cfg.get('remote_path'), section_name, input_category)) input_name, input_directory = convert_to_ascii(input_name, input_directory) - if extract == 1: + if extract == 1 and not (status > 0 and core.NOEXTRACTFAILED): logger.debug('Checking for archives to extract in directory: {0}'.format(input_directory)) extract_files(input_directory) diff --git a/nzbToMylar.py b/nzbToMylar.py index 8fe166e3..e26cfe6d 100755 --- a/nzbToMylar.py +++ b/nzbToMylar.py @@ -92,7 +92,7 @@ # # Enter Mount points as LocalPath,RemotePath and separate each pair with '|' # e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\ -#mountPoints= +#mountPoints= ## WakeOnLan @@ -113,6 +113,13 @@ ### NZBGET POST-PROCESSING SCRIPT ### ############################################################################## +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import sys import nzbToMedia diff --git a/nzbToNzbDrone.py b/nzbToNzbDrone.py index f81e1e4c..680074cd 100755 --- a/nzbToNzbDrone.py +++ b/nzbToNzbDrone.py @@ -89,7 +89,7 @@ # # Enter Mount points as LocalPath,RemotePath and separate each pair with '|' # e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\ -#mountPoints= +#mountPoints= ## Extensions @@ -124,7 +124,7 @@ # subLanguages. # -# subLanguages. create a list of languages in the order you want them in your subtitles. +# subLanguages. create a list of languages in the order you want them in your subtitles. #subLanguages = eng,spa,fra # Transcode (0, 1). @@ -150,7 +150,7 @@ # outputVideoPath. # # outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable. -#outputVideoPath = +#outputVideoPath = # processOutput (0,1). # @@ -206,20 +206,20 @@ # ffmpeg output settings. #outputVideoExtension=.mp4 #outputVideoCodec=libx264 -#VideoCodecAllow = +#VideoCodecAllow = #outputVideoResolution=720:-1 #outputVideoPreset=medium #outputVideoFramerate=24 #outputVideoBitrate=800k #outputAudioCodec=libmp3lame -#AudioCodecAllow = +#AudioCodecAllow = #outputAudioBitrate=128k #outputQualityPercent = 0 #outputAudioTrack2Codec = libfaac -#AudioCodec2Allow = +#AudioCodec2Allow = #outputAudioTrack2Bitrate = 128k #outputAudioOtherCodec = libmp3lame -#AudioOtherCodecAllow = +#AudioOtherCodecAllow = #outputAudioOtherBitrate = 128k #outputSubtitleCodec = @@ -242,6 +242,13 @@ ### NZBGET POST-PROCESSING SCRIPT ### ############################################################################## +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import sys import nzbToMedia diff --git a/nzbToRadarr.py b/nzbToRadarr.py index f667685b..f75ca350 100755 --- a/nzbToRadarr.py +++ b/nzbToRadarr.py @@ -94,7 +94,7 @@ # # Enter Mount points as LocalPath,RemotePath and separate each pair with '|' # e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\ -#mountPoints= +#mountPoints= ## Extensions @@ -129,7 +129,7 @@ # subLanguages. # -# subLanguages. create a list of languages in the order you want them in your subtitles. +# subLanguages. create a list of languages in the order you want them in your subtitles. #subLanguages = eng,spa,fra # Transcode (0, 1). @@ -155,7 +155,7 @@ # outputVideoPath. # # outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable. -#outputVideoPath = +#outputVideoPath = # processOutput (0,1). # @@ -211,20 +211,20 @@ # ffmpeg output settings. #outputVideoExtension=.mp4 #outputVideoCodec=libx264 -#VideoCodecAllow = +#VideoCodecAllow = #outputVideoResolution=720:-1 #outputVideoPreset=medium #outputVideoFramerate=24 #outputVideoBitrate=800k #outputAudioCodec=libmp3lame -#AudioCodecAllow = +#AudioCodecAllow = #outputAudioBitrate=128k #outputQualityPercent = 0 #outputAudioTrack2Codec = libfaac -#AudioCodec2Allow = +#AudioCodec2Allow = #outputAudioTrack2Bitrate = 128k #outputAudioOtherCodec = libmp3lame -#AudioOtherCodecAllow = +#AudioOtherCodecAllow = #outputAudioOtherBitrate = 128k #outputSubtitleCodec = @@ -247,6 +247,13 @@ ### NZBGET POST-PROCESSING SCRIPT ### ############################################################################## +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import sys import nzbToMedia diff --git a/nzbToSickBeard.py b/nzbToSickBeard.py index 4d415fab..00f18077 100755 --- a/nzbToSickBeard.py +++ b/nzbToSickBeard.py @@ -100,7 +100,7 @@ # # Enter Mount points as LocalPath,RemotePath and separate each pair with '|' # e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\ -#mountPoints= +#mountPoints= ## Extensions @@ -135,7 +135,7 @@ # subLanguages. # -# subLanguages. create a list of languages in the order you want them in your subtitles. +# subLanguages. create a list of languages in the order you want them in your subtitles. #subLanguages=eng,spa,fra # Transcode (0, 1). @@ -217,7 +217,7 @@ # ffmpeg output settings. #outputVideoExtension=.mp4 #outputVideoCodec=libx264 -#VideoCodecAllow= +#VideoCodecAllow= #outputVideoResolution=720:-1 #outputVideoPreset=medium #outputVideoFramerate=24 @@ -228,7 +228,7 @@ #outputAudioBitrate=640k #outputQualityPercent= #outputAudioTrack2Codec=libfaac -#AudioCodec2Allow= +#AudioCodec2Allow= #outputAudioTrack2Channels=2 #outputAudioTrack2Bitrate=160k #outputAudioOtherCodec=libmp3lame @@ -256,6 +256,13 @@ ### NZBGET POST-PROCESSING SCRIPT ### ############################################################################## +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + import sys import nzbToMedia diff --git a/setup.py b/setup.py index b2f78439..bac19586 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,11 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- -from __future__ import absolute_import, print_function +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) import io import os.path @@ -11,7 +16,7 @@ from setuptools import setup def read(*names, **kwargs): with io.open( os.path.join(os.path.dirname(__file__), *names), - encoding=kwargs.get('encoding', 'utf8') + encoding=kwargs.get('encoding', 'utf8'), ) as fh: return fh.read() @@ -21,21 +26,21 @@ setup( version='12.0.10', license='GPLv3', description='Efficient on demand post processing', - long_description=""" + long_description=""" nzbToMedia ========== - + Efficient on demand post processing ----------------------------------- - + A PVR app needs to know when a download is ready for post-processing. There are two methods: - + 1. On-demand post-processing script (e.g. sabToSickBeard.py or nzbToMedia.py): A script in the downloader runs once at the end of the download job and notifies the PVR app that the download is complete. - + 2. Continuous folder scanning: The PVR app frequently polls download folder(s) for completed downloads. - + On-demand is superior, for several reasons: - + 1. The PVR app is notified only once, exactly when the download is ready for post-processing 2. The PVR app does not have to wait for the next poll interval before it starts processing 3. Continuous polling is not as efficient and is more stressful on low performance hardware @@ -46,7 +51,7 @@ setup( 8. On-demand scripts can be tweaked to allow for delays with slow hardware nzbToMedia is an on-demand post-processing script and was created out of a demand for more efficient post-processing on low-performance hardware. Many features have been added so higher performance hardware can benefit too. - + Many issues that users have with folder scanning can be fixed by switching to on-demand. A whole class of support issues can be eliminated by using nzbToMedia. """, author='Clinton Hall', diff --git a/tests/__init__.py b/tests/__init__.py index 1f47cffe..13e499a5 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1,8 @@ +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + __author__ = 'Justin' diff --git a/tests/test_initialize.py b/tests/test_initialize.py index 612261d3..9e672f4f 100755 --- a/tests/test_initialize.py +++ b/tests/test_initialize.py @@ -1,48 +1,52 @@ #! /usr/bin/env python -from __future__ import print_function -import datetime -import os -import sys +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) + +import core + def test_eol(): import eol eol.check() + def test_cleanup(): import cleanup cleanup.clean(cleanup.FOLDER_STRUCTURE) + def test_import_core(): - import core - from core import logger, main_db + pass + def test_import_core_auto_process(): - from core.auto_process import comics, games, movies, music, tv - from core.auto_process.common import ProcessResult + pass + def test_import_core_plugins(): - from core.plugins.downloaders.nzb.utils import get_nzoid - from core.plugins.plex import plex_update + pass + def test_import_core_user_scripts(): - from core.user_scripts import external_script + pass + def test_import_six(): - from six import text_type + pass + def test_import_core_utils(): - from core.utils import ( - char_replace, clean_dir, convert_to_ascii, - extract_files, get_dirs, get_download_info, - update_download_info_status, replace_links, - ) + pass -import core -from core import logger, main_db def test_initial(): core.initialize() del core.MYAPP + def test_core_parameters(): assert core.CHECK_MEDIA == 1 diff --git a/tests/test_transcoder.py b/tests/test_transcoder.py index 929e7f23..448ceeaf 100755 --- a/tests/test_transcoder.py +++ b/tests/test_transcoder.py @@ -1,14 +1,14 @@ #! /usr/bin/env python -from __future__ import print_function -import datetime -import os -import sys -import json -import time -import requests +from __future__ import ( + absolute_import, + division, + print_function, + unicode_literals, +) import core -from core import logger, transcoder +from core import transcoder + def test_transcoder_check(): - assert transcoder.is_video_good(core.TEST_FILE, 0) == True + assert transcoder.is_video_good(core.TEST_FILE, 0) is True diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..cb6b6642 --- /dev/null +++ b/tox.ini @@ -0,0 +1,146 @@ +; a generative tox configuration, see: https://tox.readthedocs.io/en/latest/config.html#generative-envlist + +[tox] +envlist = + clean, + check, + {py27, py35, py36, py37}, + report + +[testenv] +basepython = + py27: {env:TOXPYTHON:python2.7} + py35: {env:TOXPYTHON:python3.5} + py36: {env:TOXPYTHON:python3.6} + py37: {env:TOXPYTHON:python3.7} + {clean,check,report,codecov}: {env:TOXPYTHON:python3} +setenv = + PYTHONPATH={toxinidir}/tests + PYTHONUNBUFFERED=yes +passenv = + * +usedevelop = false +skip_install = true +deps = + pytest + pytest-travis-fold + pytest-cov + pywin32 ; sys.platform == 'win32' +commands = + {posargs:pytest --cov --cov-report=term-missing tests} + +[flake8] +max-line-length = 79 +max-doc-length = 79 +verbose = 2 +statistics = True +min-version = 2.7 +require-code = True +exclude = + .github/ + .tox/ + .pytest_cache/ + htmlcov/ + logs/ + libs/common + libs/win + libs/py2 +ignore = +; -- flake8 -- +; E501 line too long +; W505 doc line too long + E501, W505 + +; -- flake8-docstrings -- +; D100 Missing docstring in public module +; D101 Missing docstring in public class +; D102 Missing docstring in public method +; D103 Missing docstring in public function +; D104 Missing docstring in public package +; D105 Missing docstring in magic method +; D107 Missing docstring in __init__ +; D200 One-line docstring should fit on one line with quotes +; D202 No blank lines allowed after function docstring +; D205 1 blank line required between summary line and description +; D400 First line should end with a period +; D401 First line should be in imperative mood +; D402 First line should not be the function's "signature" + D100, D101, D102, D103, D104, D105, D107 + +; -- flake8-future-import -- +; x = 1 for missing, 5 for present +; FIx6 nested_scopes 2.2 +; FIx7 generators 2.3 +; FIx2 with_statement 2.6 +; FIx1 absolute_import 3.0 +; FIx0 division 3.0 +; FIx3 print_function 3.0 +; FIx4 unicode_literals 3.0 +; FIx5 generator_stop 3.7 +; ???? annotations 4.0 +; FI90 __future__ import does not exist + FI50, FI51, FI53, FI54 + +per-file-ignores = +; F401 imported but unused +; E402 module level import not at top of file + nzbTo*.py: E265, E266, E402 + TorrentToMedia.py: E402 + core/__init__.py: E402, F401 + core/utils/__init__.py: F401 + core/plugins/downloaders/configuration.py: F401 + core/plugins/downloaders/utils.py: F401 + libs/custom/synchronousdeluge/__init__.py: F401 + +[testenv:check] +deps = + flake8 + flake8-bugbear + flake8-commas + flake8-comprehensions + flake8-docstrings + flake8-future-import + flake8-quotes +skip_install = true +commands = +; ** PRIMARY TESTS ** +; Run flake8 tests (with plugins) using default test selections + flake8 +; ** SELECTIVE TESTS ** +; Run flake8 tests (with plugins) for specific optional codes defined below +; -- flake8 -- +; E123 closing bracket does not match indentation of opening bracket’s line +; E226 missing whitespace around arithmetic operator +; E241 multiple spaces after ‘,’ +; E242 tab after ‘,’ +; E704 multiple statements on one line +; W504 line break after binary operator +; W505 doc line too long +; -- flake8-bugbear -- +; B902 Invalid first argument used for instance method. +; B903 Data class should be immutable or use __slots__ to save memory. + flake8 --select=B902,B903,E123,E226,E241,E242,E704,W504,W505 + +[coverage:run] +omit = + libs/* + +[testenv:codecov] +deps = + codecov +skip_install = true +commands = + coverage xml --ignore-errors + codecov [] + +[testenv:report] +deps = coverage +skip_install = true +commands = + coverage report + coverage html + +[testenv:clean] +commands = coverage erase +skip_install = true +deps = coverage