Browse Source

Code cleanup

pull/2742/merge
Ruud 11 years ago
parent
commit
799299c7cc
  1. 8
      CouchPotato.py
  2. 26
      couchpotato/__init__.py
  3. 10
      couchpotato/api.py
  4. 1
      couchpotato/core/_base/_core/__init__.py
  5. 1
      couchpotato/core/_base/clientscript/__init__.py
  6. 6
      couchpotato/core/_base/clientscript/main.py
  7. 1
      couchpotato/core/_base/desktop/__init__.py
  8. 1
      couchpotato/core/_base/scheduler/__init__.py
  9. 1
      couchpotato/core/_base/updater/__init__.py
  10. 16
      couchpotato/core/_base/updater/main.py
  11. 1
      couchpotato/core/downloaders/blackhole/__init__.py
  12. 1
      couchpotato/core/downloaders/deluge/__init__.py
  13. 1
      couchpotato/core/downloaders/deluge/main.py
  14. 1
      couchpotato/core/downloaders/nzbget/__init__.py
  15. 6
      couchpotato/core/downloaders/nzbget/main.py
  16. 1
      couchpotato/core/downloaders/nzbvortex/__init__.py
  17. 8
      couchpotato/core/downloaders/nzbvortex/main.py
  18. 1
      couchpotato/core/downloaders/pneumatic/__init__.py
  19. 12
      couchpotato/core/downloaders/pneumatic/main.py
  20. 1
      couchpotato/core/downloaders/rtorrent/__init__.py
  21. 1
      couchpotato/core/downloaders/rtorrent/main.py
  22. 1
      couchpotato/core/downloaders/sabnzbd/__init__.py
  23. 1
      couchpotato/core/downloaders/synology/__init__.py
  24. 1
      couchpotato/core/downloaders/synology/main.py
  25. 1
      couchpotato/core/downloaders/transmission/__init__.py
  26. 1
      couchpotato/core/downloaders/utorrent/__init__.py
  27. 18
      couchpotato/core/event.py
  28. 14
      couchpotato/core/helpers/encoding.py
  29. 1
      couchpotato/core/helpers/request.py
  30. 3
      couchpotato/core/helpers/rss.py
  31. 42
      couchpotato/core/helpers/variable.py
  32. 3
      couchpotato/core/logger.py
  33. 4
      couchpotato/core/media/__init__.py
  34. 1
      couchpotato/core/media/_base/media/__init__.py
  35. 3
      couchpotato/core/media/_base/media/main.py
  36. 1
      couchpotato/core/media/_base/search/__init__.py
  37. 1
      couchpotato/core/media/_base/searcher/__init__.py
  38. 2
      couchpotato/core/media/_base/searcher/base.py
  39. 1
      couchpotato/core/media/movie/_base/__init__.py
  40. 1
      couchpotato/core/media/movie/_base/main.py
  41. 1
      couchpotato/core/media/movie/library/movie/__init__.py
  42. 2
      couchpotato/core/media/movie/library/movie/main.py
  43. 1
      couchpotato/core/media/movie/searcher/__init__.py
  44. 4
      couchpotato/core/media/movie/searcher/main.py
  45. 1
      couchpotato/core/media/movie/suggestion/__init__.py
  46. 1
      couchpotato/core/migration/versions/002_Movie_category.py
  47. 1
      couchpotato/core/notifications/boxcar/__init__.py
  48. 1
      couchpotato/core/notifications/core/__init__.py
  49. 1
      couchpotato/core/notifications/core/main.py
  50. 1
      couchpotato/core/notifications/email/__init__.py
  51. 2
      couchpotato/core/notifications/email/main.py
  52. 1
      couchpotato/core/notifications/growl/__init__.py
  53. 2
      couchpotato/core/notifications/growl/main.py
  54. 1
      couchpotato/core/notifications/nmj/__init__.py
  55. 7
      couchpotato/core/notifications/nmj/main.py
  56. 1
      couchpotato/core/notifications/notifymyandroid/__init__.py
  57. 1
      couchpotato/core/notifications/notifymywp/__init__.py
  58. 3
      couchpotato/core/notifications/notifymywp/main.py
  59. 1
      couchpotato/core/notifications/plex/__init__.py
  60. 7
      couchpotato/core/notifications/plex/main.py
  61. 1
      couchpotato/core/notifications/prowl/__init__.py
  62. 1
      couchpotato/core/notifications/pushalot/__init__.py
  63. 1
      couchpotato/core/notifications/pushalot/main.py
  64. 1
      couchpotato/core/notifications/pushbullet/__init__.py
  65. 1
      couchpotato/core/notifications/pushover/__init__.py
  66. 1
      couchpotato/core/notifications/synoindex/__init__.py
  67. 2
      couchpotato/core/notifications/synoindex/main.py
  68. 1
      couchpotato/core/notifications/toasty/__init__.py
  69. 1
      couchpotato/core/notifications/toasty/main.py
  70. 1
      couchpotato/core/notifications/trakt/__init__.py
  71. 1
      couchpotato/core/notifications/trakt/main.py
  72. 1
      couchpotato/core/notifications/twitter/__init__.py
  73. 2
      couchpotato/core/notifications/twitter/main.py
  74. 1
      couchpotato/core/notifications/xbmc/__init__.py
  75. 3
      couchpotato/core/notifications/xbmc/main.py
  76. 1
      couchpotato/core/notifications/xmpp/__init__.py
  77. 1
      couchpotato/core/plugins/automation/__init__.py
  78. 9
      couchpotato/core/plugins/base.py
  79. 1
      couchpotato/core/plugins/browser/__init__.py
  80. 1
      couchpotato/core/plugins/category/__init__.py
  81. 2
      couchpotato/core/plugins/category/main.py
  82. 1
      couchpotato/core/plugins/custom/__init__.py
  83. 1
      couchpotato/core/plugins/dashboard/__init__.py
  84. 2
      couchpotato/core/plugins/dashboard/main.py
  85. 1
      couchpotato/core/plugins/file/__init__.py
  86. 1
      couchpotato/core/plugins/file/main.py
  87. 1
      couchpotato/core/plugins/log/__init__.py
  88. 2
      couchpotato/core/plugins/log/main.py
  89. 1
      couchpotato/core/plugins/manage/__init__.py
  90. 1
      couchpotato/core/plugins/manage/main.py
  91. 1
      couchpotato/core/plugins/profile/__init__.py
  92. 2
      couchpotato/core/plugins/profile/main.py
  93. 1
      couchpotato/core/plugins/quality/__init__.py
  94. 1
      couchpotato/core/plugins/release/__init__.py
  95. 15
      couchpotato/core/plugins/release/main.py
  96. 4
      couchpotato/core/plugins/renamer/__init__.py
  97. 13
      couchpotato/core/plugins/renamer/main.py
  98. 1
      couchpotato/core/plugins/scanner/__init__.py
  99. 6
      couchpotato/core/plugins/scanner/main.py
  100. 1
      couchpotato/core/plugins/score/__init__.py

8
CouchPotato.py

@ -132,14 +132,14 @@ if __name__ == '__main__':
pass
except SystemExit:
raise
except socket.error as (nr, msg):
except socket.error as e:
# log when socket receives SIGINT, but continue.
# previous code would have skipped over other types of IO errors too.
if nr != 4:
try:
l.log.critical(traceback.format_exc())
except:
print traceback.format_exc()
print(traceback.format_exc())
raise
except:
try:
@ -148,7 +148,7 @@ if __name__ == '__main__':
if l:
l.log.critical(traceback.format_exc())
else:
print traceback.format_exc()
print(traceback.format_exc())
except:
print traceback.format_exc()
print(traceback.format_exc())
raise

26
couchpotato/__init__.py

@ -9,13 +9,12 @@ import os
import time
import traceback
log = CPLog(__name__)
log = CPLog(__name__)
views = {}
template_loader = template.Loader(os.path.join(os.path.dirname(__file__), 'templates'))
class BaseHandler(RequestHandler):
def get_current_user(self):
@ -27,6 +26,7 @@ class BaseHandler(RequestHandler):
else: # Login when no username or password are set
return True
# Main web handler
class WebHandler(BaseHandler):
@ -43,9 +43,11 @@ class WebHandler(BaseHandler):
log.error("Failed doing web request '%s': %s", (route, traceback.format_exc()))
self.write({'success': False, 'error': 'Failed returning results'})
def addView(route, func, static = False):
views[route] = func
def get_session(engine = None):
return Env.getSession(engine)
@ -55,6 +57,7 @@ def index():
return template_loader.load('index.html').generate(sep = os.sep, fireEvent = fireEvent, Env = Env)
addView('', index)
# API docs
def apiDocs():
routes = []
@ -70,21 +73,22 @@ def apiDocs():
addView('docs', apiDocs)
# Make non basic auth option to get api key
class KeyHandler(RequestHandler):
def get(self, *args, **kwargs):
api = None
api_key = None
try:
username = Env.setting('username')
password = Env.setting('password')
if (self.get_argument('u') == md5(username) or not username) and (self.get_argument('p') == password or not password):
api = Env.setting('api_key')
api_key = Env.setting('api_key')
self.write({
'success': api is not None,
'api_key': api
'success': api_key is not None,
'api_key': api_key
})
except:
log.error('Failed doing key request: %s', (traceback.format_exc()))
@ -102,20 +106,21 @@ class LoginHandler(BaseHandler):
def post(self, *args, **kwargs):
api = None
api_key = None
username = Env.setting('username')
password = Env.setting('password')
if (self.get_argument('username') == username or not username) and (md5(self.get_argument('password')) == password or not password):
api = Env.setting('api_key')
api_key = Env.setting('api_key')
if api:
if api_key:
remember_me = tryInt(self.get_argument('remember_me', default = 0))
self.set_secure_cookie('user', api, expires_days = 30 if remember_me > 0 else None)
self.set_secure_cookie('user', api_key, expires_days = 30 if remember_me > 0 else None)
self.redirect(Env.get('web_base'))
class LogoutHandler(BaseHandler):
def get(self, *args, **kwargs):
@ -136,4 +141,3 @@ def page_not_found(rh):
rh.set_status(404)
rh.write('Wrong API key used')

10
couchpotato/api.py

@ -20,6 +20,7 @@ api_nonblock = {}
api_docs = {}
api_docs_missing = []
def run_async(func):
@wraps(func)
def async_func(*args, **kwargs):
@ -29,6 +30,7 @@ def run_async(func):
return async_func
# NonBlock API handler
class NonBlockHandler(RequestHandler):
@ -61,6 +63,7 @@ class NonBlockHandler(RequestHandler):
self.stopper = None
def addNonBlockApiView(route, func_tuple, docs = None, **kwargs):
api_nonblock[route] = func_tuple
@ -69,6 +72,7 @@ def addNonBlockApiView(route, func_tuple, docs = None, **kwargs):
else:
api_docs_missing.append(route)
# Blocking API handler
class ApiHandler(RequestHandler):
@ -98,11 +102,12 @@ class ApiHandler(RequestHandler):
@run_async
def run_handler(callback):
try:
result = api[route](**kwargs)
callback(result)
res = api[route](**kwargs)
callback(res)
except:
log.error('Failed doing api request "%s": %s', (route, traceback.format_exc()))
callback({'success': False, 'error': 'Failed returning results'})
result = yield tornado.gen.Task(run_handler)
# Check JSONP callback
@ -122,6 +127,7 @@ class ApiHandler(RequestHandler):
api_locks[route].release()
def addApiView(route, func, static = False, docs = None, **kwargs):
if static: func(route)

1
couchpotato/core/_base/_core/__init__.py

@ -1,6 +1,7 @@
from .main import Core
from uuid import uuid4
def start():
return Core()

1
couchpotato/core/_base/clientscript/__init__.py

@ -1,5 +1,6 @@
from .main import ClientScript
def start():
return ClientScript()

6
couchpotato/core/_base/clientscript/main.py

@ -53,9 +53,9 @@ class ClientScript(Plugin):
}
urls = {'style': {}, 'script': {}, }
minified = {'style': {}, 'script': {}, }
paths = {'style': {}, 'script': {}, }
urls = {'style': {}, 'script': {}}
minified = {'style': {}, 'script': {}}
paths = {'style': {}, 'script': {}}
comment = {
'style': '/*** %s:%d ***/\n',
'script': '// %s:%d\n'

1
couchpotato/core/_base/desktop/__init__.py

@ -1,5 +1,6 @@
from .main import Desktop
def start():
return Desktop()

1
couchpotato/core/_base/scheduler/__init__.py

@ -1,5 +1,6 @@
from .main import Scheduler
def start():
return Scheduler()

1
couchpotato/core/_base/updater/__init__.py

@ -2,6 +2,7 @@ from .main import Updater
from couchpotato.environment import Env
import os
def start():
return Updater()

16
couchpotato/core/_base/updater/main.py

@ -151,6 +151,9 @@ class BaseUpdater(Plugin):
'branch': self.branch,
}
def getVersion(self):
pass
def check(self):
pass
@ -179,7 +182,6 @@ class BaseUpdater(Plugin):
log.error('Couldn\'t remove empty directory %s: %s', (full_path, traceback.format_exc()))
class GitUpdater(BaseUpdater):
def __init__(self, git_command):
@ -214,7 +216,7 @@ class GitUpdater(BaseUpdater):
'date': output.getDate(),
'type': 'git',
}
except Exception, e:
except Exception as e:
log.error('Failed using GIT updater, running from source, you need to have GIT installed. %s', e)
return 'No GIT'
@ -250,7 +252,6 @@ class GitUpdater(BaseUpdater):
return False
class SourceUpdater(BaseUpdater):
def __init__(self):
@ -276,9 +277,9 @@ class SourceUpdater(BaseUpdater):
# Extract
if download_data.get('type') == 'zip':
zip = zipfile.ZipFile(destination)
zip.extractall(extracted_path)
zip.close()
zip_file = zipfile.ZipFile(destination)
zip_file.extractall(extracted_path)
zip_file.close()
else:
tar = tarfile.open(destination)
tar.extractall(path = extracted_path)
@ -345,7 +346,6 @@ class SourceUpdater(BaseUpdater):
return True
def removeDir(self, path):
try:
if os.path.isdir(path):
@ -366,7 +366,7 @@ class SourceUpdater(BaseUpdater):
self.version = output
self.version['type'] = 'source'
self.version['repr'] = 'source:(%s:%s % s) %s (%s)' % (self.repo_user, self.repo_name, self.branch, output.get('hash', '')[:8], datetime.fromtimestamp(output.get('date', 0)))
except Exception, e:
except Exception as e:
log.error('Failed using source updater. %s', e)
return {}

1
couchpotato/core/downloaders/blackhole/__init__.py

@ -1,6 +1,7 @@
from .main import Blackhole
from couchpotato.core.helpers.variable import getDownloadDir
def start():
return Blackhole()

1
couchpotato/core/downloaders/deluge/__init__.py

@ -1,5 +1,6 @@
from .main import Deluge
def start():
return Deluge()

1
couchpotato/core/downloaders/deluge/main.py

@ -157,6 +157,7 @@ class Deluge(Downloader):
log.debug('Requesting Deluge to remove the torrent %s%s.', (release_download['name'], ' and cleanup the downloaded files' if delete_files else ''))
return self.drpc.remove_torrent(release_download['id'], remove_local_data = delete_files)
class DelugeRPC(object):
host = 'localhost'

1
couchpotato/core/downloaders/nzbget/__init__.py

@ -1,5 +1,6 @@
from .main import NZBGet
def start():
return NZBGet()

6
couchpotato/core/downloaders/nzbget/main.py

@ -42,7 +42,7 @@ class NZBGet(Downloader):
except socket.error:
log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.')
return False
except xmlrpclib.ProtocolError, e:
except xmlrpclib.ProtocolError as e:
if e.errcode == 401:
log.error('Password is incorrect.')
else:
@ -83,7 +83,7 @@ class NZBGet(Downloader):
except socket.error:
log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.')
return []
except xmlrpclib.ProtocolError, e:
except xmlrpclib.ProtocolError as e:
if e.errcode == 401:
log.error('Password is incorrect.')
else:
@ -169,7 +169,7 @@ class NZBGet(Downloader):
except socket.error:
log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.')
return False
except xmlrpclib.ProtocolError, e:
except xmlrpclib.ProtocolError as e:
if e.errcode == 401:
log.error('Password is incorrect.')
else:

1
couchpotato/core/downloaders/nzbvortex/__init__.py

@ -1,5 +1,6 @@
from .main import NZBVortex
def start():
return NZBVortex()

8
couchpotato/core/downloaders/nzbvortex/main.py

@ -62,7 +62,7 @@ class NZBVortex(Downloader):
'name': nzb['uiTitle'],
'status': status,
'original_status': nzb['state'],
'timeleft':-1,
'timeleft': -1,
'folder': sp(nzb['destinationPath']),
})
@ -102,7 +102,6 @@ class NZBVortex(Downloader):
log.error('Login failed, please check you api-key')
return False
def call(self, call, parameters = None, repeat = False, auth = True, *args, **kwargs):
# Login first
@ -123,7 +122,7 @@ class NZBVortex(Downloader):
if data:
return json.loads(data)
except URLError, e:
except URLError as e:
if hasattr(e, 'code') and e.code == 403:
# Try login and do again
if not repeat:
@ -145,7 +144,7 @@ class NZBVortex(Downloader):
try:
data = self.urlopen(url, show_error = False)
self.api_level = float(json.loads(data).get('apilevel'))
except URLError, e:
except URLError as e:
if hasattr(e, 'code') and e.code == 403:
log.error('This version of NZBVortex isn\'t supported. Please update to 2.8.6 or higher')
else:
@ -175,6 +174,7 @@ class HTTPSConnection(httplib.HTTPSConnection):
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version = ssl.PROTOCOL_TLSv1)
class HTTPSHandler(urllib2.HTTPSHandler):
def https_open(self, req):
return self.do_open(HTTPSConnection, req)

1
couchpotato/core/downloaders/pneumatic/__init__.py

@ -1,5 +1,6 @@
from .main import Pneumatic
def start():
return Pneumatic()

12
couchpotato/core/downloaders/pneumatic/main.py

@ -26,26 +26,26 @@ class Pneumatic(Downloader):
log.error('No nzb available!')
return False
fullPath = os.path.join(directory, self.createFileName(data, filedata, media))
full_path = os.path.join(directory, self.createFileName(data, filedata, media))
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)
nzb_name = self.createNzbName(data, media)
strm_path = os.path.join(directory, nzb_name)
strm_file = open(strm_path + '.strm', 'wb')
strmContent = self.strm_syntax % (fullPath, nzb_name)
strmContent = self.strm_syntax % (full_path, nzb_name)
strm_file.write(strmContent)
strm_file.close()
return self.downloadReturnId('')
else:
log.info('File %s already exists.', fullPath)
log.info('File %s already exists.', full_path)
return self.downloadReturnId('')
except:

1
couchpotato/core/downloaders/rtorrent/__init__.py

@ -1,5 +1,6 @@
from .main import rTorrent
def start():
return rTorrent()

1
couchpotato/core/downloaders/rtorrent/main.py

@ -111,7 +111,6 @@ class rTorrent(Downloader):
if self.conf('label'):
torrent_params['label'] = self.conf('label')
if not filedata and data.get('protocol') == 'torrent':
log.error('Failed sending torrent, no data')
return False

1
couchpotato/core/downloaders/sabnzbd/__init__.py

@ -1,5 +1,6 @@
from .main import Sabnzbd
def start():
return Sabnzbd()

1
couchpotato/core/downloaders/synology/__init__.py

@ -1,5 +1,6 @@
from .main import Synology
def start():
return Synology()

1
couchpotato/core/downloaders/synology/main.py

@ -65,6 +65,7 @@ class Synology(Downloader):
return super(Synology, self).isEnabled(manual, data) and\
((self.conf('use_for') in for_protocol))
class SynologyRPC(object):
"""SynologyRPC lite library"""

1
couchpotato/core/downloaders/transmission/__init__.py

@ -1,5 +1,6 @@
from .main import Transmission
def start():
return Transmission()

1
couchpotato/core/downloaders/utorrent/__init__.py

@ -1,5 +1,6 @@
from .main import uTorrent
def start():
return uTorrent()

18
couchpotato/core/event.py

@ -7,6 +7,7 @@ import traceback
log = CPLog(__name__)
events = {}
def runHandler(name, handler, *args, **kwargs):
try:
return handler(*args, **kwargs)
@ -14,6 +15,7 @@ def runHandler(name, handler, *args, **kwargs):
from couchpotato.environment import Env
log.error('Error in event "%s", that wasn\'t caught: %s%s', (name, traceback.format_exc(), Env.all() if not Env.get('dev') else ''))
def addEvent(name, handler, priority = 100):
if not events.get(name):
@ -48,12 +50,14 @@ def addEvent(name, handler, priority = 100):
'priority': priority,
})
def removeEvent(name, handler):
e = events[name]
e -= handler
def fireEvent(name, *args, **kwargs):
if not events.has_key(name): return
if name not in events: return
#log.debug('Firing event %s', name)
try:
@ -101,11 +105,14 @@ def fireEvent(name, *args, **kwargs):
# Fire
result = e(*args, **kwargs)
result_keys = result.keys()
result_keys.sort(natcmp)
if options['single'] and not options['merge']:
results = None
# Loop over results, stop when first not None result is found.
for r_key in sorted(result.iterkeys(), cmp = natcmp):
for r_key in result_keys:
r = result[r_key]
if r[0] is True and r[1] is not None:
results = r[1]
@ -117,7 +124,7 @@ def fireEvent(name, *args, **kwargs):
else:
results = []
for r_key in sorted(result.iterkeys(), cmp = natcmp):
for r_key in result_keys:
r = result[r_key]
if r[0] == True and r[1]:
results.append(r[1])
@ -160,18 +167,21 @@ def fireEvent(name, *args, **kwargs):
except Exception:
log.error('%s: %s', (name, traceback.format_exc()))
def fireEventAsync(*args, **kwargs):
try:
t = threading.Thread(target = fireEvent, args = args, kwargs = kwargs)
t.setDaemon(True)
t.start()
return True
except Exception, e:
except Exception as e:
log.error('%s: %s', (args[0], e))
def errorHandler(error):
etype, value, tb = error
log.error(''.join(traceback.format_exception(etype, value, tb)))
def getEvent(name):
return events[name]

14
couchpotato/core/helpers/encoding.py

@ -11,16 +11,18 @@ log = CPLog(__name__)
def toSafeString(original):
valid_chars = "-_.() %s%s" % (ascii_letters, digits)
cleanedFilename = unicodedata.normalize('NFKD', toUnicode(original)).encode('ASCII', 'ignore')
valid_string = ''.join(c for c in cleanedFilename if c in valid_chars)
cleaned_filename = unicodedata.normalize('NFKD', toUnicode(original)).encode('ASCII', 'ignore')
valid_string = ''.join(c for c in cleaned_filename if c in valid_chars)
return ' '.join(valid_string.split())
def simplifyString(original):
string = stripAccents(original.lower())
string = toSafeString(' '.join(re.split('\W+', string)))
split = re.split('\W+|_', string.lower())
return toUnicode(' '.join(split))
def toUnicode(original, *args):
try:
if isinstance(original, unicode):
@ -38,16 +40,18 @@ def toUnicode(original, *args):
ascii_text = str(original).encode('string_escape')
return toUnicode(ascii_text)
def ss(original, *args):
u_original = toUnicode(original, *args)
try:
from couchpotato.environment import Env
return u_original.encode(Env.get('encoding'))
except Exception, e:
except Exception as e:
log.debug('Failed ss encoding char, force UTF8: %s', e)
return u_original.encode('UTF-8')
def sp(path, *args):
# Standardise encoding, normalise case, path and strip trailing '/' or '\'
@ -73,6 +77,7 @@ def sp(path, *args):
return path
def ek(original, *args):
if isinstance(original, (str, unicode)):
try:
@ -83,6 +88,7 @@ def ek(original, *args):
return original
def isInt(value):
try:
int(value)
@ -90,9 +96,11 @@ def isInt(value):
except ValueError:
return False
def stripAccents(s):
return ''.join((c for c in unicodedata.normalize('NFD', toUnicode(s)) if unicodedata.category(c) != 'Mn'))
def tryUrlencode(s):
new = u''
if isinstance(s, dict):

1
couchpotato/core/helpers/request.py

@ -37,6 +37,7 @@ def getParams(params):
return dictToList(temp)
def dictToList(params):
if type(params) is dict:

3
couchpotato/core/helpers/rss.py

@ -3,6 +3,7 @@ import xml.etree.ElementTree as XMLTree
log = CPLog(__name__)
class RSS(object):
def getTextElements(self, xml, path):
@ -46,6 +47,6 @@ class RSS(object):
def getItems(self, data, path = 'channel/item'):
try:
return XMLTree.parse(data).findall(path)
except Exception, e:
except Exception as e:
log.error('Error parsing RSS. %s', e)
return []

42
couchpotato/core/helpers/variable.py

@ -11,8 +11,10 @@ import sys
log = CPLog(__name__)
def fnEscape(pattern):
return pattern.replace('[','[[').replace(']','[]]').replace('[[','[[]')
return pattern.replace('[', '[[').replace(']', '[]]').replace('[[', '[[]')
def link(src, dst):
if os.name == 'nt':
@ -21,6 +23,7 @@ def link(src, dst):
else:
os.link(src, dst)
def symlink(src, dst):
if os.name == 'nt':
import ctypes
@ -28,6 +31,7 @@ def symlink(src, dst):
else:
os.symlink(src, dst)
def getUserDir():
try:
import pwd
@ -37,6 +41,7 @@ def getUserDir():
return os.path.expanduser('~')
def getDownloadDir():
user_dir = getUserDir()
@ -49,6 +54,7 @@ def getDownloadDir():
return user_dir
def getDataDir():
# Windows
@ -68,8 +74,10 @@ def getDataDir():
# Linux
return os.path.join(user_dir, '.couchpotato')
def isDict(object):
return isinstance(object, dict)
def isDict(obj):
return isinstance(obj, dict)
def mergeDicts(a, b, prepend_list = False):
assert isDict(a), isDict(b)
@ -91,6 +99,7 @@ def mergeDicts(a, b, prepend_list = False):
current_dst[key] = current_src[key]
return dst
def removeListDuplicates(seq):
checked = []
for e in seq:
@ -98,26 +107,32 @@ def removeListDuplicates(seq):
checked.append(e)
return checked
def flattenList(l):
if isinstance(l, list):
return sum(map(flattenList, l))
else:
return l
def md5(text):
return hashlib.md5(ss(text)).hexdigest()
def sha1(text):
return hashlib.sha1(text).hexdigest()
def isLocalIP(ip):
ip = ip.lstrip('htps:/')
regex = '/(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1)$/'
return re.search(regex, ip) is not None or 'localhost' in ip or ip[:4] == '127.'
def getExt(filename):
return os.path.splitext(filename)[1][1:]
def cleanHost(host, protocol = True, ssl = False, username = None, password = None):
if not '://' in host and protocol:
@ -137,6 +152,7 @@ def cleanHost(host, protocol = True, ssl = False, username = None, password = No
return host
def getImdb(txt, check_inside = False, multiple = False):
if not check_inside:
@ -161,10 +177,12 @@ def getImdb(txt, check_inside = False, multiple = False):
return False
def tryInt(s, default = 0):
try: return int(s)
except: return default
def tryFloat(s):
try:
if isinstance(s, str):
@ -173,17 +191,24 @@ def tryFloat(s):
return float(s)
except: return 0
def natsortKey(s):
return map(tryInt, re.findall(r'(\d+|\D+)', s))
def natcmp(a, b):
return cmp(natsortKey(a), natsortKey(b))
a2 = natsortKey(a)
b2 = natsortKey(b)
return (a2 > b2) - (a2 < b2)
def toIterable(value):
if isinstance(value, collections.Iterable):
return value
return [value]
def getTitle(library_dict):
try:
try:
@ -206,6 +231,7 @@ def getTitle(library_dict):
log.error('Could not get title for library item: %s', library_dict)
return None
def possibleTitles(raw_title):
titles = [
@ -220,16 +246,20 @@ def possibleTitles(raw_title):
return list(set(titles))
def randomString(size = 8, chars = string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for x in range(size))
def splitString(str, split_on = ',', clean = True):
list = [x.strip() for x in str.split(split_on)] if str else []
return filter(None, list) if clean else list
l = [x.strip() for x in str.split(split_on)] if str else []
return filter(None, l) if clean else l
def dictIsSubset(a, b):
return all([k in b and b[k] == v for k, v in a.items()])
def isSubFolder(sub_folder, base_folder):
# Returns True if sub_folder is the same as or inside base_folder
return base_folder and sub_folder and os.path.normpath(base_folder).rstrip(os.path.sep) + os.path.sep in os.path.normpath(sub_folder).rstrip(os.path.sep) + os.path.sep

3
couchpotato/core/logger.py

@ -1,6 +1,7 @@
import logging
import re
class CPLog(object):
context = ''
@ -49,7 +50,7 @@ class CPLog(object):
msg = msg % tuple([ss(x) for x in list(replace_tuple)])
else:
msg = msg % ss(replace_tuple)
except Exception, e:
except Exception as e:
self.logger.error(u'Failed encoding stuff to log "%s": %s' % (msg, e))
if not Env.get('dev'):

4
couchpotato/core/media/__init__.py

@ -10,8 +10,8 @@ class MediaBase(Plugin):
default_dict = {
'profile': {'types': {'quality': {}}},
'releases': {'status': {}, 'quality': {}, 'files':{}, 'info': {}},
'library': {'titles': {}, 'files':{}},
'releases': {'status': {}, 'quality': {}, 'files': {}, 'info': {}},
'library': {'titles': {}, 'files': {}},
'files': {},
'status': {},
'category': {},

1
couchpotato/core/media/_base/media/__init__.py

@ -1,5 +1,6 @@
from .main import MediaPlugin
def start():
return MediaPlugin()

3
couchpotato/core/media/_base/media/main.py

@ -102,7 +102,6 @@ class MediaPlugin(MediaBase):
def handler():
fireEvent('library.update.%s' % media.type, identifier = identifier, default_title = default_title, force = True, on_complete = self.createOnComplete(id))
return handler
def addSingleRefreshView(self):
@ -254,7 +253,7 @@ class MediaPlugin(MediaBase):
# Merge releases with movie dict
movies.append(mergeDicts(movie_dict[media_id].to_dict({
'library': {'titles': {}, 'files':{}},
'library': {'titles': {}, 'files': {}},
'files': {},
}), {
'releases': releases,

1
couchpotato/core/media/_base/search/__init__.py

@ -1,5 +1,6 @@
from .main import Search
def start():
return Search()

1
couchpotato/core/media/_base/searcher/__init__.py

@ -1,5 +1,6 @@
from .main import Searcher
def start():
return Searcher()

2
couchpotato/core/media/_base/searcher/base.py

@ -12,7 +12,6 @@ class SearcherBase(Plugin):
def __init__(self):
super(SearcherBase, self).__init__()
addEvent('searcher.progress', self.getProgress)
addEvent('%s.searcher.progress' % self.getType(), self.getProgress)
@ -26,7 +25,6 @@ class SearcherBase(Plugin):
_type = self.getType()
def setCrons():
fireEvent('schedule.cron', '%s.searcher.all' % _type, self.searchAll,
day = self.conf('cron_day'), hour = self.conf('cron_hour'), minute = self.conf('cron_minute'))

1
couchpotato/core/media/movie/_base/__init__.py

@ -1,5 +1,6 @@
from .main import MovieBase
def start():
return MovieBase()

1
couchpotato/core/media/movie/_base/main.py

@ -61,7 +61,6 @@ class MovieBase(MovieTypeBase):
except:
pass
library = fireEvent('library.add.movie', single = True, attrs = params, update_after = update_library)
# Status

1
couchpotato/core/media/movie/library/movie/__init__.py

@ -1,5 +1,6 @@
from .main import MovieLibraryPlugin
def start():
return MovieLibraryPlugin()

2
couchpotato/core/media/movie/library/movie/main.py

@ -13,7 +13,7 @@ log = CPLog(__name__)
class MovieLibraryPlugin(LibraryBase):
default_dict = {'titles': {}, 'files':{}}
default_dict = {'titles': {}, 'files': {}}
def __init__(self):
addEvent('library.add.movie', self.add)

1
couchpotato/core/media/movie/searcher/__init__.py

@ -1,6 +1,7 @@
from .main import MovieSearcher
import random
def start():
return MovieSearcher()

4
couchpotato/core/media/movie/searcher/main.py

@ -91,7 +91,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
'category': {},
'profile': {'types': {'quality': {}}},
'releases': {'status': {}, 'quality': {}},
'library': {'titles': {}, 'files':{}},
'library': {'titles': {}, 'files': {}},
'files': {},
})
@ -117,7 +117,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
def single(self, movie, search_protocols = None, manual = False):
# movies don't contain 'type' yet, so just set to default here
if not movie.has_key('type'):
if 'type' not in movie:
movie['type'] = 'movie'
# Find out search type

1
couchpotato/core/media/movie/suggestion/__init__.py

@ -1,5 +1,6 @@
from .main import Suggestion
def start():
return Suggestion()

1
couchpotato/core/migration/versions/002_Movie_category.py

@ -13,5 +13,6 @@ def upgrade(migrate_engine):
create_column(category_column, movie)
Index('ix_movie_category_id', movie.c.category_id).create()
def downgrade(migrate_engine):
pass

1
couchpotato/core/notifications/boxcar/__init__.py

@ -1,5 +1,6 @@
from .main import Boxcar
def start():
return Boxcar()

1
couchpotato/core/notifications/core/__init__.py

@ -1,5 +1,6 @@
from .main import CoreNotifier
def start():
return CoreNotifier()

1
couchpotato/core/notifications/core/main.py

@ -71,7 +71,6 @@ class CoreNotifier(Notification):
db.query(Notif).filter(Notif.added <= (int(time.time()) - 2419200)).delete()
db.commit()
def markAsRead(self, ids = None, **kwargs):
ids = splitString(ids) if ids else None

1
couchpotato/core/notifications/email/__init__.py

@ -1,5 +1,6 @@
from .main import Email
def start():
return Email()

2
couchpotato/core/notifications/email/main.py

@ -40,7 +40,7 @@ class Email(Notification):
log.debug("SMTP over SSL %s", ("enabled" if ssl == 1 else "disabled"))
mailserver = smtplib.SMTP_SSL(smtp_server) if ssl == 1 else smtplib.SMTP(smtp_server)
if (starttls):
if starttls:
log.debug("Using StartTLS to initiate the connection with the SMTP server")
mailserver.starttls()

1
couchpotato/core/notifications/growl/__init__.py

@ -1,5 +1,6 @@
from .main import Growl
def start():
return Growl()

2
couchpotato/core/notifications/growl/main.py

@ -37,7 +37,7 @@ class Growl(Notification):
)
self.growl.register()
self.registered = True
except Exception, e:
except Exception as e:
if 'timed out' in str(e):
self.registered = True
else:

1
couchpotato/core/notifications/nmj/__init__.py

@ -1,5 +1,6 @@
from .main import NMJ
def start():
return NMJ()

7
couchpotato/core/notifications/nmj/main.py

@ -86,18 +86,17 @@ class NMJ(Notification):
'arg3': '',
}
params = tryUrlencode(params)
UPDATE_URL = 'http://%(host)s:8008/metadata_database?%(params)s'
updateUrl = UPDATE_URL % {'host': host, 'params': params}
update_url = 'http://%(host)s:8008/metadata_database?%(params)s' % {'host': host, 'params': params}
try:
response = self.urlopen(updateUrl)
response = self.urlopen(update_url)
except:
return False
try:
et = etree.fromstring(response)
result = et.findtext('returnValue')
except SyntaxError, e:
except SyntaxError as e:
log.error('Unable to parse XML returned from the Popcorn Hour: %s', e)
return False

1
couchpotato/core/notifications/notifymyandroid/__init__.py

@ -1,5 +1,6 @@
from .main import NotifyMyAndroid
def start():
return NotifyMyAndroid()

1
couchpotato/core/notifications/notifymywp/__init__.py

@ -1,5 +1,6 @@
from .main import NotifyMyWP
def start():
return NotifyMyWP()

3
couchpotato/core/notifications/notifymywp/main.py

@ -8,7 +8,8 @@ log = CPLog(__name__)
class NotifyMyWP(Notification):
def notify(self, message = '', data = {}, listener = None):
def notify(self, message = '', data = None, listener = None):
if not data: data = {}
keys = splitString(self.conf('api_key'))
p = PyNMWP(keys, self.conf('dev_key'))

1
couchpotato/core/notifications/plex/__init__.py

@ -1,5 +1,6 @@
from .main import Plex
def start():
return Plex()

7
couchpotato/core/notifications/plex/main.py

@ -23,9 +23,9 @@ class Plex(Notification):
addEvent('renamer.after', self.addToLibrary)
def addToLibrary(self, message = None, group = {}):
def addToLibrary(self, message = None, group = None):
if self.isDisabled(): return
if not group: group = {}
return self.server.refresh()
@ -57,7 +57,8 @@ class Plex(Notification):
return success
def notify(self, message = '', data = {}, listener = None):
def notify(self, message = '', data = None, listener = None):
if not data: data = {}
return self.notifyClients(message, self.getClientNames())
def test(self, **kwargs):

1
couchpotato/core/notifications/prowl/__init__.py

@ -1,5 +1,6 @@
from .main import Prowl
def start():
return Prowl()

1
couchpotato/core/notifications/pushalot/__init__.py

@ -1,5 +1,6 @@
from .main import Pushalot
def start():
return Pushalot()

1
couchpotato/core/notifications/pushalot/main.py

@ -5,6 +5,7 @@ import traceback
log = CPLog(__name__)
class Pushalot(Notification):
urls = {

1
couchpotato/core/notifications/pushbullet/__init__.py

@ -1,5 +1,6 @@
from .main import Pushbullet
def start():
return Pushbullet()

1
couchpotato/core/notifications/pushover/__init__.py

@ -1,5 +1,6 @@
from .main import Pushover
def start():
return Pushover()

1
couchpotato/core/notifications/synoindex/__init__.py

@ -1,5 +1,6 @@
from .main import Synoindex
def start():
return Synoindex()

2
couchpotato/core/notifications/synoindex/main.py

@ -26,7 +26,7 @@ class Synoindex(Notification):
out = p.communicate()
log.info('Result from synoindex: %s', str(out))
return True
except OSError, e:
except OSError as e:
log.error('Unable to run synoindex: %s', e)
return False

1
couchpotato/core/notifications/toasty/__init__.py

@ -1,5 +1,6 @@
from .main import Toasty
def start():
return Toasty()

1
couchpotato/core/notifications/toasty/main.py

@ -5,6 +5,7 @@ import traceback
log = CPLog(__name__)
class Toasty(Notification):
urls = {

1
couchpotato/core/notifications/trakt/__init__.py

@ -1,5 +1,6 @@
from .main import Trakt
def start():
return Trakt()

1
couchpotato/core/notifications/trakt/main.py

@ -3,6 +3,7 @@ from couchpotato.core.notifications.base import Notification
log = CPLog(__name__)
class Trakt(Notification):
urls = {

1
couchpotato/core/notifications/twitter/__init__.py

@ -1,5 +1,6 @@
from .main import Twitter
def start():
return Twitter()

2
couchpotato/core/notifications/twitter/main.py

@ -64,7 +64,7 @@ class Twitter(Notification):
api.PostUpdate(update_message[135:] + ' 2/2')
else:
api.PostUpdate(update_message)
except Exception, e:
except Exception as e:
log.error('Error sending tweet: %s', e)
return False

1
couchpotato/core/notifications/xbmc/__init__.py

@ -1,5 +1,6 @@
from .main import XBMC
def start():
return XBMC()

3
couchpotato/core/notifications/xbmc/main.py

@ -1,7 +1,6 @@
from couchpotato.core.helpers.variable import splitString
from couchpotato.core.logger import CPLog
from couchpotato.core.notifications.base import Notification
from urllib2 import URLError
import base64
import json
import socket
@ -46,7 +45,7 @@ class XBMC(Notification):
max_successful += len(calls)
response = self.request(host, calls)
else:
response = self.notifyXBMCnoJSON(host, {'title':self.default_title, 'message':message})
response = self.notifyXBMCnoJSON(host, {'title': self.default_title, 'message': message})
if data and data.get('destination_dir') and (not self.conf('only_first') or hosts.index(host) == 0):
response += self.request(host, [('VideoLibrary.Scan', {})])

1
couchpotato/core/notifications/xmpp/__init__.py

@ -1,5 +1,6 @@
from .main import Xmpp
def start():
return Xmpp()

1
couchpotato/core/plugins/automation/__init__.py

@ -1,5 +1,6 @@
from .main import Automation
def start():
return Automation()

9
couchpotato/core/plugins/base.py

@ -85,7 +85,7 @@ class Plugin(object):
class_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
# View path
path = 'static/plugin/%s/' % (class_name)
path = 'static/plugin/%s/' % class_name
# Add handler to Tornado
Env.get('app').add_handlers(".*$", [(Env.get('web_base') + path + '(.*)', StaticFileHandler, {'path': static_folder})])
@ -110,7 +110,7 @@ class Plugin(object):
f.write(content)
f.close()
os.chmod(path, Env.getPermission('file'))
except Exception, e:
except Exception as e:
log.error('Unable writing to file "%s": %s', (path, traceback.format_exc()))
if os.path.isfile(path):
os.remove(path)
@ -121,7 +121,7 @@ class Plugin(object):
if not os.path.isdir(path):
os.makedirs(path, Env.getPermission('folder'))
return True
except Exception, e:
except Exception as e:
log.error('Unable to create folder "%s": %s', (path, e))
return False
@ -243,7 +243,6 @@ class Plugin(object):
except:
log.error("Something went wrong when finishing the plugin function. Could not find the 'is_running' key")
def getCache(self, cache_key, url = None, **kwargs):
cache_key_md5 = md5(cache_key)
cache = Env.get('cache').get(cache_key_md5)
@ -255,7 +254,7 @@ class Plugin(object):
try:
cache_timeout = 300
if kwargs.has_key('cache_timeout'):
if 'cache_timeout' in kwargs:
cache_timeout = kwargs.get('cache_timeout')
del kwargs['cache_timeout']

1
couchpotato/core/plugins/browser/__init__.py

@ -1,5 +1,6 @@
from .main import FileBrowser
def start():
return FileBrowser()

1
couchpotato/core/plugins/category/__init__.py

@ -1,5 +1,6 @@
from .main import CategoryPlugin
def start():
return CategoryPlugin()

2
couchpotato/core/plugins/category/main.py

@ -101,7 +101,7 @@ class CategoryPlugin(Plugin):
self.removeFromMovie(id)
success = True
except Exception, e:
except Exception as e:
message = log.error('Failed deleting category: %s', e)
db.expire_all()

1
couchpotato/core/plugins/custom/__init__.py

@ -1,5 +1,6 @@
from .main import Custom
def start():
return Custom()

1
couchpotato/core/plugins/dashboard/__init__.py

@ -1,5 +1,6 @@
from .main import Dashboard
def start():
return Dashboard()

2
couchpotato/core/plugins/dashboard/main.py

@ -115,7 +115,7 @@ class Dashboard(Plugin):
for movie_id in movie_ids:
movies.append(movie_dict[movie_id].to_dict({
'library': {'titles': {}, 'files':{}},
'library': {'titles': {}, 'files': {}},
'files': {},
}))

1
couchpotato/core/plugins/file/__init__.py

@ -1,5 +1,6 @@
from .main import FileManager
def start():
return FileManager()

1
couchpotato/core/plugins/file/main.py

@ -82,7 +82,6 @@ class FileManager(Plugin):
def showCacheFile(self, route, **kwargs):
Env.get('app').add_handlers(".*$", [('%s%s' % (Env.get('api_base'), route), StaticFileHandler, {'path': Env.get('cache_dir')})])
def download(self, url = '', dest = None, overwrite = False, urlopen_kwargs = None):
if not urlopen_kwargs: urlopen_kwargs = {}

1
couchpotato/core/plugins/log/__init__.py

@ -1,5 +1,6 @@
from .main import Logging
def start():
return Logging()

2
couchpotato/core/plugins/log/main.py

@ -42,7 +42,7 @@ class Logging(Plugin):
'desc': 'Log errors',
'params': {
'type': {'desc': 'Type of logging, default "error"'},
'**kwargs': {'type':'object', 'desc': 'All other params will be printed in the log string.'},
'**kwargs': {'type': 'object', 'desc': 'All other params will be printed in the log string.'},
}
})

1
couchpotato/core/plugins/manage/__init__.py

@ -1,5 +1,6 @@
from .main import Manage
def start():
return Manage()

1
couchpotato/core/plugins/manage/main.py

@ -14,6 +14,7 @@ import traceback
log = CPLog(__name__)
class Manage(Plugin):
in_progress = False

1
couchpotato/core/plugins/profile/__init__.py

@ -1,5 +1,6 @@
from .main import ProfilePlugin
def start():
return ProfilePlugin()

2
couchpotato/core/plugins/profile/main.py

@ -149,7 +149,7 @@ class ProfilePlugin(Plugin):
self.forceDefaults()
success = True
except Exception, e:
except Exception as e:
message = log.error('Failed deleting Profile: %s', e)
db.expire_all()

1
couchpotato/core/plugins/quality/__init__.py

@ -1,5 +1,6 @@
from .main import QualityPlugin
def start():
return QualityPlugin()

1
couchpotato/core/plugins/release/__init__.py

@ -1,5 +1,6 @@
from .main import Release
def start():
return Release()

15
couchpotato/core/plugins/release/main.py

@ -96,7 +96,6 @@ class Release(Plugin):
identifier = '%s.%s.%s' % (group['library']['identifier'], group['meta_data'].get('audio', 'unknown'), group['meta_data']['quality']['identifier'])
done_status, snatched_status = fireEvent('status.get', ['done', 'snatched'], single = True)
# Add movie
@ -237,15 +236,15 @@ class Release(Plugin):
success = self.download(data = item, media = rel.movie.to_dict({
'profile': {'types': {'quality': {}}},
'releases': {'status': {}, 'quality': {}},
'library': {'titles': {}, 'files':{}},
'library': {'titles': {}, 'files': {}},
'files': {}
}), manual = True)
if success == True:
db.expunge_all()
rel = db.query(Relea).filter_by(id = id).first() # Get release again @RuudBurger why do we need to get it again??
if success:
fireEvent('notify.frontend', type = 'release.manual_download', data = True, message = 'Successfully snatched "%s"' % item['name'])
return {
'success': success == True
}
@ -317,8 +316,8 @@ class Release(Plugin):
# If renamer isn't used, mark media done if finished or release downloaded
else:
if media['status_id'] == active_status.get('id'):
finished = next((True for profile_type in media['profile']['types'] if \
profile_type['quality_id'] == rls.quality.id and profile_type['finish']), False)
finished = next((True for profile_type in media['profile']['types']
if profile_type['quality_id'] == rls.quality.id and profile_type['finish']), False)
if finished:
log.info('Renamer disabled, marking media as finished: %s', log_movie)
@ -423,7 +422,7 @@ class Release(Plugin):
.filter(Relea.movie_id == id) \
.all()
releases = [r.to_dict({'info':{}, 'files':{}}) for r in releases_raw]
releases = [r.to_dict({'info': {}, 'files': {}}) for r in releases_raw]
releases = sorted(releases, key = lambda k: k['info'].get('score', 0), reverse = True)
return releases
@ -449,6 +448,7 @@ class Release(Plugin):
for info in rel.info:
item[info.identifier] = info.value
release_name = None
if rel.files:
for file_item in rel.files:
if file_item.type.identifier == 'movie':
@ -456,6 +456,7 @@ class Release(Plugin):
break
else:
release_name = item['name']
#update status in Db
log.debug('Marking release %s as %s', (release_name, status.get("label")))
rel.status_id = status.get('id')

4
couchpotato/core/plugins/renamer/__init__.py

@ -1,6 +1,7 @@
from couchpotato.core.plugins.renamer.main import Renamer
import os
def start():
return Renamer()
@ -136,7 +137,8 @@ config = [{
'default': 'link',
'type': 'dropdown',
'values': [('Link', 'link'), ('Copy', 'copy'), ('Move', 'move')],
'description': ('<strong>Link</strong>, <strong>Copy</strong> or <strong>Move</strong> after download completed.', 'Link first tries <a href="http://en.wikipedia.org/wiki/Hard_link">hard link</a>, then <a href="http://en.wikipedia.org/wiki/Sym_link">sym link</a> and falls back to Copy. It is perfered to use link when downloading torrents as it will save you space, while still beeing able to seed.'),
'description': ('<strong>Link</strong>, <strong>Copy</strong> or <strong>Move</strong> after download completed.',
'Link first tries <a href="http://en.wikipedia.org/wiki/Hard_link">hard link</a>, then <a href="http://en.wikipedia.org/wiki/Sym_link">sym link</a> and falls back to Copy. It is perfered to use link when downloading torrents as it will save you space, while still beeing able to seed.'),
'advanced': True,
},
{

13
couchpotato/core/plugins/renamer/main.py

@ -20,6 +20,7 @@ import traceback
log = CPLog(__name__)
class Renamer(Plugin):
renaming_started = False
@ -33,7 +34,7 @@ class Renamer(Plugin):
'media_folder': {'desc': 'Optional: The folder of the media to scan. Keep empty for default renamer folder.'},
'files': {'desc': 'Optional: Provide the release files if more releases are in the same media_folder, delimited with a \'|\'. Note that no dedicated release folder is expected for releases with one file.'},
'base_folder': {'desc': 'Optional: The folder to find releases in. Leave empty for default folder.'},
'downloader' : {'desc': 'Optional: The downloader the release has been downloaded with. \'download_id\' is required with this option.'},
'downloader': {'desc': 'Optional: The downloader the release has been downloaded with. \'download_id\' is required with this option.'},
'download_id': {'desc': 'Optional: The nzb/torrent ID of the release in media_folder. \'downloader\' is required with this option.'},
'status': {'desc': 'Optional: The status of the release: \'completed\' (default) or \'seeding\''},
},
@ -434,7 +435,7 @@ class Renamer(Plugin):
movie.status_id = done_status.get('id')
movie.last_edit = int(time.time())
db.commit()
except Exception, e:
except Exception as e:
log.error('Failed marking movie finished: %s %s', (e, traceback.format_exc()))
# Go over current movie releases
@ -526,7 +527,7 @@ class Renamer(Plugin):
for delete_folder in delete_folders:
try:
self.deleteEmptyFolder(delete_folder, show_error = False)
except Exception, e:
except Exception as e:
log.error('Failed to delete folder: %s %s', (e, traceback.format_exc()))
# Rename all files marked
@ -1160,7 +1161,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
rar_handle.extract(condition = [packedinfo.index], path = extr_path, withSubpath = False, overwrite = False)
extr_files.append(sp(os.path.join(extr_path, os.path.basename(packedinfo.filename))))
del rar_handle
except Exception, e:
except Exception as e:
log.error('Failed to extract %s: %s %s', (archive['file'], e, traceback.format_exc()))
continue
@ -1169,7 +1170,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
if cleanup:
try:
os.remove(filename)
except Exception, e:
except Exception as e:
log.error('Failed to remove %s: %s %s', (filename, e, traceback.format_exc()))
continue
files.remove(filename)
@ -1182,7 +1183,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
try:
self.makeDir(os.path.dirname(move_to))
self.moveFile(leftoverfile, move_to, cleanup)
except Exception, e:
except Exception as e:
log.error('Failed moving left over file %s to %s: %s %s', (leftoverfile, move_to, e, traceback.format_exc()))
# As we probably tried to overwrite the nfo file, check if it exists and then remove the original
if os.path.isfile(move_to):

1
couchpotato/core/plugins/scanner/__init__.py

@ -1,5 +1,6 @@
from .main import Scanner
def start():
return Scanner()

6
couchpotato/core/plugins/scanner/main.py

@ -263,7 +263,7 @@ class Scanner(Plugin):
delete_identifiers.append(identifier)
# Remove the found files from the leftover stack
leftovers = leftovers - set([ff])
leftovers -= leftovers - set([ff])
# Break if CP wants to shut down
if self.shuttingDown():
@ -727,7 +727,9 @@ class Scanner(Plugin):
if is_sample: log.debug('Is sample file: %s', filename)
return is_sample
def filesizeBetween(self, file, file_size = []):
def filesizeBetween(self, file, file_size = None):
if not file_size: file_size = []
try:
return (file_size.get('min', 0) * 1048576) < os.path.getsize(file) < (file_size.get('max', 100000) * 1048576)
except:

1
couchpotato/core/plugins/score/__init__.py

@ -1,5 +1,6 @@
from .main import Score
def start():
return Score()

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save