From 96b4af1fea17f55b8fe63b58160c72a857ded386 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 29 Sep 2013 00:08:26 +0200 Subject: [PATCH 1/9] Hide first item in combined table --- couchpotato/static/style/settings.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/static/style/settings.css b/couchpotato/static/style/settings.css index 61d5239f..744531a9 100644 --- a/couchpotato/static/style/settings.css +++ b/couchpotato/static/style/settings.css @@ -542,7 +542,7 @@ line-height: 140%; cursor: help; } - .page .combined_table .head abbr.use, .page .combined_table .head abbr.automation_urls_use { + .page .combined_table .head abbr:first-child { display: none; } .page .combined_table .head abbr.host { From 91332e06e5f4a3261ca2338539b806e0e8fbd8cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20K=C3=A5berg?= Date: Sun, 29 Sep 2013 01:45:24 +0200 Subject: [PATCH 2/9] add option to create sub directory --- couchpotato/core/downloaders/blackhole/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/couchpotato/core/downloaders/blackhole/__init__.py b/couchpotato/core/downloaders/blackhole/__init__.py index 290e8d43..5de8ac76 100644 --- a/couchpotato/core/downloaders/blackhole/__init__.py +++ b/couchpotato/core/downloaders/blackhole/__init__.py @@ -35,6 +35,13 @@ config = [{ 'type': 'dropdown', 'values': [('usenet & torrents', 'both'), ('usenet', 'nzb'), ('torrent', 'torrent')], }, + { + 'name': 'create_subdir', + 'default': 0, + 'type': 'bool', + 'advanced': True, + 'description': 'Create a sub directory when adding torrent to blackhole.', + }, { 'name': 'manual', 'default': 0, From e38d68c01934316d37311f4d000efaebe4a843d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20K=C3=A5berg?= Date: Sun, 29 Sep 2013 01:45:50 +0200 Subject: [PATCH 3/9] actual code --- couchpotato/core/downloaders/blackhole/main.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/couchpotato/core/downloaders/blackhole/main.py b/couchpotato/core/downloaders/blackhole/main.py index 9a5a6217..e3e070cc 100644 --- a/couchpotato/core/downloaders/blackhole/main.py +++ b/couchpotato/core/downloaders/blackhole/main.py @@ -35,6 +35,15 @@ class Blackhole(Downloader): fullPath = os.path.join(directory, self.createFileName(data, filedata, movie)) + if self.conf('create_subdir'): + try: + new_path = os.path.splitext(fullPath)[0] + if not os.path.exists(new_path): + os.makedirs(new_path) + fullPath = os.path.join(new_path, self.createFileName(data, filedata, movie)) + except: + log.error('Couldnt create sub dir, reverting to old one: %s', fullPath) + try: if not os.path.isfile(fullPath): log.info('Downloading %s to %s.', (data.get('protocol'), fullPath)) From 201185f7e7e6833436be4db51b101944bb32d949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20K=C3=A5berg?= Date: Sun, 29 Sep 2013 01:49:51 +0200 Subject: [PATCH 4/9] better english damnit! --- couchpotato/core/downloaders/blackhole/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/core/downloaders/blackhole/__init__.py b/couchpotato/core/downloaders/blackhole/__init__.py index 5de8ac76..6b5279a1 100644 --- a/couchpotato/core/downloaders/blackhole/__init__.py +++ b/couchpotato/core/downloaders/blackhole/__init__.py @@ -40,7 +40,7 @@ config = [{ 'default': 0, 'type': 'bool', 'advanced': True, - 'description': 'Create a sub directory when adding torrent to blackhole.', + 'description': 'Create a sub directory when saving the .nzb (or .torrent).', }, { 'name': 'manual', From 1f2c2269e69f754332454352a3e516c2bd9ebe0a Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 29 Sep 2013 09:54:37 +0200 Subject: [PATCH 5/9] Ignore thumbs.db files and don't fail on single path split. fix #2265 --- couchpotato/core/plugins/scanner/main.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/plugins/scanner/main.py b/couchpotato/core/plugins/scanner/main.py index 9990bda7..58627093 100644 --- a/couchpotato/core/plugins/scanner/main.py +++ b/couchpotato/core/plugins/scanner/main.py @@ -25,7 +25,9 @@ class Scanner(Plugin): 'media': 314572800, # 300MB 'trailer': 1048576, # 1MB } - ignored_in_path = [os.path.sep + 'extracted' + os.path.sep, 'extracting', '_unpack', '_failed_', '_unknown_', '_exists_', '_failed_remove_', '_failed_rename_', '.appledouble', '.appledb', '.appledesktop', os.path.sep + '._', '.ds_store', 'cp.cpnfo'] #unpacking, smb-crap, hidden files + ignored_in_path = [os.path.sep + 'extracted' + os.path.sep, 'extracting', '_unpack', '_failed_', '_unknown_', '_exists_', '_failed_remove_', + '_failed_rename_', '.appledouble', '.appledb', '.appledesktop', os.path.sep + '._', '.ds_store', 'cp.cpnfo', + 'thumbs.db', 'ehthumbs.db', 'desktop.ini'] #unpacking, smb-crap, hidden files ignore_names = ['extract', 'extracting', 'extracted', 'movie', 'movies', 'film', 'films', 'download', 'downloads', 'video_ts', 'audio_ts', 'bdmv', 'certificate'] extensions = { 'movie': ['mkv', 'wmv', 'avi', 'mpg', 'mpeg', 'mp4', 'm2ts', 'iso', 'img', 'mdf', 'ts', 'm4v'], @@ -747,8 +749,10 @@ class Scanner(Plugin): identifier = file_path.replace(folder, '').lstrip(os.path.sep) # root folder identifier = os.path.splitext(identifier)[0] # ext - path_split = splitString(identifier, os.path.sep) - identifier = path_split[-2] if len(path_split) > 1 and len(path_split[-2]) > len(path_split[-1]) else path_split[-1] # Only get filename + try: + path_split = splitString(identifier, os.path.sep) + identifier = path_split[-2] if len(path_split) > 1 and len(path_split[-2]) > len(path_split[-1]) else path_split[-1] # Only get filename + except: pass if exclude_filename: identifier = identifier[:len(identifier) - len(os.path.split(identifier)[-1])] From 99c899ea3a22dfa7cedbbbb3bb9629d2d4956c51 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 29 Sep 2013 10:06:12 +0200 Subject: [PATCH 6/9] Proper variable naming --- .../core/downloaders/blackhole/main.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/couchpotato/core/downloaders/blackhole/main.py b/couchpotato/core/downloaders/blackhole/main.py index e3e070cc..854860cd 100644 --- a/couchpotato/core/downloaders/blackhole/main.py +++ b/couchpotato/core/downloaders/blackhole/main.py @@ -33,26 +33,27 @@ class Blackhole(Downloader): log.error('No nzb/torrent available: %s', data.get('url')) return False - fullPath = os.path.join(directory, self.createFileName(data, filedata, movie)) + file_name = self.createFileName(data, filedata, movie) + full_path = os.path.join(directory, file_name) if self.conf('create_subdir'): try: - new_path = os.path.splitext(fullPath)[0] + new_path = os.path.splitext(full_path)[0] if not os.path.exists(new_path): os.makedirs(new_path) - fullPath = os.path.join(new_path, self.createFileName(data, filedata, movie)) + full_path = os.path.join(new_path, file_name) except: - log.error('Couldnt create sub dir, reverting to old one: %s', fullPath) + log.error('Couldnt create sub dir, reverting to old one: %s', full_path) try: - if not os.path.isfile(fullPath): - log.info('Downloading %s to %s.', (data.get('protocol'), fullPath)) - with open(fullPath, 'wb') as f: + if not os.path.isfile(full_path): + log.info('Downloading %s to %s.', (data.get('protocol'), full_path)) + with open(full_path, 'wb') as f: f.write(filedata) - os.chmod(fullPath, Env.getPermission('file')) + os.chmod(full_path, Env.getPermission('file')) return True else: - log.info('File %s already exists.', fullPath) + log.info('File %s already exists.', full_path) return True except: From ae4e15286a12ea2b4da469bd14c19abcefec5296 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 29 Sep 2013 12:17:09 +0200 Subject: [PATCH 7/9] Don't try to loop over None. fix #2268 --- couchpotato/core/plugins/manage/main.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/couchpotato/core/plugins/manage/main.py b/couchpotato/core/plugins/manage/main.py index 702b1293..e8ccaf7e 100644 --- a/couchpotato/core/plugins/manage/main.py +++ b/couchpotato/core/plugins/manage/main.py @@ -222,9 +222,10 @@ class Manage(Plugin): groups = fireEvent('scanner.scan', folder = folder, files = files, single = True) - for group in groups.itervalues(): - if group['library'] and group['library'].get('identifier'): - fireEvent('release.add', group = group) + if groups: + for group in groups.itervalues(): + if group['library'] and group['library'].get('identifier'): + fireEvent('release.add', group = group) def getDiskSpace(self): From 333abd248663969cfdaab7486281e127f4712bcd Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 29 Sep 2013 13:25:10 +0200 Subject: [PATCH 8/9] Custom plugin folder outside source. fix #2076 --- couchpotato/core/loader.py | 46 ++++++++++++--------- couchpotato/core/plugins/custom/__init__.py | 6 +++ couchpotato/core/plugins/custom/main.py | 21 ++++++++++ libs/importlib/__init__.py | 38 +++++++++++++++++ 4 files changed, 92 insertions(+), 19 deletions(-) create mode 100644 couchpotato/core/plugins/custom/__init__.py create mode 100644 couchpotato/core/plugins/custom/main.py create mode 100644 libs/importlib/__init__.py diff --git a/couchpotato/core/loader.py b/couchpotato/core/loader.py index 9362bb8c..6ceee4ed 100644 --- a/couchpotato/core/loader.py +++ b/couchpotato/core/loader.py @@ -1,6 +1,8 @@ from couchpotato.core.event import fireEvent from couchpotato.core.logger import CPLog +from importlib import import_module import os +import sys import traceback log = CPLog(__name__) @@ -11,17 +13,6 @@ class Loader(object): providers = {} modules = {} - def addPath(self, root, base_path, priority, recursive = False): - for filename in os.listdir(os.path.join(root, *base_path)): - path = os.path.join(os.path.join(root, *base_path), filename) - if os.path.isdir(path) and filename[:2] != '__': - if u'__init__.py' in os.listdir(path): - new_base_path = ''.join(s + '.' for s in base_path) + filename - self.paths[new_base_path.replace('.', '_')] = (priority, new_base_path, path) - - if recursive: - self.addPath(root, base_path + [filename], priority, recursive = True) - def preload(self, root = ''): core = os.path.join(root, 'couchpotato', 'core') @@ -38,6 +29,13 @@ class Loader(object): # Add media to loader self.addPath(root, ['couchpotato', 'core', 'media'], 25, recursive = True) + # Add custom plugin folder + from couchpotato.environment import Env + custom_plugin_dir = os.path.join(Env.get('data_dir'), 'custom_plugins') + sys.path.insert(0, custom_plugin_dir) + self.paths['custom_plugins'] = (30, '', custom_plugin_dir) + + # Loop over all paths and add to module list for plugin_type, plugin_tuple in self.paths.iteritems(): priority, module, dir_name = plugin_tuple self.addFromDir(plugin_type, priority, module, dir_name) @@ -45,8 +43,9 @@ class Loader(object): def run(self): did_save = 0 - for priority in self.modules: + for priority in sorted(self.modules): for module_name, plugin in sorted(self.modules[priority].iteritems()): + # Load module try: if plugin.get('name')[:2] == '__': @@ -55,7 +54,6 @@ class Loader(object): m = self.loadModule(module_name) if m is None: continue - m = getattr(m, plugin.get('name')) log.info('Loading %s: %s', (plugin['type'], plugin['name'])) @@ -77,10 +75,23 @@ class Loader(object): if did_save: fireEvent('settings.save') + def addPath(self, root, base_path, priority, recursive = False): + root_path = os.path.join(root, *base_path) + for filename in os.listdir(root_path): + path = os.path.join(root_path, filename) + if os.path.isdir(path) and filename[:2] != '__': + if u'__init__.py' in os.listdir(path): + new_base_path = ''.join(s + '.' for s in base_path) + filename + self.paths[new_base_path.replace('.', '_')] = (priority, new_base_path, path) + + if recursive: + self.addPath(root, base_path + [filename], priority, recursive = True) + def addFromDir(self, plugin_type, priority, module, dir_name): # Load dir module - self.addModule(priority, plugin_type, module, os.path.basename(dir_name)) + if module and len(module) > 0: + self.addModule(priority, plugin_type, module, os.path.basename(dir_name)) for name in os.listdir(dir_name): if os.path.isdir(os.path.join(dir_name, name)) and name != 'static' and os.path.isfile(os.path.join(dir_name, name, '__init__.py')): @@ -123,6 +134,7 @@ class Loader(object): if not self.modules.get(priority): self.modules[priority] = {} + module = module.lstrip('.') self.modules[priority][module] = { 'priority': priority, 'module': module, @@ -132,11 +144,7 @@ class Loader(object): def loadModule(self, name): try: - m = __import__(name) - splitted = name.split('.') - for sub in splitted[1:-1]: - m = getattr(m, sub) - return m + return import_module(name) except ImportError: log.debug('Skip loading module plugin %s: %s', (name, traceback.format_exc())) return None diff --git a/couchpotato/core/plugins/custom/__init__.py b/couchpotato/core/plugins/custom/__init__.py new file mode 100644 index 00000000..573cd99f --- /dev/null +++ b/couchpotato/core/plugins/custom/__init__.py @@ -0,0 +1,6 @@ +from .main import Custom + +def start(): + return Custom() + +config = [] diff --git a/couchpotato/core/plugins/custom/main.py b/couchpotato/core/plugins/custom/main.py new file mode 100644 index 00000000..a15c915c --- /dev/null +++ b/couchpotato/core/plugins/custom/main.py @@ -0,0 +1,21 @@ +from couchpotato.core.event import addEvent +from couchpotato.core.logger import CPLog +from couchpotato.core.plugins.base import Plugin +from couchpotato.environment import Env +import os + +log = CPLog(__name__) + + +class Custom(Plugin): + + def __init__(self): + addEvent('app.load', self.createStructure) + + def createStructure(self): + + custom_dir = os.path.join(Env.get('data_dir'), 'custom_plugins') + + if not os.path.isdir(custom_dir): + self.makeDir(custom_dir) + self.createFile(os.path.join(custom_dir, '__init__.py'), '# Don\'t remove this file') diff --git a/libs/importlib/__init__.py b/libs/importlib/__init__.py new file mode 100644 index 00000000..ad31a1ac --- /dev/null +++ b/libs/importlib/__init__.py @@ -0,0 +1,38 @@ +"""Backport of importlib.import_module from 3.x.""" +# While not critical (and in no way guaranteed!), it would be nice to keep this +# code compatible with Python 2.3. +import sys + +def _resolve_name(name, package, level): + """Return the absolute name of the module to be imported.""" + if not hasattr(package, 'rindex'): + raise ValueError("'package' not set to a string") + dot = len(package) + for x in xrange(level, 1, -1): + try: + dot = package.rindex('.', 0, dot) + except ValueError: + raise ValueError("attempted relative import beyond top-level " + "package") + return "%s.%s" % (package[:dot], name) + + +def import_module(name, package=None): + """Import a module. + + The 'package' argument is required when performing a relative import. It + specifies the package to use as the anchor point from which to resolve the + relative import to an absolute import. + + """ + if name.startswith('.'): + if not package: + raise TypeError("relative imports require the 'package' argument") + level = 0 + for character in name: + if character != '.': + break + level += 1 + name = _resolve_name(name[level:], package, level) + __import__(name) + return sys.modules[name] From e7aa91b3e1f5cc28c5d678b7a7dfe6b038d44ea8 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 29 Sep 2013 13:44:52 +0200 Subject: [PATCH 9/9] Don't try to use custom_plugins when folder doesn't exist --- couchpotato/core/loader.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/couchpotato/core/loader.py b/couchpotato/core/loader.py index 6ceee4ed..c14b55bd 100644 --- a/couchpotato/core/loader.py +++ b/couchpotato/core/loader.py @@ -32,8 +32,9 @@ class Loader(object): # Add custom plugin folder from couchpotato.environment import Env custom_plugin_dir = os.path.join(Env.get('data_dir'), 'custom_plugins') - sys.path.insert(0, custom_plugin_dir) - self.paths['custom_plugins'] = (30, '', custom_plugin_dir) + if os.path.isdir(custom_plugin_dir): + sys.path.insert(0, custom_plugin_dir) + self.paths['custom_plugins'] = (30, '', custom_plugin_dir) # Loop over all paths and add to module list for plugin_type, plugin_tuple in self.paths.iteritems():