[Lint] Convert all python double quotes to single quotes

* A rather disruptive change but for a few reasons such as easier to read,
   easier type, keep consistent and javascript code uses single quotes.
 * There are a few exceptions for the automated process:
    * Any double quotes in comments
    * Triple double quotes for docstrings
    * Strings containing single quotes are left e.g. "they're"

 * To deal with merge conflicts from feature branches it is best to follow
   these steps for each commit:
     * Create a patch: `git format-patch -1 <sha1>`
     * Edit the patch and replace double quotes with single except those in
       comments or strings containing an unescaped apostrophe.
     * Check the patch `git apply --check <patchfile>` and fix any remaining
       issues if it outputs an error.
     * Apply the patch `git am < <patchfile>`
This commit is contained in:
Calum Lind 2016-11-03 21:26:46 +00:00
parent d4a8a38586
commit 3a2ff0c188
231 changed files with 8812 additions and 8812 deletions

View File

@ -23,7 +23,7 @@ try:
except ImportError:
import libtorrent as lt
REQUIRED_VERSION = "1.0.7.0"
REQUIRED_VERSION = '1.0.7.0'
if VersionSplit(lt.__version__) < VersionSplit(REQUIRED_VERSION):
raise ImportError("Deluge %s requires libtorrent >= %s" % (get_version(), REQUIRED_VERSION))
raise ImportError('Deluge %s requires libtorrent >= %s' % (get_version(), REQUIRED_VERSION))

View File

@ -75,7 +75,7 @@ def bdecode(x):
try:
r, l = decode_func[x[0]](x, 0)
except (IndexError, KeyError, ValueError):
raise BTFailure("not a valid bencoded string")
raise BTFailure('not a valid bencoded string')
return r

View File

@ -32,7 +32,7 @@ from deluge.error import InvalidPathError
try:
import dbus
bus = dbus.SessionBus()
dbus_fileman = bus.get_object("org.freedesktop.FileManager1", "/org/freedesktop/FileManager1")
dbus_fileman = bus.get_object('org.freedesktop.FileManager1', '/org/freedesktop/FileManager1')
except Exception:
dbus_fileman = None
@ -40,29 +40,29 @@ except Exception:
log = logging.getLogger(__name__)
TORRENT_STATE = [
"Allocating",
"Checking",
"Downloading",
"Seeding",
"Paused",
"Error",
"Queued",
"Moving"
'Allocating',
'Checking',
'Downloading',
'Seeding',
'Paused',
'Error',
'Queued',
'Moving'
]
FILE_PRIORITY = {
0: "Do Not Download",
1: "Normal Priority",
2: "High Priority",
3: "High Priority",
4: "High Priority",
5: "High Priority",
6: "High Priority",
7: "Highest Priority",
"Do Not Download": 0,
"Normal Priority": 1,
"High Priority": 5,
"Highest Priority": 7
0: 'Do Not Download',
1: 'Normal Priority',
2: 'High Priority',
3: 'High Priority',
4: 'High Priority',
5: 'High Priority',
6: 'High Priority',
7: 'Highest Priority',
'Do Not Download': 0,
'Normal Priority': 1,
'High Priority': 5,
'Highest Priority': 7
}
@ -74,7 +74,7 @@ def get_version():
:rtype: string
"""
return pkg_resources.require("Deluge")[0].version
return pkg_resources.require('Deluge')[0].version
def get_default_config_dir(filename=None):
@ -89,12 +89,12 @@ def get_default_config_dir(filename=None):
if windows_check():
def save_config_path(resource):
app_data_path = os.environ.get("APPDATA")
app_data_path = os.environ.get('APPDATA')
if not app_data_path:
import _winreg
hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders")
app_data_reg = _winreg.QueryValueEx(hkey, "AppData")
'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders')
app_data_reg = _winreg.QueryValueEx(hkey, 'AppData')
app_data_path = app_data_reg[0]
_winreg.CloseKey(hkey)
return os.path.join(app_data_path, resource)
@ -103,9 +103,9 @@ def get_default_config_dir(filename=None):
if not filename:
filename = ''
try:
return os.path.join(save_config_path("deluge"), filename)
return os.path.join(save_config_path('deluge'), filename)
except OSError as ex:
log.error("Unable to use default config directory, exiting... (%s)", ex)
log.error('Unable to use default config directory, exiting... (%s)', ex)
sys.exit(1)
@ -115,20 +115,20 @@ def get_default_download_dir():
:rtype: string
"""
download_dir = ""
download_dir = ''
if not windows_check():
from xdg.BaseDirectory import xdg_config_home
try:
with open(os.path.join(xdg_config_home, 'user-dirs.dirs'), 'r') as _file:
for line in _file:
if not line.startswith('#') and line.startswith('XDG_DOWNLOAD_DIR'):
download_dir = os.path.expandvars(line.partition("=")[2].rstrip().strip('"'))
download_dir = os.path.expandvars(line.partition('=')[2].rstrip().strip('"'))
break
except IOError:
pass
if not download_dir:
download_dir = os.path.join(os.path.expanduser("~"), 'Downloads')
download_dir = os.path.join(os.path.expanduser('~'), 'Downloads')
return download_dir
@ -151,7 +151,7 @@ def vista_check():
:rtype: bool
"""
return platform.release() == "Vista"
return platform.release() == 'Vista'
def osx_check():
@ -162,7 +162,7 @@ def osx_check():
:rtype: bool
"""
return platform.system() == "Darwin"
return platform.system() == 'Darwin'
def linux_check():
@ -173,7 +173,7 @@ def linux_check():
:rtype: bool
"""
return platform.system() == "Linux"
return platform.system() == 'Linux'
def get_os_version():
@ -197,7 +197,7 @@ def get_pixmap(fname):
:rtype: string
"""
return resource_filename("deluge", os.path.join("ui", "data", "pixmaps", fname))
return resource_filename('deluge', os.path.join('ui', 'data', 'pixmaps', fname))
def resource_filename(module, path):
@ -207,8 +207,8 @@ def resource_filename(module, path):
# not, it returns the first found on the python path, which is not good
# enough.
# This is a work-around that.
return pkg_resources.require("Deluge>=%s" % get_version())[0].get_resource_filename(
pkg_resources._manager, os.path.join(*(module.split(".") + [path]))
return pkg_resources.require('Deluge>=%s' % get_version())[0].get_resource_filename(
pkg_resources._manager, os.path.join(*(module.split('.') + [path]))
)
@ -223,14 +223,14 @@ def open_file(path, timestamp=None):
if windows_check():
os.startfile(path)
elif osx_check():
subprocess.Popen(["open", path])
subprocess.Popen(['open', path])
else:
if timestamp is None:
timestamp = int(time.time())
env = os.environ.copy()
env["DESKTOP_STARTUP_ID"] = "%s-%u-%s-xdg_open_TIME%d" % \
env['DESKTOP_STARTUP_ID'] = '%s-%u-%s-xdg_open_TIME%d' % \
(os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp)
subprocess.Popen(["xdg-open", "%s" % path], env=env)
subprocess.Popen(['xdg-open', '%s' % path], env=env)
def show_file(path, timestamp=None):
@ -242,21 +242,21 @@ def show_file(path, timestamp=None):
"""
if windows_check():
subprocess.Popen(["explorer", "/select,", path])
subprocess.Popen(['explorer', '/select,', path])
elif osx_check():
subprocess.Popen(["open", "-R", path])
subprocess.Popen(['open', '-R', path])
else:
if timestamp is None:
timestamp = int(time.time())
startup_id = "%s_%u_%s-dbus_TIME%d" % (os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp)
startup_id = '%s_%u_%s-dbus_TIME%d' % (os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp)
if dbus_fileman:
paths = [urlparse.urljoin("file:", urllib.pathname2url(utf8_encoded(path)))]
dbus_fileman.ShowItems(paths, startup_id, dbus_interface="org.freedesktop.FileManager1")
paths = [urlparse.urljoin('file:', urllib.pathname2url(utf8_encoded(path)))]
dbus_fileman.ShowItems(paths, startup_id, dbus_interface='org.freedesktop.FileManager1')
else:
env = os.environ.copy()
env["DESKTOP_STARTUP_ID"] = startup_id.replace("dbus", "xdg-open")
env['DESKTOP_STARTUP_ID'] = startup_id.replace('dbus', 'xdg-open')
# No option in xdg to highlight a file so just open parent folder.
subprocess.Popen(["xdg-open", os.path.dirname(path.rstrip("/"))], env=env)
subprocess.Popen(['xdg-open', os.path.dirname(path.rstrip('/'))], env=env)
def open_url_in_browser(url):
@ -272,15 +272,15 @@ def open_url_in_browser(url):
# Formatting text functions
byte_txt = "B"
kib_txt = "KiB"
mib_txt = "MiB"
gib_txt = "GiB"
tib_txt = "TiB"
kib_txt_short = "K"
mib_txt_short = "M"
gib_txt_short = "G"
tib_txt_short = "T"
byte_txt = 'B'
kib_txt = 'KiB'
mib_txt = 'MiB'
gib_txt = 'GiB'
tib_txt = 'TiB'
kib_txt_short = 'K'
mib_txt_short = 'M'
gib_txt_short = 'G'
tib_txt_short = 'T'
def translate_size_units():
@ -289,15 +289,15 @@ def translate_size_units():
global byte_txt, kib_txt, mib_txt, gib_txt, tib_txt
global kib_txt_short, mib_txt_short, gib_txt_short, tib_txt_short
byte_txt = _("B")
kib_txt = _("KiB")
mib_txt = _("MiB")
gib_txt = _("GiB")
tib_txt = _("TiB")
kib_txt_short = _("K")
mib_txt_short = _("M")
gib_txt_short = _("G")
tib_txt_short = _("T")
byte_txt = _('B')
kib_txt = _('KiB')
mib_txt = _('MiB')
gib_txt = _('GiB')
tib_txt = _('TiB')
kib_txt_short = _('K')
mib_txt_short = _('M')
gib_txt_short = _('G')
tib_txt_short = _('T')
def fsize(fsize_b, precision=1, shortform=False):
@ -324,15 +324,15 @@ def fsize(fsize_b, precision=1, shortform=False):
"""
if fsize_b >= 1024 ** 4:
return "%.*f %s" % (precision, fsize_b / 1024 ** 4, tib_txt_short if shortform else tib_txt)
return '%.*f %s' % (precision, fsize_b / 1024 ** 4, tib_txt_short if shortform else tib_txt)
elif fsize_b >= 1024 ** 3:
return "%.*f %s" % (precision, fsize_b / 1024 ** 3, gib_txt_short if shortform else gib_txt)
return '%.*f %s' % (precision, fsize_b / 1024 ** 3, gib_txt_short if shortform else gib_txt)
elif fsize_b >= 1024 ** 2:
return "%.*f %s" % (precision, fsize_b / 1024 ** 2, mib_txt_short if shortform else mib_txt)
return '%.*f %s' % (precision, fsize_b / 1024 ** 2, mib_txt_short if shortform else mib_txt)
elif fsize_b >= 1024:
return "%.*f %s" % (precision, fsize_b / 1024, kib_txt_short if shortform else kib_txt)
return '%.*f %s' % (precision, fsize_b / 1024, kib_txt_short if shortform else kib_txt)
else:
return "%d %s" % (fsize_b, byte_txt)
return '%d %s' % (fsize_b, byte_txt)
def fpcnt(dec, precision=2):
@ -375,13 +375,13 @@ def fspeed(bps, precision=1, shortform=False):
"""
if bps < 1024 ** 2:
return "%.*f %s" % (precision, bps / 1024, _("K/s") if shortform else _("KiB/s"))
return '%.*f %s' % (precision, bps / 1024, _('K/s') if shortform else _('KiB/s'))
elif bps < 1024 ** 3:
return "%.*f %s" % (precision, bps / 1024 ** 2, _("M/s") if shortform else _("MiB/s"))
return '%.*f %s' % (precision, bps / 1024 ** 2, _('M/s') if shortform else _('MiB/s'))
elif bps < 1024 ** 4:
return "%.*f %s" % (precision, bps / 1024 ** 3, _("G/s") if shortform else _("GiB/s"))
return '%.*f %s' % (precision, bps / 1024 ** 3, _('G/s') if shortform else _('GiB/s'))
else:
return "%.*f %s" % (precision, bps / 1024 ** 4, _("T/s") if shortform else _("TiB/s"))
return '%.*f %s' % (precision, bps / 1024 ** 4, _('T/s') if shortform else _('TiB/s'))
def fpeer(num_peers, total_peers):
@ -402,9 +402,9 @@ def fpeer(num_peers, total_peers):
"""
if total_peers > -1:
return "{:d} ({:d})".format(num_peers, total_peers)
return '{:d} ({:d})'.format(num_peers, total_peers)
else:
return "{:d}".format(num_peers)
return '{:d}'.format(num_peers)
def ftime(secs):
@ -456,8 +456,8 @@ def fdate(seconds, date_only=False, precision_secs=False):
"""
if seconds < 0:
return ""
time_format = "%x %X" if precision_secs else "%x %H:%M"
return ''
time_format = '%x %X' if precision_secs else '%x %H:%M'
if date_only:
time_format = time_format.split()[0]
return time.strftime(time_format, time.localtime(seconds))
@ -535,7 +535,7 @@ def parse_human_size(size):
if normalized_unit.startswith(unit['prefix'].lower()):
return int(tokens[0] * unit['divider'])
# We failed to parse the size specification.
msg = "Failed to parse size! (input %r was tokenized as %r)"
msg = 'Failed to parse size! (input %r was tokenized as %r)'
raise InvalidSize(msg % (size, tokens))
@ -554,7 +554,7 @@ def is_url(url):
True
"""
return url.partition('://')[0] in ("http", "https", "ftp", "udp")
return url.partition('://')[0] in ('http', 'https', 'ftp', 'udp')
def is_infohash(infohash):
@ -623,9 +623,9 @@ def get_magnet_info(uri):
xt_hash = param[len(xt_param):]
if len(xt_hash) == 32:
try:
info_hash = base64.b32decode(xt_hash.upper()).encode("hex")
info_hash = base64.b32decode(xt_hash.upper()).encode('hex')
except TypeError as ex:
log.debug("Invalid base32 magnet hash: %s, %s", xt_hash, ex)
log.debug('Invalid base32 magnet hash: %s, %s', xt_hash, ex)
break
elif is_infohash(xt_hash):
info_hash = xt_hash.lower()
@ -637,7 +637,7 @@ def get_magnet_info(uri):
if info_hash:
if not name:
name = info_hash
return {"name": name, "info_hash": info_hash, "files_tree": ''}
return {'name': name, 'info_hash': info_hash, 'files_tree': ''}
return False
@ -657,12 +657,12 @@ def create_magnet_uri(infohash, name=None, trackers=None):
"""
from base64 import b32encode
uri = "magnet:?xt=urn:btih:" + b32encode(infohash.decode("hex"))
uri = 'magnet:?xt=urn:btih:' + b32encode(infohash.decode('hex'))
if name:
uri = uri + "&dn=" + name
uri = uri + '&dn=' + name
if trackers:
for t in trackers:
uri = uri + "&tr=" + t
uri = uri + '&tr=' + t
return uri
@ -704,13 +704,13 @@ def free_space(path):
"""
if not path or not os.path.exists(path):
raise InvalidPathError("%s is not a valid path" % path)
raise InvalidPathError('%s is not a valid path' % path)
if windows_check():
from win32file import GetDiskFreeSpaceEx
return GetDiskFreeSpaceEx(path)[0]
else:
disk_data = os.statvfs(path.encode("utf8"))
disk_data = os.statvfs(path.encode('utf8'))
block_size = disk_data.f_frsize
return disk_data.f_bavail * block_size
@ -745,7 +745,7 @@ def is_ip(ip):
# now test ipv6
try:
if windows_check():
log.warning("ipv6 check unavailable on windows")
log.warning('ipv6 check unavailable on windows')
return True
else:
if socket.inet_pton(socket.AF_INET6, ip):
@ -754,7 +754,7 @@ def is_ip(ip):
return False
def decode_string(s, encoding="utf8"):
def decode_string(s, encoding='utf8'):
"""
Decodes a string and return unicode. If it cannot decode using
`:param:encoding` then it will try latin1, and if that fails,
@ -774,12 +774,12 @@ def decode_string(s, encoding="utf8"):
elif isinstance(s, unicode):
return s
encodings = [lambda: ("utf8", 'strict'),
lambda: ("iso-8859-1", 'strict'),
lambda: (chardet.detect(s)["encoding"], 'strict'),
encodings = [lambda: ('utf8', 'strict'),
lambda: ('iso-8859-1', 'strict'),
lambda: (chardet.detect(s)['encoding'], 'strict'),
lambda: (encoding, 'ignore')]
if encoding is not "utf8":
if encoding is not 'utf8':
encodings.insert(0, lambda: (encoding, 'strict'))
for l in encodings:
@ -790,7 +790,7 @@ def decode_string(s, encoding="utf8"):
return u''
def utf8_encoded(s, encoding="utf8"):
def utf8_encoded(s, encoding='utf8'):
"""
Returns a utf8 encoded string of s
@ -803,9 +803,9 @@ def utf8_encoded(s, encoding="utf8"):
"""
if isinstance(s, str):
s = decode_string(s, encoding).encode("utf8")
s = decode_string(s, encoding).encode('utf8')
elif isinstance(s, unicode):
s = s.encode("utf8")
s = s.encode('utf8')
return s
@ -838,13 +838,13 @@ class VersionSplit(object):
vs = [''.join(group[0:2]), ''.join(group[2:4]), group[4].lstrip('.')]
else:
ver = ver.lower()
vs = ver.replace("_", "-").split("-")
vs = ver.replace('_', '-').split('-')
self.version = [int(x) for x in vs[0].split(".") if x.isdigit()]
self.version = [int(x) for x in vs[0].split('.') if x.isdigit()]
self.suffix = None
self.dev = False
if len(vs) > 1:
if vs[1].startswith(("rc", "a", "b", "c")):
if vs[1].startswith(('rc', 'a', 'b', 'c')):
self.suffix = vs[1]
if vs[-1].startswith('dev'):
self.dev = vs[-1]
@ -889,10 +889,10 @@ def create_auth_file():
import stat
import deluge.configmanager
auth_file = deluge.configmanager.get_config_dir("auth")
auth_file = deluge.configmanager.get_config_dir('auth')
# Check for auth file and create if necessary
if not os.path.exists(auth_file):
with open(auth_file, "w") as _file:
with open(auth_file, 'w') as _file:
_file.flush()
os.fsync(_file.fileno())
# Change the permissions on the file so only this user can read/write it
@ -904,13 +904,13 @@ def create_localclient_account(append=False):
from hashlib import sha1 as sha
import deluge.configmanager
auth_file = deluge.configmanager.get_config_dir("auth")
auth_file = deluge.configmanager.get_config_dir('auth')
if not os.path.exists(auth_file):
create_auth_file()
with open(auth_file, "a" if append else "w") as _file:
_file.write(":".join([
"localclient",
with open(auth_file, 'a' if append else 'w') as _file:
_file.write(':'.join([
'localclient',
sha(str(random.random())).hexdigest(),
str(AUTH_LEVEL_ADMIN)
]) + '\n')
@ -1008,11 +1008,11 @@ def unicode_argv():
else:
# On other platforms, we have to find the likely encoding of the args and decode
# First check if sys.stdout or stdin have encoding set
encoding = getattr(sys.stdout, "encoding") or getattr(sys.stdin, "encoding")
encoding = getattr(sys.stdout, 'encoding') or getattr(sys.stdin, 'encoding')
# If that fails, check what the locale is set to
encoding = encoding or locale.getpreferredencoding()
# As a last resort, just default to utf-8
encoding = encoding or "utf-8"
encoding = encoding or 'utf-8'
return [arg.decode(encoding) for arg in sys.argv]
@ -1028,16 +1028,16 @@ def run_profiled(func, *args, **kwargs):
output_file (str, optional): Filename to save profile results. If None, print to stdout.
Defaults to None.
"""
if kwargs.get("do_profile", True) is not False:
if kwargs.get('do_profile', True) is not False:
import cProfile
profiler = cProfile.Profile()
def on_shutdown():
output_file = kwargs.get("output_file", None)
output_file = kwargs.get('output_file', None)
if output_file:
profiler.dump_stats(output_file)
log.info("Profile stats saved to %s", output_file)
print("Profile stats saved to %s" % output_file)
log.info('Profile stats saved to %s', output_file)
print('Profile stats saved to %s' % output_file)
else:
import pstats
import StringIO

View File

@ -31,7 +31,7 @@ class ComponentException(Exception):
def __str__(self):
s = super(ComponentException, self).__str__()
return "%s\n%s" % (s, "".join(self.tb))
return '%s\n%s' % (s, ''.join(self.tb))
def __eq__(self, other):
if isinstance(other, self.__class__):
@ -101,7 +101,7 @@ class Component(object):
self._component_name = name
self._component_interval = interval
self._component_depend = depend
self._component_state = "Stopped"
self._component_state = 'Stopped'
self._component_timer = None
self._component_starting_deferred = None
self._component_stopping_deferred = None
@ -112,34 +112,34 @@ class Component(object):
_ComponentRegistry.deregister(self)
def _component_start_timer(self):
if hasattr(self, "update"):
if hasattr(self, 'update'):
self._component_timer = LoopingCall(self.update)
self._component_timer.start(self._component_interval)
def _component_start(self):
def on_start(result):
self._component_state = "Started"
self._component_state = 'Started'
self._component_starting_deferred = None
self._component_start_timer()
return True
def on_start_fail(result):
self._component_state = "Stopped"
self._component_state = 'Stopped'
self._component_starting_deferred = None
log.error(result)
return fail(result)
if self._component_state == "Stopped":
if hasattr(self, "start"):
self._component_state = "Starting"
if self._component_state == 'Stopped':
if hasattr(self, 'start'):
self._component_state = 'Starting'
d = deferLater(reactor, 0, self.start)
d.addCallbacks(on_start, on_start_fail)
self._component_starting_deferred = d
else:
d = maybeDeferred(on_start, None)
elif self._component_state == "Starting":
elif self._component_state == 'Starting':
return self._component_starting_deferred
elif self._component_state == "Started":
elif self._component_state == 'Started':
d = succeed(True)
else:
d = fail(ComponentException("Trying to start a component ('%s') not in stopped state. Current state: '%s'" %
@ -148,20 +148,20 @@ class Component(object):
def _component_stop(self):
def on_stop(result):
self._component_state = "Stopped"
self._component_state = 'Stopped'
if self._component_timer and self._component_timer.running:
self._component_timer.stop()
return True
def on_stop_fail(result):
self._component_state = "Started"
self._component_state = 'Started'
self._component_stopping_deferred = None
log.error(result)
return result
if self._component_state != "Stopped" and self._component_state != "Stopping":
if hasattr(self, "stop"):
self._component_state = "Stopping"
if self._component_state != 'Stopped' and self._component_state != 'Stopping':
if hasattr(self, 'stop'):
self._component_state = 'Stopping'
d = maybeDeferred(self.stop)
d.addCallback(on_stop)
d.addErrback(on_stop_fail)
@ -169,22 +169,22 @@ class Component(object):
else:
d = maybeDeferred(on_stop, None)
if self._component_state == "Stopping":
if self._component_state == 'Stopping':
return self._component_stopping_deferred
return succeed(None)
def _component_pause(self):
def on_pause(result):
self._component_state = "Paused"
self._component_state = 'Paused'
if self._component_state == "Started":
if self._component_state == 'Started':
if self._component_timer and self._component_timer.running:
d = maybeDeferred(self._component_timer.stop)
d.addCallback(on_pause)
else:
d = succeed(None)
elif self._component_state == "Paused":
elif self._component_state == 'Paused':
d = succeed(None)
else:
d = fail(ComponentException("Trying to pause a component ('%s') not in started state. Current state: '%s'" %
@ -193,9 +193,9 @@ class Component(object):
def _component_resume(self):
def on_resume(result):
self._component_state = "Started"
self._component_state = 'Started'
if self._component_state == "Paused":
if self._component_state == 'Paused':
d = maybeDeferred(self._component_start_timer)
d.addCallback(on_resume)
else:
@ -205,7 +205,7 @@ class Component(object):
def _component_shutdown(self):
def on_stop(result):
if hasattr(self, "shutdown"):
if hasattr(self, 'shutdown'):
return maybeDeferred(self.shutdown)
return succeed(None)
@ -254,7 +254,7 @@ class ComponentRegistry(object):
"""
name = obj._component_name
if name in self.components:
raise ComponentAlreadyRegistered("Component already registered with name %s" % name)
raise ComponentAlreadyRegistered('Component already registered with name %s' % name)
self.components[obj._component_name] = obj
if obj._component_depend:
@ -273,7 +273,7 @@ class ComponentRegistry(object):
"""
if obj in self.components.values():
log.debug("Deregistering Component: %s", obj._component_name)
log.debug('Deregistering Component: %s', obj._component_name)
d = self.stop([obj._component_name])
def on_stop(result, name):
@ -377,7 +377,7 @@ class ComponentRegistry(object):
deferreds = []
for name in names:
if self.components[name]._component_state == "Started":
if self.components[name]._component_state == 'Started':
deferreds.append(self.components[name]._component_pause())
return DeferredList(deferreds)
@ -403,7 +403,7 @@ class ComponentRegistry(object):
deferreds = []
for name in names:
if self.components[name]._component_state == "Paused":
if self.components[name]._component_state == 'Paused':
deferreds.append(self.components[name]._component_resume())
return DeferredList(deferreds)

View File

@ -82,16 +82,16 @@ def find_json_objects(s):
"""
objects = []
opens = 0
start = s.find("{")
start = s.find('{')
offset = start
if start < 0:
return []
for index, c in enumerate(s[offset:]):
if c == "{":
if c == '{':
opens += 1
elif c == "}":
elif c == '}':
opens -= 1
if opens == 0:
objects.append((start, index + offset + 1))
@ -119,8 +119,8 @@ class Config(object):
# These hold the version numbers and they will be set when loaded
self.__version = {
"format": 1,
"file": file_version
'format': 1,
'file': file_version
}
# This will get set with a reactor.callLater whenever a config option
@ -186,7 +186,7 @@ class Config(object):
try:
oldtype = type(self.__config[key])
if isinstance(self.__config[key], unicode):
value = oldtype(value, "utf8")
value = oldtype(value, 'utf8')
else:
value = oldtype(value)
except ValueError:
@ -244,7 +244,7 @@ class Config(object):
"""
if isinstance(self.__config[key], str):
try:
return self.__config[key].decode("utf8")
return self.__config[key].decode('utf8')
except UnicodeDecodeError:
return self.__config[key]
else:
@ -342,7 +342,7 @@ class Config(object):
test 5
"""
log.debug("Registering function for %s key..", key)
log.debug('Registering function for %s key..', key)
if key not in self.__set_functions:
self.__set_functions[key] = []
@ -367,7 +367,7 @@ class Config(object):
test 5
"""
log.debug("Calling all set functions..")
log.debug('Calling all set functions..')
for key, value in self.__set_functions.iteritems():
for func in value:
func(key, self.__config[key])
@ -379,7 +379,7 @@ class Config(object):
key (str): the config key
"""
log.debug("Calling set functions for key %s..", key)
log.debug('Calling set functions for key %s..', key)
if key in self.__set_functions:
for func in self.__set_functions[key]:
func(key, self.__config[key])
@ -395,10 +395,10 @@ class Config(object):
filename = self.__config_file
try:
with open(filename, "rb") as _file:
with open(filename, 'rb') as _file:
data = _file.read()
except IOError as ex:
log.warning("Unable to open config file %s: %s", filename, ex)
log.warning('Unable to open config file %s: %s', filename, ex)
return
objects = find_json_objects(data)
@ -409,14 +409,14 @@ class Config(object):
self.__config.update(pickle.loads(data))
except Exception as ex:
log.exception(ex)
log.warning("Unable to load config file: %s", filename)
log.warning('Unable to load config file: %s', filename)
elif len(objects) == 1:
start, end = objects[0]
try:
self.__config.update(json.loads(data[start:end]))
except Exception as ex:
log.exception(ex)
log.warning("Unable to load config file: %s", filename)
log.warning('Unable to load config file: %s', filename)
elif len(objects) == 2:
try:
start, end = objects[0]
@ -425,10 +425,10 @@ class Config(object):
self.__config.update(json.loads(data[start:end]))
except Exception as ex:
log.exception(ex)
log.warning("Unable to load config file: %s", filename)
log.warning('Unable to load config file: %s', filename)
log.debug("Config %s version: %s.%s loaded: %s", filename,
self.__version["format"], self.__version["file"], self.__config)
log.debug('Config %s version: %s.%s loaded: %s', filename,
self.__version['format'], self.__version['file'], self.__config)
def save(self, filename=None):
"""Save configuration to disk
@ -445,7 +445,7 @@ class Config(object):
# Check to see if the current config differs from the one on disk
# We will only write a new config file if there is a difference
try:
with open(filename, "rb") as _file:
with open(filename, 'rb') as _file:
data = _file.read()
objects = find_json_objects(data)
start, end = objects[0]
@ -458,34 +458,34 @@ class Config(object):
self._save_timer.cancel()
return True
except (IOError, IndexError) as ex:
log.warning("Unable to open config file: %s because: %s", filename, ex)
log.warning('Unable to open config file: %s because: %s', filename, ex)
# Save the new config and make sure it's written to disk
try:
log.debug("Saving new config file %s", filename + ".new")
with open(filename + ".new", "wb") as _file:
log.debug('Saving new config file %s', filename + '.new')
with open(filename + '.new', 'wb') as _file:
json.dump(self.__version, _file, indent=2)
json.dump(self.__config, _file, indent=2, sort_keys=True)
_file.flush()
os.fsync(_file.fileno())
except IOError as ex:
log.error("Error writing new config file: %s", ex)
log.error('Error writing new config file: %s', ex)
return False
# Make a backup of the old config
try:
log.debug("Backing up old config file to %s.bak", filename)
shutil.move(filename, filename + ".bak")
log.debug('Backing up old config file to %s.bak', filename)
shutil.move(filename, filename + '.bak')
except IOError as ex:
log.warning("Unable to backup old config: %s", ex)
log.warning('Unable to backup old config: %s', ex)
# The new config file has been written successfully, so let's move it over
# the existing one.
try:
log.debug("Moving new config file %s to %s..", filename + ".new", filename)
shutil.move(filename + ".new", filename)
log.debug('Moving new config file %s to %s..', filename + '.new', filename)
shutil.move(filename + '.new', filename)
except IOError as ex:
log.error("Error moving new config file: %s", ex)
log.error('Error moving new config file: %s', ex)
return False
else:
return True
@ -508,22 +508,22 @@ class Config(object):
"""
if output_version in input_range or output_version <= max(input_range):
raise ValueError("output_version needs to be greater than input_range")
raise ValueError('output_version needs to be greater than input_range')
if self.__version["file"] not in input_range:
log.debug("File version %s is not in input_range %s, ignoring converter function..",
self.__version["file"], input_range)
if self.__version['file'] not in input_range:
log.debug('File version %s is not in input_range %s, ignoring converter function..',
self.__version['file'], input_range)
return
try:
self.__config = func(self.__config)
except Exception as ex:
log.exception(ex)
log.error("There was an exception try to convert config file %s %s to %s",
self.__config_file, self.__version["file"], output_version)
log.error('There was an exception try to convert config file %s %s to %s',
self.__config_file, self.__version['file'], output_version)
raise ex
else:
self.__version["file"] = output_version
self.__version['file'] = output_version
self.save()
@property

View File

@ -19,7 +19,7 @@ log = logging.getLogger(__name__)
class _ConfigManager(object):
def __init__(self):
log.debug("ConfigManager started..")
log.debug('ConfigManager started..')
self.config_files = {}
self.__config_directory = None
@ -44,16 +44,16 @@ class _ConfigManager(object):
if not directory:
return False
log.info("Setting config directory to: %s", directory)
log.info('Setting config directory to: %s', directory)
if not os.path.exists(directory):
# Try to create the config folder if it doesn't exist
try:
os.makedirs(directory)
except OSError as ex:
log.error("Unable to make config directory: %s", ex)
log.error('Unable to make config directory: %s', ex)
return False
elif not os.path.isdir(directory):
log.error("Config directory needs to be a directory!")
log.error('Config directory needs to be a directory!')
return False
self.__config_directory = directory

View File

@ -30,9 +30,9 @@ log = logging.getLogger(__name__)
class AlertManager(component.Component):
"""AlertManager fetches and processes libtorrent alerts"""
def __init__(self):
log.debug("AlertManager init...")
component.Component.__init__(self, "AlertManager", interval=0.3)
self.session = component.get("Core").session
log.debug('AlertManager init...')
component.Component.__init__(self, 'AlertManager', interval=0.3)
self.session = component.get('Core').session
# Increase the alert queue size so that alerts don't get lost.
self.alert_queue_size = 10000
@ -47,7 +47,7 @@ class AlertManager(component.Component):
lt.alert.category_t.performance_warning)
try:
self.session.apply_settings("alert_mask", alert_mask)
self.session.apply_settings('alert_mask', alert_mask)
except AttributeError:
self.session.set_alert_mask(alert_mask)
@ -81,7 +81,7 @@ class AlertManager(component.Component):
# Append the handler to the list in the handlers dictionary
self.handlers[alert_type].append(handler)
log.debug("Registered handler for alert %s", alert_type)
log.debug('Registered handler for alert %s', alert_type)
def deregister_handler(self, handler):
"""
@ -105,16 +105,16 @@ class AlertManager(component.Component):
num_alerts = len(alerts)
if log.isEnabledFor(logging.DEBUG):
log.debug("Alerts queued: %s", num_alerts)
log.debug('Alerts queued: %s', num_alerts)
if num_alerts > 0.9 * self.alert_queue_size:
log.warning("Warning total alerts queued, %s, passes 90%% of queue size.", num_alerts)
log.warning('Warning total alerts queued, %s, passes 90%% of queue size.', num_alerts)
# Loop through all alerts in the queue
for alert in alerts:
alert_type = type(alert).__name__
# Display the alert message
if log.isEnabledFor(logging.DEBUG):
log.debug("%s: %s", alert_type, decode_string(alert.message()))
log.debug('%s: %s', alert_type, decode_string(alert.message()))
# Call any handlers for this alert type
if alert_type in self.handlers:
for handler in self.handlers[alert_type]:
@ -122,6 +122,6 @@ class AlertManager(component.Component):
def set_alert_queue_size(self, queue_size):
"""Sets the maximum size of the libtorrent alert queue"""
log.info("Alert Queue Size set to %s", queue_size)
log.info('Alert Queue Size set to %s', queue_size)
self.alert_queue_size = queue_size
component.get("Core").apply_session_setting("alert_queue_size", self.alert_queue_size)
component.get('Core').apply_session_setting('alert_queue_size', self.alert_queue_size)

View File

@ -51,12 +51,12 @@ class Account(object):
def __repr__(self):
return ('<Account username="%(username)s" authlevel=%(authlevel)s>' %
{"username": self.username, "authlevel": self.authlevel})
{'username': self.username, 'authlevel': self.authlevel})
class AuthManager(component.Component):
def __init__(self):
component.Component.__init__(self, "AuthManager", interval=10)
component.Component.__init__(self, 'AuthManager', interval=10)
self.__auth = {}
self.__auth_modification_time = None
@ -70,16 +70,16 @@ class AuthManager(component.Component):
pass
def update(self):
auth_file = configmanager.get_config_dir("auth")
auth_file = configmanager.get_config_dir('auth')
# Check for auth file and create if necessary
if not os.path.isfile(auth_file):
log.info("Authfile not found, recreating it.")
log.info('Authfile not found, recreating it.')
self.__load_auth_file()
return
auth_file_modification_time = os.stat(auth_file).st_mtime
if self.__auth_modification_time != auth_file_modification_time:
log.info("Auth file changed, reloading it!")
log.info('Auth file changed, reloading it!')
self.__load_auth_file()
def authorize(self, username, password):
@ -99,22 +99,22 @@ class AuthManager(component.Component):
"""
if not username:
raise AuthenticationRequired(
"Username and Password are required.", username
'Username and Password are required.', username
)
if username not in self.__auth:
# Let's try to re-load the file.. Maybe it's been updated
self.__load_auth_file()
if username not in self.__auth:
raise BadLoginError("Username does not exist", username)
raise BadLoginError('Username does not exist', username)
if self.__auth[username].password == password:
# Return the users auth level
return self.__auth[username].authlevel
elif not password and self.__auth[username].password:
raise AuthenticationRequired("Password is required", username)
raise AuthenticationRequired('Password is required', username)
else:
raise BadLoginError("Password does not match", username)
raise BadLoginError('Password does not match', username)
def has_account(self, username):
return username in self.__auth
@ -126,7 +126,7 @@ class AuthManager(component.Component):
def create_account(self, username, password, authlevel):
if username in self.__auth:
raise AuthManagerError("Username in use.", username)
raise AuthManagerError('Username in use.', username)
if authlevel not in AUTH_LEVELS_MAPPING:
raise AuthManagerError("Invalid auth level: '%s'" % authlevel)
try:
@ -140,7 +140,7 @@ class AuthManager(component.Component):
def update_account(self, username, password, authlevel):
if username not in self.__auth:
raise AuthManagerError("Username not known", username)
raise AuthManagerError('Username not known', username)
if authlevel not in AUTH_LEVELS_MAPPING:
raise AuthManagerError("Invalid auth level: '%s'" % authlevel)
try:
@ -155,10 +155,10 @@ class AuthManager(component.Component):
def remove_account(self, username):
if username not in self.__auth:
raise AuthManagerError("Username not known", username)
elif username == component.get("RPCServer").get_session_user():
raise AuthManagerError('Username not known', username)
elif username == component.get('RPCServer').get_session_user():
raise AuthManagerError(
"You cannot delete your own account while logged in!", username
'You cannot delete your own account while logged in!', username
)
del self.__auth[username]
@ -166,39 +166,39 @@ class AuthManager(component.Component):
return True
def write_auth_file(self):
filename = "auth"
filename = 'auth'
filepath = os.path.join(configmanager.get_config_dir(), filename)
filepath_bak = filepath + ".bak"
filepath_tmp = filepath + ".tmp"
filepath_bak = filepath + '.bak'
filepath_tmp = filepath + '.tmp'
try:
if os.path.isfile(filepath):
log.debug("Creating backup of %s at: %s", filename, filepath_bak)
log.debug('Creating backup of %s at: %s', filename, filepath_bak)
shutil.copy2(filepath, filepath_bak)
except IOError as ex:
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
log.error('Unable to backup %s to %s: %s', filepath, filepath_bak, ex)
else:
log.info("Saving the %s at: %s", filename, filepath)
log.info('Saving the %s at: %s', filename, filepath)
try:
with open(filepath_tmp, "wb") as _file:
with open(filepath_tmp, 'wb') as _file:
for account in self.__auth.values():
_file.write("%(username)s:%(password)s:%(authlevel_int)s\n" % account.data())
_file.write('%(username)s:%(password)s:%(authlevel_int)s\n' % account.data())
_file.flush()
os.fsync(_file.fileno())
shutil.move(filepath_tmp, filepath)
except IOError as ex:
log.error("Unable to save %s: %s", filename, ex)
log.error('Unable to save %s: %s', filename, ex)
if os.path.isfile(filepath_bak):
log.info("Restoring backup of %s from: %s", filename, filepath_bak)
log.info('Restoring backup of %s from: %s', filename, filepath_bak)
shutil.move(filepath_bak, filepath)
self.__load_auth_file()
def __load_auth_file(self):
save_and_reload = False
filename = "auth"
filename = 'auth'
auth_file = configmanager.get_config_dir(filename)
auth_file_bak = auth_file + ".bak"
auth_file_bak = auth_file + '.bak'
# Check for auth file and create if necessary
if not os.path.isfile(auth_file):
@ -213,28 +213,28 @@ class AuthManager(component.Component):
return
for _filepath in (auth_file, auth_file_bak):
log.info("Opening %s for load: %s", filename, _filepath)
log.info('Opening %s for load: %s', filename, _filepath)
try:
with open(_filepath, "rb") as _file:
with open(_filepath, 'rb') as _file:
file_data = _file.readlines()
except IOError as ex:
log.warning("Unable to load %s: %s", _filepath, ex)
log.warning('Unable to load %s: %s', _filepath, ex)
file_data = []
else:
log.info("Successfully loaded %s: %s", filename, _filepath)
log.info('Successfully loaded %s: %s', filename, _filepath)
break
# Load the auth file into a dictionary: {username: Account(...)}
for line in file_data:
line = line.strip()
if line.startswith("#") or not line:
if line.startswith('#') or not line:
# This line is a comment or empty
continue
lsplit = line.split(":")
lsplit = line.split(':')
if len(lsplit) == 2:
username, password = lsplit
log.warning("Your auth entry for %s contains no auth level, "
"using AUTH_LEVEL_DEFAULT(%s)..", username, AUTH_LEVEL_DEFAULT)
log.warning('Your auth entry for %s contains no auth level, '
'using AUTH_LEVEL_DEFAULT(%s)..', username, AUTH_LEVEL_DEFAULT)
if username == 'localclient':
authlevel = AUTH_LEVEL_ADMIN
else:
@ -244,7 +244,7 @@ class AuthManager(component.Component):
elif len(lsplit) == 3:
username, password, authlevel = lsplit
else:
log.error("Your auth file is malformed: Incorrect number of fields!")
log.error('Your auth file is malformed: Incorrect number of fields!')
continue
username = username.strip()
@ -255,16 +255,16 @@ class AuthManager(component.Component):
try:
authlevel = AUTH_LEVELS_MAPPING[authlevel]
except KeyError:
log.error("Your auth file is malformed: %r is not a valid auth level", authlevel)
log.error('Your auth file is malformed: %r is not a valid auth level', authlevel)
continue
self.__auth[username] = Account(username, password, authlevel)
if "localclient" not in self.__auth:
if 'localclient' not in self.__auth:
create_localclient_account(True)
return self.__load_auth_file()
if save_and_reload:
log.info("Re-writing auth file (upgrade)")
log.info('Re-writing auth file (upgrade)')
self.write_auth_file()
self.__auth_modification_time = auth_file_modification_time

View File

@ -44,22 +44,22 @@ log = logging.getLogger(__name__)
class Core(component.Component):
def __init__(self, listen_interface=None, read_only_config_keys=None):
log.debug("Core init...")
component.Component.__init__(self, "Core")
log.debug('Core init...')
component.Component.__init__(self, 'Core')
# These keys will be dropped from the set_config() RPC and are
# configurable from the command-line.
self.read_only_config_keys = read_only_config_keys
log.debug("read_only_config_keys: %s", read_only_config_keys)
log.debug('read_only_config_keys: %s', read_only_config_keys)
# Create the client fingerprint
client_id = "DE"
client_id = 'DE'
client_version = deluge.common.VersionSplit(deluge.common.get_version()).version
while len(client_version) < 4:
client_version.append(0)
# Start the libtorrent session
log.info("Starting libtorrent %s (%s, %s) session...", lt.__version__, client_id, client_version)
log.info('Starting libtorrent %s (%s, %s) session...', lt.__version__, client_id, client_version)
self.session = lt.session(lt.fingerprint(client_id, *client_version), flags=0)
# Load the session state if available
@ -67,20 +67,20 @@ class Core(component.Component):
# Apply session settings
self.apply_session_setting(
"user_agent",
"Deluge/%(deluge_version)s libtorrent/%(lt_version)s" % {
'user_agent',
'Deluge/%(deluge_version)s libtorrent/%(lt_version)s' % {
'deluge_version': deluge.common.get_version(),
'lt_version': self.get_libtorrent_version().rpartition(".")[0]}
'lt_version': self.get_libtorrent_version().rpartition('.')[0]}
)
# No SSL torrent support in code so disable the listen port.
self.apply_session_setting("ssl_listen", 0)
self.apply_session_setting('ssl_listen', 0)
# Enable libtorrent extensions
# Allows peers to download the metadata from the swarm directly
self.session.add_extension("ut_metadata")
self.session.add_extension('ut_metadata')
# Ban peers that sends bad data
self.session.add_extension("smart_ban")
self.session.add_extension('smart_ban')
# Create the components
self.eventmanager = EventManager()
@ -96,13 +96,13 @@ class Core(component.Component):
# External IP Address from libtorrent
self.external_ip = None
self.eventmanager.register_event_handler("ExternalIPEvent", self._on_external_ip_event)
self.eventmanager.register_event_handler('ExternalIPEvent', self._on_external_ip_event)
# GeoIP instance with db loaded
self.geoip_instance = None
# Get the core config
self.config = ConfigManager("core.conf")
self.config = ConfigManager('core.conf')
self.config.save()
# If there was an interface value from the command line, use it, but
@ -110,10 +110,10 @@ class Core(component.Component):
self.__old_interface = None
if listen_interface:
if deluge.common.is_ip(listen_interface):
self.__old_interface = self.config["listen_interface"]
self.config["listen_interface"] = listen_interface
self.__old_interface = self.config['listen_interface']
self.config['listen_interface'] = listen_interface
else:
log.error("Invalid listen interface (must be IP Address): %s", listen_interface)
log.error('Invalid listen interface (must be IP Address): %s', listen_interface)
# New release check information
self.__new_release = None
@ -123,14 +123,14 @@ class Core(component.Component):
pass
def stop(self):
log.debug("Core stopping...")
log.debug('Core stopping...')
# Save the libtorrent session state
self.__save_session_state()
# We stored a copy of the old interface value
if self.__old_interface:
self.config["listen_interface"] = self.__old_interface
self.config['listen_interface'] = self.__old_interface
# Make sure the config file has been saved
self.config.save()
@ -156,64 +156,64 @@ class Core(component.Component):
def __save_session_state(self):
"""Saves the libtorrent session state"""
filename = "session.state"
filename = 'session.state'
filepath = get_config_dir(filename)
filepath_bak = filepath + ".bak"
filepath_tmp = filepath + ".tmp"
filepath_bak = filepath + '.bak'
filepath_tmp = filepath + '.tmp'
try:
if os.path.isfile(filepath):
log.debug("Creating backup of %s at: %s", filename, filepath_bak)
log.debug('Creating backup of %s at: %s', filename, filepath_bak)
shutil.copy2(filepath, filepath_bak)
except IOError as ex:
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
log.error('Unable to backup %s to %s: %s', filepath, filepath_bak, ex)
else:
log.info("Saving the %s at: %s", filename, filepath)
log.info('Saving the %s at: %s', filename, filepath)
try:
with open(filepath_tmp, "wb") as _file:
with open(filepath_tmp, 'wb') as _file:
_file.write(lt.bencode(self.session.save_state()))
_file.flush()
os.fsync(_file.fileno())
shutil.move(filepath_tmp, filepath)
except (IOError, EOFError) as ex:
log.error("Unable to save %s: %s", filename, ex)
log.error('Unable to save %s: %s', filename, ex)
if os.path.isfile(filepath_bak):
log.info("Restoring backup of %s from: %s", filename, filepath_bak)
log.info('Restoring backup of %s from: %s', filename, filepath_bak)
shutil.move(filepath_bak, filepath)
def __load_session_state(self):
"""Loads the libtorrent session state"""
filename = "session.state"
filename = 'session.state'
filepath = get_config_dir(filename)
filepath_bak = filepath + ".bak"
filepath_bak = filepath + '.bak'
for _filepath in (filepath, filepath_bak):
log.info("Opening %s for load: %s", filename, _filepath)
log.info('Opening %s for load: %s', filename, _filepath)
try:
with open(_filepath, "rb") as _file:
with open(_filepath, 'rb') as _file:
state = lt.bdecode(_file.read())
except (IOError, EOFError, RuntimeError) as ex:
log.warning("Unable to load %s: %s", _filepath, ex)
log.warning('Unable to load %s: %s', _filepath, ex)
else:
log.info("Successfully loaded %s: %s", filename, _filepath)
log.info('Successfully loaded %s: %s', filename, _filepath)
self.session.load_state(state)
return
def get_new_release(self):
log.debug("get_new_release")
log.debug('get_new_release')
from urllib2 import urlopen, URLError
try:
self.new_release = urlopen("http://download.deluge-torrent.org/version-1.0").read().strip()
self.new_release = urlopen('http://download.deluge-torrent.org/version-1.0').read().strip()
except URLError as ex:
log.debug("Unable to get release info from website: %s", ex)
log.debug('Unable to get release info from website: %s', ex)
return
self.check_new_release()
def check_new_release(self):
if self.new_release:
log.debug("new_release: %s", self.new_release)
log.debug('new_release: %s', self.new_release)
if deluge.common.VersionSplit(self.new_release) > deluge.common.VersionSplit(deluge.common.get_version()):
component.get("EventManager").emit(NewVersionAvailableEvent(self.new_release))
component.get('EventManager').emit(NewVersionAvailableEvent(self.new_release))
return self.new_release
return False
@ -233,14 +233,14 @@ class Core(component.Component):
try:
filedump = base64.decodestring(filedump)
except Exception as ex:
log.error("There was an error decoding the filedump string: %s", ex)
log.error('There was an error decoding the filedump string: %s', ex)
try:
d = self.torrentmanager.add(
filedump=filedump, options=options, filename=filename, save_state=save_state
)
except RuntimeError as ex:
log.error("There was an error adding the torrent file %s: %s", filename, ex)
log.error('There was an error adding the torrent file %s: %s', filename, ex)
raise
else:
return d
@ -301,11 +301,11 @@ class Core(component.Component):
:returns: a Deferred which returns the torrent_id as a str or None
"""
log.info("Attempting to add url %s", url)
log.info('Attempting to add url %s', url)
def on_download_success(filename):
# We got the file, so add it to the session
with open(filename, "rb") as _file:
with open(filename, 'rb') as _file:
data = _file.read()
try:
os.remove(filename)
@ -315,7 +315,7 @@ class Core(component.Component):
def on_download_fail(failure):
# Log the error and pass the failure onto the client
log.error("Failed to add torrent from url %s", url)
log.error('Failed to add torrent from url %s', url)
return failure
tmp_fd, tmp_file = tempfile.mkstemp(prefix='deluge_url.', suffix='.torrent')
@ -338,7 +338,7 @@ class Core(component.Component):
:rtype: string
"""
log.debug("Attempting to add by magnet uri: %s", uri)
log.debug('Attempting to add by magnet uri: %s', uri)
return self.torrentmanager.add(magnet=uri, options=options)
@ -357,7 +357,7 @@ class Core(component.Component):
InvalidTorrentError: If the torrent ID does not exist in the session.
"""
log.debug("Removing torrent %s from the core.", torrent_id)
log.debug('Removing torrent %s from the core.', torrent_id)
return self.torrentmanager.remove(torrent_id, remove_data)
@export
@ -375,7 +375,7 @@ class Core(component.Component):
[("<torrent_id>", "Error removing torrent")]
"""
log.info("Removing %d torrents from core.", len(torrent_ids))
log.info('Removing %d torrents from core.', len(torrent_ids))
def do_remove_torrents():
errors = []
@ -387,7 +387,7 @@ class Core(component.Component):
# Save the session state
self.torrentmanager.save_state()
if errors:
log.warn("Failed to remove %d of %d torrents.", len(errors), len(torrent_ids))
log.warn('Failed to remove %d of %d torrents.', len(errors), len(torrent_ids))
return errors
return task.deferLater(reactor, 0, do_remove_torrents)
@ -426,55 +426,55 @@ class Core(component.Component):
status = self.session.get_cache_status()
cache = {}
for attr in dir(status):
if attr.startswith("_"):
if attr.startswith('_'):
continue
cache[attr] = getattr(status, attr)
# Add in a couple ratios
try:
cache["write_hit_ratio"] = (cache["blocks_written"] - cache["writes"]) / cache["blocks_written"]
cache['write_hit_ratio'] = (cache['blocks_written'] - cache['writes']) / cache['blocks_written']
except ZeroDivisionError:
cache["write_hit_ratio"] = 0.0
cache['write_hit_ratio'] = 0.0
try:
cache["read_hit_ratio"] = cache["blocks_read_hit"] / cache["blocks_read"]
cache['read_hit_ratio'] = cache['blocks_read_hit'] / cache['blocks_read']
except ZeroDivisionError:
cache["read_hit_ratio"] = 0.0
cache['read_hit_ratio'] = 0.0
return cache
@export
def force_reannounce(self, torrent_ids):
log.debug("Forcing reannouncment to: %s", torrent_ids)
log.debug('Forcing reannouncment to: %s', torrent_ids)
for torrent_id in torrent_ids:
self.torrentmanager[torrent_id].force_reannounce()
@export
def pause_torrent(self, torrent_ids):
log.debug("Pausing: %s", torrent_ids)
log.debug('Pausing: %s', torrent_ids)
for torrent_id in torrent_ids:
if not self.torrentmanager[torrent_id].pause():
log.warning("Error pausing torrent %s", torrent_id)
log.warning('Error pausing torrent %s', torrent_id)
@export
def connect_peer(self, torrent_id, ip, port):
log.debug("adding peer %s to %s", ip, torrent_id)
log.debug('adding peer %s to %s', ip, torrent_id)
if not self.torrentmanager[torrent_id].connect_peer(ip, port):
log.warning("Error adding peer %s:%s to %s", ip, port, torrent_id)
log.warning('Error adding peer %s:%s to %s', ip, port, torrent_id)
@export
def move_storage(self, torrent_ids, dest):
log.debug("Moving storage %s to %s", torrent_ids, dest)
log.debug('Moving storage %s to %s', torrent_ids, dest)
for torrent_id in torrent_ids:
if not self.torrentmanager[torrent_id].move_storage(dest):
log.warning("Error moving torrent %s to %s", torrent_id, dest)
log.warning('Error moving torrent %s to %s', torrent_id, dest)
@export
def pause_session(self):
"""Pause all torrents in the session"""
if not self.session.is_paused():
self.session.pause()
component.get("EventManager").emit(SessionPausedEvent())
component.get('EventManager').emit(SessionPausedEvent())
@export
def resume_session(self):
@ -483,11 +483,11 @@ class Core(component.Component):
self.session.resume()
for torrent_id in self.torrentmanager.torrents:
self.torrentmanager[torrent_id].update_state()
component.get("EventManager").emit(SessionResumedEvent())
component.get('EventManager').emit(SessionResumedEvent())
@export
def resume_torrent(self, torrent_ids):
log.debug("Resuming: %s", torrent_ids)
log.debug('Resuming: %s', torrent_ids)
for torrent_id in torrent_ids:
self.torrentmanager[torrent_id].resume()
@ -566,7 +566,7 @@ class Core(component.Component):
if self.read_only_config_keys and key in self.read_only_config_keys:
continue
if isinstance(config[key], basestring):
config[key] = config[key].encode("utf8")
config[key] = config[key].encode('utf8')
self.config[key] = config[key]
@export
@ -578,7 +578,7 @@ class Core(component.Component):
def get_i2p_proxy(self):
"""Returns the active listen port"""
i2p_settings = self.session.i2p_proxy() # Deprecated, moved to proxy types
i2p_dict = {"hostname": i2p_settings.hostname, "port": i2p_settings.port}
i2p_dict = {'hostname': i2p_settings.hostname, 'port': i2p_settings.port}
return i2p_dict
@export
@ -586,13 +586,13 @@ class Core(component.Component):
"""Returns the active listen port"""
proxy_settings = self.session.proxy()
proxy_dict = {
"type": int(proxy_settings.type),
"hostname": proxy_settings.hostname,
"username": proxy_settings.username,
"password": proxy_settings.password,
"port": proxy_settings.port,
"proxy_hostnames": proxy_settings.proxy_hostnames,
"proxy_peer_connections": proxy_settings.proxy_peer_connections
'type': int(proxy_settings.type),
'hostname': proxy_settings.hostname,
'username': proxy_settings.username,
'password': proxy_settings.password,
'port': proxy_settings.port,
'proxy_hostnames': proxy_settings.proxy_hostnames,
'proxy_peer_connections': proxy_settings.proxy_peer_connections
}
return proxy_dict
@ -733,7 +733,7 @@ class Core(component.Component):
def create_torrent(self, path, tracker, piece_length, comment, target,
webseeds, private, created_by, trackers, add_to_session):
log.debug("creating torrent..")
log.debug('creating torrent..')
threading.Thread(target=self._create_torrent_thread,
args=(
path,
@ -760,11 +760,11 @@ class Core(component.Component):
private=private,
created_by=created_by,
trackers=trackers)
log.debug("torrent created!")
log.debug('torrent created!')
if add_to_session:
options = {}
options["download_location"] = os.path.split(path)[0]
with open(target, "rb") as _file:
options['download_location'] = os.path.split(path)[0]
with open(target, 'rb') as _file:
self.add_torrent_file(os.path.split(target)[1], _file.read(), options)
@export
@ -777,20 +777,20 @@ class Core(component.Component):
try:
filedump = base64.decodestring(filedump)
except Exception as ex:
log.error("There was an error decoding the filedump string!")
log.error('There was an error decoding the filedump string!')
log.exception(ex)
return
with open(os.path.join(get_config_dir(), "plugins", filename), "wb") as _file:
with open(os.path.join(get_config_dir(), 'plugins', filename), 'wb') as _file:
_file.write(filedump)
component.get("CorePluginManager").scan_for_plugins()
component.get('CorePluginManager').scan_for_plugins()
@export
def rescan_plugins(self):
"""
Rescans the plugin folders for new plugins
"""
component.get("CorePluginManager").scan_for_plugins()
component.get('CorePluginManager').scan_for_plugins()
@export
def rename_files(self, torrent_id, filenames):
@ -808,7 +808,7 @@ class Core(component.Component):
"""
if torrent_id not in self.torrentmanager.torrents:
raise InvalidTorrentError("torrent_id is not in session")
raise InvalidTorrentError('torrent_id is not in session')
def rename():
self.torrentmanager[torrent_id].rename_files(filenames)
@ -833,25 +833,25 @@ class Core(component.Component):
"""
if torrent_id not in self.torrentmanager.torrents:
raise InvalidTorrentError("torrent_id is not in session")
raise InvalidTorrentError('torrent_id is not in session')
return self.torrentmanager[torrent_id].rename_folder(folder, new_folder)
@export
def queue_top(self, torrent_ids):
log.debug("Attempting to queue %s to top", torrent_ids)
log.debug('Attempting to queue %s to top', torrent_ids)
# torrent_ids must be sorted in reverse before moving to preserve order
for torrent_id in sorted(torrent_ids, key=self.torrentmanager.get_queue_position, reverse=True):
try:
# If the queue method returns True, then we should emit a signal
if self.torrentmanager.queue_top(torrent_id):
component.get("EventManager").emit(TorrentQueueChangedEvent())
component.get('EventManager').emit(TorrentQueueChangedEvent())
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
log.warning('torrent_id: %s does not exist in the queue', torrent_id)
@export
def queue_up(self, torrent_ids):
log.debug("Attempting to queue %s to up", torrent_ids)
log.debug('Attempting to queue %s to up', torrent_ids)
torrents = ((self.torrentmanager.get_queue_position(torrent_id), torrent_id) for torrent_id in torrent_ids)
torrent_moved = True
prev_queue_position = None
@ -862,16 +862,16 @@ class Core(component.Component):
try:
torrent_moved = self.torrentmanager.queue_up(torrent_id)
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
log.warning('torrent_id: %s does not exist in the queue', torrent_id)
# If the torrent moved, then we should emit a signal
if torrent_moved:
component.get("EventManager").emit(TorrentQueueChangedEvent())
component.get('EventManager').emit(TorrentQueueChangedEvent())
else:
prev_queue_position = queue_position
@export
def queue_down(self, torrent_ids):
log.debug("Attempting to queue %s to down", torrent_ids)
log.debug('Attempting to queue %s to down', torrent_ids)
torrents = ((self.torrentmanager.get_queue_position(torrent_id), torrent_id) for torrent_id in torrent_ids)
torrent_moved = True
prev_queue_position = None
@ -882,24 +882,24 @@ class Core(component.Component):
try:
torrent_moved = self.torrentmanager.queue_down(torrent_id)
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
log.warning('torrent_id: %s does not exist in the queue', torrent_id)
# If the torrent moved, then we should emit a signal
if torrent_moved:
component.get("EventManager").emit(TorrentQueueChangedEvent())
component.get('EventManager').emit(TorrentQueueChangedEvent())
else:
prev_queue_position = queue_position
@export
def queue_bottom(self, torrent_ids):
log.debug("Attempting to queue %s to bottom", torrent_ids)
log.debug('Attempting to queue %s to bottom', torrent_ids)
# torrent_ids must be sorted before moving to preserve order
for torrent_id in sorted(torrent_ids, key=self.torrentmanager.get_queue_position):
try:
# If the queue method returns True, then we should emit a signal
if self.torrentmanager.queue_bottom(torrent_id):
component.get("EventManager").emit(TorrentQueueChangedEvent())
component.get('EventManager').emit(TorrentQueueChangedEvent())
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
log.warning('torrent_id: %s does not exist in the queue', torrent_id)
@export
def glob(self, path):
@ -914,14 +914,14 @@ class Core(component.Component):
:rtype: bool
"""
d = getPage("http://deluge-torrent.org/test_port.php?port=%s" %
d = getPage('http://deluge-torrent.org/test_port.php?port=%s' %
self.get_listen_port(), timeout=30)
def on_get_page(result):
return bool(int(result))
def on_error(failure):
log.warning("Error testing listen port: %s", failure)
log.warning('Error testing listen port: %s', failure)
d.addCallback(on_get_page)
d.addErrback(on_error)
@ -943,7 +943,7 @@ class Core(component.Component):
"""
if not path:
path = self.config["download_location"]
path = self.config['download_location']
try:
return deluge.common.free_space(path)
except InvalidPathError:

View File

@ -43,7 +43,7 @@ def is_daemon_running(pid_file):
try:
with open(pid_file) as _file:
pid, port = [int(x) for x in _file.readline().strip().split(";")]
pid, port = [int(x) for x in _file.readline().strip().split(';')]
except EnvironmentError:
return False
@ -51,7 +51,7 @@ def is_daemon_running(pid_file):
# Ensure it's a deluged process by trying to open a socket to it's port.
_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
_socket.connect(("127.0.0.1", port))
_socket.connect(('127.0.0.1', port))
except socket.error:
# Can't connect, so pid is not a deluged process.
return False
@ -77,19 +77,19 @@ class Daemon(object):
altered by core.set_config() RPC method.
"""
self.standalone = standalone
self.pid_file = get_config_dir("deluged.pid")
log.info("Deluge daemon %s", get_version())
self.pid_file = get_config_dir('deluged.pid')
log.info('Deluge daemon %s', get_version())
if is_daemon_running(self.pid_file):
raise DaemonRunningError("Deluge daemon already running with this config directory!")
raise DaemonRunningError('Deluge daemon already running with this config directory!')
# Twisted catches signals to terminate, so just have it call the shutdown method.
reactor.addSystemEventTrigger("before", "shutdown", self._shutdown)
reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
# Catch some Windows specific signals
if windows_check():
def win_handler(ctrl_type):
"""Handle the Windows shutdown or close events."""
log.debug("windows handler ctrl_type: %s", ctrl_type)
log.debug('windows handler ctrl_type: %s', ctrl_type)
if ctrl_type == CTRL_CLOSE_EVENT or ctrl_type == CTRL_SHUTDOWN_EVENT:
self._shutdown()
return 1
@ -100,21 +100,21 @@ class Daemon(object):
read_only_config_keys=read_only_config_keys)
if port is None:
port = self.core.config["daemon_port"]
port = self.core.config['daemon_port']
self.port = port
if interface and not is_ip(interface):
log.error("Invalid UI interface (must be IP Address): %s", interface)
log.error('Invalid UI interface (must be IP Address): %s', interface)
interface = None
self.rpcserver = RPCServer(
port=port,
allow_remote=self.core.config["allow_remote"],
allow_remote=self.core.config['allow_remote'],
listen=not standalone,
interface=interface
)
log.debug("Listening to UI on: %s:%s and bittorrent on: %s", interface, port, listen_interface)
log.debug('Listening to UI on: %s:%s and bittorrent on: %s', interface, port, listen_interface)
def start(self):
# Register the daemon and the core RPCs
@ -122,32 +122,32 @@ class Daemon(object):
self.rpcserver.register_object(self)
# Make sure we start the PreferencesManager first
component.start("PreferencesManager")
component.start('PreferencesManager')
if not self.standalone:
log.info("Deluge daemon starting...")
log.info('Deluge daemon starting...')
# Create pid file to track if deluged is running, also includes the port number.
pid = os.getpid()
log.debug("Storing pid %s & port %s in: %s", pid, self.port, self.pid_file)
with open(self.pid_file, "wb") as _file:
_file.write("%s;%s\n" % (pid, self.port))
log.debug('Storing pid %s & port %s in: %s', pid, self.port, self.pid_file)
with open(self.pid_file, 'wb') as _file:
_file.write('%s;%s\n' % (pid, self.port))
component.start()
try:
reactor.run()
finally:
log.debug("Remove pid file: %s", self.pid_file)
log.debug('Remove pid file: %s', self.pid_file)
os.remove(self.pid_file)
log.info("Deluge daemon shutdown successfully")
log.info('Deluge daemon shutdown successfully')
@export()
def shutdown(self, *args, **kwargs):
log.debug("Deluge daemon shutdown requested...")
log.debug('Deluge daemon shutdown requested...')
reactor.callLater(0, reactor.stop)
def _shutdown(self, *args, **kwargs):
log.info("Deluge daemon shutting down, waiting for components to shutdown...")
log.info('Deluge daemon shutting down, waiting for components to shutdown...')
if not self.standalone:
return component.shutdown()

View File

@ -20,15 +20,15 @@ from deluge.ui.util import lang
def add_daemon_options(parser):
group = parser.add_argument_group(_("Daemon Options"))
group.add_argument("-u", "--ui-interface", metavar="<ip-addr>", action="store",
help=_("IP address to listen for UI connections"))
group.add_argument("-p", "--port", metavar="<port>", action="store", type=int,
help=_("Port to listen for UI connections on"))
group.add_argument("-i", "--interface", metavar="<ip-addr>", dest="listen_interface", action="store",
help=_("IP address to listen for BitTorrent connections"))
group.add_argument("--read-only-config-keys", metavar="<comma-separated-keys>", action="store",
help=_("Config keys to be unmodified by `set_config` RPC"), type=str, default="")
group = parser.add_argument_group(_('Daemon Options'))
group.add_argument('-u', '--ui-interface', metavar='<ip-addr>', action='store',
help=_('IP address to listen for UI connections'))
group.add_argument('-p', '--port', metavar='<port>', action='store', type=int,
help=_('Port to listen for UI connections on'))
group.add_argument('-i', '--interface', metavar='<ip-addr>', dest='listen_interface', action='store',
help=_('IP address to listen for BitTorrent connections'))
group.add_argument('--read-only-config-keys', metavar='<comma-separated-keys>', action='store',
help=_('Config keys to be unmodified by `set_config` RPC'), type=str, default='')
parser.add_process_arg_group()
@ -53,17 +53,17 @@ def start_daemon(skip_start=False):
# Check for any daemons running with this same config
from deluge.core.daemon import is_daemon_running
pid_file = get_config_dir("deluged.pid")
pid_file = get_config_dir('deluged.pid')
if is_daemon_running(pid_file):
print("Cannot run multiple daemons using the same config directory.\n"
"If you believe this is an error, you can force a start by deleting: %s" % pid_file)
print('Cannot run multiple daemons using the same config directory.\n'
'If you believe this is an error, you can force a start by deleting: %s' % pid_file)
sys.exit(1)
log = getLogger(__name__)
# If no logfile specified add logging to default location (as well as stdout)
if not options.logfile:
options.logfile = get_config_dir("deluged.log")
options.logfile = get_config_dir('deluged.log')
file_handler = FileHandler(options.logfile)
log.addHandler(file_handler)
@ -73,7 +73,7 @@ def start_daemon(skip_start=False):
daemon = Daemon(listen_interface=options.listen_interface,
interface=options.ui_interface,
port=options.port,
read_only_config_keys=options.read_only_config_keys.split(","))
read_only_config_keys=options.read_only_config_keys.split(','))
if skip_start:
return daemon
else:

View File

@ -16,7 +16,7 @@ log = logging.getLogger(__name__)
class EventManager(component.Component):
def __init__(self):
component.Component.__init__(self, "EventManager")
component.Component.__init__(self, 'EventManager')
self.handlers = {}
def emit(self, event):
@ -26,7 +26,7 @@ class EventManager(component.Component):
:param event: DelugeEvent
"""
# Emit the event to the interested clients
component.get("RPCServer").emit_event(event)
component.get('RPCServer').emit_event(event)
# Call any handlers for the event
if event.name in self.handlers:
for handler in self.handlers[event.name]:
@ -34,7 +34,7 @@ class EventManager(component.Component):
try:
handler(*event.args)
except Exception as ex:
log.error("Event handler %s failed in %s with exception %s", event.name, handler, ex)
log.error('Event handler %s failed in %s with exception %s', event.name, handler, ex)
def register_event_handler(self, event, handler):
"""

View File

@ -14,14 +14,14 @@ from deluge.common import TORRENT_STATE
log = logging.getLogger(__name__)
STATE_SORT = ["All", "Active"] + TORRENT_STATE
STATE_SORT = ['All', 'Active'] + TORRENT_STATE
# Special purpose filters:
def filter_keywords(torrent_ids, values):
# Cleanup
keywords = ",".join([v.lower() for v in values])
keywords = keywords.split(",")
keywords = ','.join([v.lower() for v in values])
keywords = keywords.split(',')
for keyword in keywords:
torrent_ids = filter_one_keyword(torrent_ids, keyword)
@ -33,7 +33,7 @@ def filter_one_keyword(torrent_ids, keyword):
search torrent on keyword.
searches title,state,tracker-status,tracker,files
"""
all_torrents = component.get("TorrentManager").torrents
all_torrents = component.get('TorrentManager').torrents
for torrent_id in torrent_ids:
torrent = all_torrents[torrent_id]
@ -41,7 +41,7 @@ def filter_one_keyword(torrent_ids, keyword):
yield torrent_id
elif keyword in torrent.state.lower():
yield torrent_id
elif torrent.trackers and keyword in torrent.trackers[0]["url"]:
elif torrent.trackers and keyword in torrent.trackers[0]['url']:
yield torrent_id
elif keyword in torrent_id:
yield torrent_id
@ -50,13 +50,13 @@ def filter_one_keyword(torrent_ids, keyword):
yield torrent_id
else:
for t_file in torrent.get_files():
if keyword in t_file["path"].lower():
if keyword in t_file['path'].lower():
yield torrent_id
break
def filter_by_name(torrent_ids, search_string):
all_torrents = component.get("TorrentManager").torrents
all_torrents = component.get('TorrentManager').torrents
try:
search_string, match_case = search_string[0].split('::match')
except ValueError:
@ -79,18 +79,18 @@ def filter_by_name(torrent_ids, search_string):
def tracker_error_filter(torrent_ids, values):
filtered_torrent_ids = []
tm = component.get("TorrentManager")
tm = component.get('TorrentManager')
# If this is a tracker_host, then we need to filter on it
if values[0] != "Error":
if values[0] != 'Error':
for torrent_id in torrent_ids:
if values[0] == tm[torrent_id].get_status(["tracker_host"])["tracker_host"]:
if values[0] == tm[torrent_id].get_status(['tracker_host'])['tracker_host']:
filtered_torrent_ids.append(torrent_id)
return filtered_torrent_ids
# Check torrent's tracker_status for 'Error:' and return those torrent_ids
for torrent_id in torrent_ids:
if "Error:" in tm[torrent_id].get_status(["tracker_status"])["tracker_status"]:
if 'Error:' in tm[torrent_id].get_status(['tracker_status'])['tracker_status']:
filtered_torrent_ids.append(torrent_id)
return filtered_torrent_ids
@ -100,26 +100,26 @@ class FilterManager(component.Component):
"""
def __init__(self, core):
component.Component.__init__(self, "FilterManager")
log.debug("FilterManager init..")
component.Component.__init__(self, 'FilterManager')
log.debug('FilterManager init..')
self.core = core
self.torrents = core.torrentmanager
self.registered_filters = {}
self.register_filter("keyword", filter_keywords)
self.register_filter("name", filter_by_name)
self.register_filter('keyword', filter_keywords)
self.register_filter('name', filter_by_name)
self.tree_fields = {}
self.register_tree_field("state", self._init_state_tree)
self.register_tree_field('state', self._init_state_tree)
def _init_tracker_tree():
return {"Error": 0}
self.register_tree_field("tracker_host", _init_tracker_tree)
return {'Error': 0}
self.register_tree_field('tracker_host', _init_tracker_tree)
self.register_filter("tracker_host", tracker_error_filter)
self.register_filter('tracker_host', tracker_error_filter)
def _init_users_tree():
return {"": 0}
self.register_tree_field("owner", _init_users_tree)
return {'': 0}
self.register_tree_field('owner', _init_users_tree)
def filter_torrent_ids(self, filter_dict):
"""
@ -135,9 +135,9 @@ class FilterManager(component.Component):
filter_dict[key] = [value]
# Optimized filter for id
if "id" in filter_dict:
torrent_ids = list(filter_dict["id"])
del filter_dict["id"]
if 'id' in filter_dict:
torrent_ids = list(filter_dict['id'])
del filter_dict['id']
else:
torrent_ids = self.torrents.get_torrent_list()
@ -146,14 +146,14 @@ class FilterManager(component.Component):
return torrent_ids
# Special purpose, state=Active.
if "state" in filter_dict:
if 'state' in filter_dict:
# We need to make sure this is a list for the logic below
filter_dict["state"] = list(filter_dict["state"])
filter_dict['state'] = list(filter_dict['state'])
if "state" in filter_dict and "Active" in filter_dict["state"]:
filter_dict["state"].remove("Active")
if not filter_dict["state"]:
del filter_dict["state"]
if 'state' in filter_dict and 'Active' in filter_dict['state']:
filter_dict['state'].remove('Active')
if not filter_dict['state']:
del filter_dict['state']
torrent_ids = self.filter_state_active(torrent_ids)
if not filter_dict:
@ -200,12 +200,12 @@ class FilterManager(component.Component):
value = status[field]
items[field][value] = items[field].get(value, 0) + 1
if "tracker_host" in items:
items["tracker_host"]["All"] = len(torrent_ids)
items["tracker_host"]["Error"] = len(tracker_error_filter(torrent_ids, ("Error",)))
if 'tracker_host' in items:
items['tracker_host']['All'] = len(torrent_ids)
items['tracker_host']['Error'] = len(tracker_error_filter(torrent_ids, ('Error',)))
if not show_zero_hits:
for cat in ["state", "owner", "tracker_host"]:
for cat in ['state', 'owner', 'tracker_host']:
if cat in tree_keys:
self._hide_state_items(items[cat])
@ -214,17 +214,17 @@ class FilterManager(component.Component):
for field in tree_keys:
sorted_items[field] = sorted(items[field].iteritems())
if "state" in tree_keys:
sorted_items["state"].sort(self._sort_state_items)
if 'state' in tree_keys:
sorted_items['state'].sort(self._sort_state_items)
return sorted_items
def _init_state_tree(self):
init_state = {}
init_state["All"] = len(self.torrents.get_torrent_list())
init_state['All'] = len(self.torrents.get_torrent_list())
for state in TORRENT_STATE:
init_state[state] = 0
init_state["Active"] = len(self.filter_state_active(self.torrents.get_torrent_list()))
init_state['Active'] = len(self.filter_state_active(self.torrents.get_torrent_list()))
return init_state
def register_filter(self, filter_id, filter_func, filter_value=None):
@ -242,8 +242,8 @@ class FilterManager(component.Component):
def filter_state_active(self, torrent_ids):
for torrent_id in list(torrent_ids):
status = self.torrents[torrent_id].get_status(["download_payload_rate", "upload_payload_rate"])
if status["download_payload_rate"] or status["upload_payload_rate"]:
status = self.torrents[torrent_id].get_status(['download_payload_rate', 'upload_payload_rate'])
if status['download_payload_rate'] or status['upload_payload_rate']:
pass
else:
torrent_ids.remove(torrent_id)
@ -252,7 +252,7 @@ class FilterManager(component.Component):
def _hide_state_items(self, state_items):
"""For hide(show)-zero hits"""
for (value, count) in state_items.items():
if value != "All" and count == 0:
if value != 'All' and count == 0:
del state_items[value]
def _sort_state_items(self, x, y):

View File

@ -26,13 +26,13 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, component.Compon
functions to access parts of the core."""
def __init__(self, core):
component.Component.__init__(self, "CorePluginManager")
component.Component.__init__(self, 'CorePluginManager')
self.status_fields = {}
# Call the PluginManagerBase constructor
deluge.pluginmanagerbase.PluginManagerBase.__init__(
self, "core.conf", "deluge.plugin.core")
self, 'core.conf', 'deluge.plugin.core')
def start(self):
# Enable plugins that are enabled in the config
@ -47,7 +47,7 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, component.Compon
def update_plugins(self):
for plugin in self.plugins:
if hasattr(self.plugins[plugin], "update"):
if hasattr(self.plugins[plugin], 'update'):
try:
self.plugins[plugin].update()
except Exception as ex:
@ -60,7 +60,7 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, component.Compon
def on_enable_plugin(result):
if result is True and name in self.plugins:
component.get("EventManager").emit(PluginEnabledEvent(name))
component.get('EventManager').emit(PluginEnabledEvent(name))
return result
d.addBoth(on_enable_plugin)
@ -73,7 +73,7 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, component.Compon
def on_disable_plugin(result):
if name not in self.plugins:
component.get("EventManager").emit(PluginDisabledEvent(name))
component.get('EventManager').emit(PluginDisabledEvent(name))
return result
d.addBoth(on_disable_plugin)
return d
@ -93,13 +93,13 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, component.Compon
def register_status_field(self, field, function):
"""Register a new status field. This can be used in the same way the
client requests other status information from core."""
log.debug("Registering status field %s with PluginManager", field)
log.debug('Registering status field %s with PluginManager', field)
self.status_fields[field] = function
def deregister_status_field(self, field):
"""Deregisters a status field"""
log.debug("Deregistering status field %s with PluginManager", field)
log.debug('Deregistering status field %s with PluginManager', field)
try:
del self.status_fields[field]
except Exception:
log.warning("Unable to deregister status field %s", field)
log.warning('Unable to deregister status field %s', field)

View File

@ -29,119 +29,119 @@ except ImportError:
log = logging.getLogger(__name__)
DEFAULT_PREFS = {
"send_info": False,
"info_sent": 0.0,
"daemon_port": 58846,
"allow_remote": False,
"pre_allocate_storage": False,
"download_location": deluge.common.get_default_download_dir(),
"listen_ports": [6881, 6891],
"listen_interface": "",
"random_port": True,
"listen_random_port": None,
"listen_use_sys_port": False,
"listen_reuse_port": True,
"outgoing_ports": [0, 0],
"random_outgoing_ports": True,
"copy_torrent_file": False,
"del_copy_torrent_file": False,
"torrentfiles_location": deluge.common.get_default_download_dir(),
"plugins_location": os.path.join(deluge.configmanager.get_config_dir(), "plugins"),
"prioritize_first_last_pieces": False,
"sequential_download": False,
"dht": True,
"upnp": True,
"natpmp": True,
"utpex": True,
"lsd": True,
"enc_in_policy": 1,
"enc_out_policy": 1,
"enc_level": 2,
"max_connections_global": 200,
"max_upload_speed": -1.0,
"max_download_speed": -1.0,
"max_upload_slots_global": 4,
"max_half_open_connections": (lambda: deluge.common.windows_check() and
'send_info': False,
'info_sent': 0.0,
'daemon_port': 58846,
'allow_remote': False,
'pre_allocate_storage': False,
'download_location': deluge.common.get_default_download_dir(),
'listen_ports': [6881, 6891],
'listen_interface': '',
'random_port': True,
'listen_random_port': None,
'listen_use_sys_port': False,
'listen_reuse_port': True,
'outgoing_ports': [0, 0],
'random_outgoing_ports': True,
'copy_torrent_file': False,
'del_copy_torrent_file': False,
'torrentfiles_location': deluge.common.get_default_download_dir(),
'plugins_location': os.path.join(deluge.configmanager.get_config_dir(), 'plugins'),
'prioritize_first_last_pieces': False,
'sequential_download': False,
'dht': True,
'upnp': True,
'natpmp': True,
'utpex': True,
'lsd': True,
'enc_in_policy': 1,
'enc_out_policy': 1,
'enc_level': 2,
'max_connections_global': 200,
'max_upload_speed': -1.0,
'max_download_speed': -1.0,
'max_upload_slots_global': 4,
'max_half_open_connections': (lambda: deluge.common.windows_check() and
(lambda: deluge.common.vista_check() and 4 or 8)() or 50)(),
"max_connections_per_second": 20,
"ignore_limits_on_local_network": True,
"max_connections_per_torrent": -1,
"max_upload_slots_per_torrent": -1,
"max_upload_speed_per_torrent": -1,
"max_download_speed_per_torrent": -1,
"enabled_plugins": [],
"add_paused": False,
"max_active_seeding": 5,
"max_active_downloading": 3,
"max_active_limit": 8,
"dont_count_slow_torrents": False,
"queue_new_to_top": False,
"stop_seed_at_ratio": False,
"remove_seed_at_ratio": False,
"stop_seed_ratio": 2.00,
"share_ratio_limit": 2.00,
"seed_time_ratio_limit": 7.00,
"seed_time_limit": 180,
"auto_managed": True,
"move_completed": False,
"move_completed_path": deluge.common.get_default_download_dir(),
"move_completed_paths_list": [],
"download_location_paths_list": [],
"path_chooser_show_chooser_button_on_localhost": True,
"path_chooser_auto_complete_enabled": True,
"path_chooser_accelerator_string": "Tab",
"path_chooser_max_popup_rows": 20,
"path_chooser_show_hidden_files": False,
"new_release_check": True,
"proxy": {
"type": 0,
"hostname": "",
"username": "",
"password": "",
"port": 8080,
"proxy_hostnames": True,
"proxy_peer_connections": True,
'max_connections_per_second': 20,
'ignore_limits_on_local_network': True,
'max_connections_per_torrent': -1,
'max_upload_slots_per_torrent': -1,
'max_upload_speed_per_torrent': -1,
'max_download_speed_per_torrent': -1,
'enabled_plugins': [],
'add_paused': False,
'max_active_seeding': 5,
'max_active_downloading': 3,
'max_active_limit': 8,
'dont_count_slow_torrents': False,
'queue_new_to_top': False,
'stop_seed_at_ratio': False,
'remove_seed_at_ratio': False,
'stop_seed_ratio': 2.00,
'share_ratio_limit': 2.00,
'seed_time_ratio_limit': 7.00,
'seed_time_limit': 180,
'auto_managed': True,
'move_completed': False,
'move_completed_path': deluge.common.get_default_download_dir(),
'move_completed_paths_list': [],
'download_location_paths_list': [],
'path_chooser_show_chooser_button_on_localhost': True,
'path_chooser_auto_complete_enabled': True,
'path_chooser_accelerator_string': 'Tab',
'path_chooser_max_popup_rows': 20,
'path_chooser_show_hidden_files': False,
'new_release_check': True,
'proxy': {
'type': 0,
'hostname': '',
'username': '',
'password': '',
'port': 8080,
'proxy_hostnames': True,
'proxy_peer_connections': True,
},
"i2p_proxy": {
"hostname": "",
"port": 0
'i2p_proxy': {
'hostname': '',
'port': 0
},
"peer_tos": "0x00",
"rate_limit_ip_overhead": True,
"anonymous_mode": False,
"geoip_db_location": "/usr/share/GeoIP/GeoIP.dat",
"cache_size": 512,
"cache_expiry": 60,
"auto_manage_prefer_seeds": False,
"shared": False,
"super_seeding": False,
"priority": 0
'peer_tos': '0x00',
'rate_limit_ip_overhead': True,
'anonymous_mode': False,
'geoip_db_location': '/usr/share/GeoIP/GeoIP.dat',
'cache_size': 512,
'cache_expiry': 60,
'auto_manage_prefer_seeds': False,
'shared': False,
'super_seeding': False,
'priority': 0
}
class PreferencesManager(component.Component):
def __init__(self):
component.Component.__init__(self, "PreferencesManager")
self.config = deluge.configmanager.ConfigManager("core.conf", DEFAULT_PREFS)
if "proxies" in self.config:
component.Component.__init__(self, 'PreferencesManager')
self.config = deluge.configmanager.ConfigManager('core.conf', DEFAULT_PREFS)
if 'proxies' in self.config:
log.warning("Updating config file for proxy, using 'peer' values to fill new 'proxy' setting")
self.config["proxy"].update(self.config["proxies"]['peer'])
log.warning("New proxy config is: %s", self.config["proxy"])
del self.config["proxies"]
self.config['proxy'].update(self.config['proxies']['peer'])
log.warning('New proxy config is: %s', self.config['proxy'])
del self.config['proxies']
self.core = component.get("Core")
self.session = component.get("Core").session
self.core = component.get('Core')
self.session = component.get('Core').session
self.new_release_timer = None
def start(self):
# Setup listen port followed by dht to ensure both use same port.
self.__set_listen_on()
self._on_set_dht("dht", self.config["dht"])
self._on_set_dht('dht', self.config['dht'])
# Set the initial preferences on start-up
for key in DEFAULT_PREFS:
# Listen port and dht already setup in correct order so skip running again.
if key in ("dht", "random_port") or key.startswith("listen_"):
if key in ('dht', 'random_port') or key.startswith('listen_'):
continue
self.do_config_set_func(key, self.config[key])
@ -153,10 +153,10 @@ class PreferencesManager(component.Component):
# Config set functions
def do_config_set_func(self, key, value):
on_set_func = getattr(self, "_on_set_" + key, None)
on_set_func = getattr(self, '_on_set_' + key, None)
if on_set_func:
if log.isEnabledFor(logging.DEBUG):
log.debug("Config key: %s set to %s..", key, value)
log.debug('Config key: %s set to %s..', key, value)
on_set_func(key, value)
def session_set_setting(self, key, value):
@ -164,27 +164,27 @@ class PreferencesManager(component.Component):
self.session.apply_settings({key: value})
except AttributeError:
# Deprecated in libtorrent 1.1
if key in ("enable_lsd", "enable_upnp", "enable_natpmp", "enable_dht"):
start_stop = key.replace("enable", "start") if value else key.replace("enable", "stop")
if key in ('enable_lsd', 'enable_upnp', 'enable_natpmp', 'enable_dht'):
start_stop = key.replace('enable', 'start') if value else key.replace('enable', 'stop')
getattr(self.session, start_stop)()
elif key == "dht_bootstrap_nodes":
self.session.add_dht_router("router.bittorrent.com", 6881)
self.session.add_dht_router("router.utorrent.com", 6881)
self.session.add_dht_router("router.bitcomet.com", 6881)
elif key == 'dht_bootstrap_nodes':
self.session.add_dht_router('router.bittorrent.com', 6881)
self.session.add_dht_router('router.utorrent.com', 6881)
self.session.add_dht_router('router.bitcomet.com', 6881)
else:
self.session.set_settings({key: value})
def _on_config_value_change(self, key, value):
if self.get_state() == "Started":
if self.get_state() == 'Started':
self.do_config_set_func(key, value)
component.get("EventManager").emit(ConfigValueChangedEvent(key, value))
component.get('EventManager').emit(ConfigValueChangedEvent(key, value))
def _on_set_torrentfiles_location(self, key, value):
if self.config["copy_torrent_file"]:
if self.config['copy_torrent_file']:
try:
os.makedirs(value)
except OSError as ex:
log.debug("Unable to make directory: %s", ex)
log.debug('Unable to make directory: %s', ex)
def _on_set_listen_ports(self, key, value):
self.__set_listen_on()
@ -197,35 +197,35 @@ class PreferencesManager(component.Component):
def __set_listen_on(self):
""" Set the ports and interface address to listen for incoming connections on."""
if self.config["random_port"]:
if not self.config["listen_random_port"]:
self.config["listen_random_port"] = random.randrange(49152, 65525)
listen_ports = [self.config["listen_random_port"]] * 2 # use single port range
if self.config['random_port']:
if not self.config['listen_random_port']:
self.config['listen_random_port'] = random.randrange(49152, 65525)
listen_ports = [self.config['listen_random_port']] * 2 # use single port range
else:
self.config["listen_random_port"] = None
listen_ports = self.config["listen_ports"]
self.config['listen_random_port'] = None
listen_ports = self.config['listen_ports']
interface = str(self.config["listen_interface"].strip())
interface = str(self.config['listen_interface'].strip())
log.debug("Listen Interface: %s, Ports: %s with use_sys_port: %s",
interface, listen_ports, self.config["listen_use_sys_port"])
log.debug('Listen Interface: %s, Ports: %s with use_sys_port: %s',
interface, listen_ports, self.config['listen_use_sys_port'])
try:
interfaces = ["%s:%s" % (interface, port) for port in range(listen_ports[0], listen_ports[1]+1)]
self.session.apply_setting({"listen_system_port_fallback", self.config["listen_use_sys_port"]})
self.session.apply_setting({"listen_interfaces", interfaces})
interfaces = ['%s:%s' % (interface, port) for port in range(listen_ports[0], listen_ports[1]+1)]
self.session.apply_setting({'listen_system_port_fallback', self.config['listen_use_sys_port']})
self.session.apply_setting({'listen_interfaces', interfaces})
except AttributeError:
# Deprecated in libtorrent 1.1
# If a single port range then always enable re-use port flag.
reuse_port = True if listen_ports[0] == listen_ports[1] else self.config["listen_reuse_port"]
reuse_port = True if listen_ports[0] == listen_ports[1] else self.config['listen_reuse_port']
flags = ((lt.listen_on_flags_t.listen_no_system_port
if not self.config["listen_use_sys_port"] else 0) |
if not self.config['listen_use_sys_port'] else 0) |
(lt.listen_on_flags_t.listen_reuse_address
if reuse_port else 0))
try:
self.session.listen_on(listen_ports[0], listen_ports[1], interface, flags)
except RuntimeError as ex:
if ex.message == "Invalid Argument":
log.error("Error setting listen interface (must be IP Address): %s %s-%s",
if ex.message == 'Invalid Argument':
log.error('Error setting listen interface (must be IP Address): %s %s-%s',
interface, listen_ports[0], listen_ports[1])
def _on_set_outgoing_ports(self, key, value):
@ -235,34 +235,34 @@ class PreferencesManager(component.Component):
self.__set_outgoing_ports()
def __set_outgoing_ports(self):
ports = [0, 0] if self.config["random_outgoing_ports"] else self.config["outgoing_ports"]
log.debug("Outgoing ports set to %s", ports)
self.session_set_setting("outgoing_ports", (ports[0], ports[1]))
ports = [0, 0] if self.config['random_outgoing_ports'] else self.config['outgoing_ports']
log.debug('Outgoing ports set to %s', ports)
self.session_set_setting('outgoing_ports', (ports[0], ports[1]))
def _on_set_peer_tos(self, key, value):
try:
self.session_set_setting("peer_tos", chr(int(value, 16)))
self.session_set_setting('peer_tos', chr(int(value, 16)))
except ValueError as ex:
log.debug("Invalid tos byte: %s", ex)
log.debug('Invalid tos byte: %s', ex)
return
def _on_set_dht(self, key, value):
dht_bootstraps = "router.bittorrent.com:6881,router.utorrent.com:6881,router.bitcomet.com:6881"
self.session_set_setting("dht_bootstrap_nodes", dht_bootstraps)
self.session_set_setting("enable_dht", value)
dht_bootstraps = 'router.bittorrent.com:6881,router.utorrent.com:6881,router.bitcomet.com:6881'
self.session_set_setting('dht_bootstrap_nodes', dht_bootstraps)
self.session_set_setting('enable_dht', value)
def _on_set_upnp(self, key, value):
self.session_set_setting("enable_upnp", value)
self.session_set_setting('enable_upnp', value)
def _on_set_natpmp(self, key, value):
self.session_set_setting("enable_natpmp", value)
self.session_set_setting('enable_natpmp', value)
def _on_set_lsd(self, key, value):
self.session_set_setting("enable_lsd", value)
self.session_set_setting('enable_lsd', value)
def _on_set_utpex(self, key, value):
if value:
self.session.add_extension("ut_pex")
self.session.add_extension('ut_pex')
def _on_set_enc_in_policy(self, key, value):
self._on_set_encryption(key, value)
@ -277,76 +277,76 @@ class PreferencesManager(component.Component):
# Convert Deluge enc_level values to libtorrent enc_level values.
pe_enc_level = {0: lt.enc_level.plaintext, 1: lt.enc_level.rc4, 2: lt.enc_level.both}
try:
self.session.apply_setting("out_enc_policy", lt.enc_policy(self.config["enc_out_policy"]))
self.session.apply_setting("in_enc_policy", lt.enc_policy(self.config["enc_in_policy"]))
self.session.apply_setting("allowed_enc_level", lt.enc_level(pe_enc_level[self.config["enc_level"]]))
self.session.apply_setting("prefer_rc4", True)
self.session.apply_setting('out_enc_policy', lt.enc_policy(self.config['enc_out_policy']))
self.session.apply_setting('in_enc_policy', lt.enc_policy(self.config['enc_in_policy']))
self.session.apply_setting('allowed_enc_level', lt.enc_level(pe_enc_level[self.config['enc_level']]))
self.session.apply_setting('prefer_rc4', True)
except AttributeError:
# Deprecated in libtorrent 1.1
pe_settings = lt.pe_settings()
pe_settings.out_enc_policy = lt.enc_policy(self.config["enc_out_policy"])
pe_settings.in_enc_policy = lt.enc_policy(self.config["enc_in_policy"])
pe_settings.allowed_enc_level = lt.enc_level(pe_enc_level[self.config["enc_level"]])
pe_settings.out_enc_policy = lt.enc_policy(self.config['enc_out_policy'])
pe_settings.in_enc_policy = lt.enc_policy(self.config['enc_in_policy'])
pe_settings.allowed_enc_level = lt.enc_level(pe_enc_level[self.config['enc_level']])
pe_settings.prefer_rc4 = True
self.session.set_pe_settings(pe_settings)
pe_sess_settings = self.session.get_pe_settings()
log.debug("encryption settings:\n\t\t\tout_policy: %s\n\t\t\
in_policy: %s\n\t\t\tlevel: %s\n\t\t\tprefer_rc4: %s",
log.debug('encryption settings:\n\t\t\tout_policy: %s\n\t\t\
in_policy: %s\n\t\t\tlevel: %s\n\t\t\tprefer_rc4: %s',
pe_sess_settings.out_enc_policy,
pe_sess_settings.in_enc_policy,
pe_sess_settings.allowed_enc_level,
pe_sess_settings.prefer_rc4)
def _on_set_max_connections_global(self, key, value):
self.session_set_setting("connections_limit", value)
self.session_set_setting('connections_limit', value)
def _on_set_max_upload_speed(self, key, value):
# We need to convert Kb/s to B/s
value = -1 if value < 0 else int(value * 1024)
self.session_set_setting("upload_rate_limit", value)
self.session_set_setting('upload_rate_limit', value)
def _on_set_max_download_speed(self, key, value):
# We need to convert Kb/s to B/s
value = -1 if value < 0 else int(value * 1024)
self.session_set_setting("download_rate_limit", value)
self.session_set_setting('download_rate_limit', value)
def _on_set_max_upload_slots_global(self, key, value):
self.session_set_setting("unchoke_slots_limit", value)
self.session_set_setting('unchoke_slots_limit', value)
def _on_set_max_half_open_connections(self, key, value):
self.session_set_setting("half_open_limit", value)
self.session_set_setting('half_open_limit', value)
def _on_set_max_connections_per_second(self, key, value):
self.session_set_setting("connection_speed", value)
self.session_set_setting('connection_speed', value)
def _on_set_ignore_limits_on_local_network(self, key, value):
self.session_set_setting("ignore_limits_on_local_network", value)
self.session_set_setting('ignore_limits_on_local_network', value)
def _on_set_share_ratio_limit(self, key, value):
self.session_set_setting("share_ratio_limit", value)
self.session_set_setting('share_ratio_limit', value)
def _on_set_seed_time_ratio_limit(self, key, value):
self.session_set_setting("seed_time_ratio_limit", value)
self.session_set_setting('seed_time_ratio_limit', value)
def _on_set_seed_time_limit(self, key, value):
# This value is stored in minutes in deluge, but libtorrent wants seconds
self.session_set_setting("seed_time_limit", int(value * 60))
self.session_set_setting('seed_time_limit', int(value * 60))
def _on_set_max_active_downloading(self, key, value):
self.session_set_setting("active_downloads", value)
self.session_set_setting('active_downloads', value)
def _on_set_max_active_seeding(self, key, value):
self.session_set_setting("active_seeds", value)
self.session_set_setting('active_seeds', value)
def _on_set_max_active_limit(self, key, value):
self.session_set_setting("active_limit", value)
self.session_set_setting('active_limit', value)
def _on_set_dont_count_slow_torrents(self, key, value):
self.session_set_setting("dont_count_slow_torrents", value)
self.session_set_setting('dont_count_slow_torrents', value)
def _on_set_send_info(self, key, value):
"""sends anonymous stats home"""
log.debug("Sending anonymous stats..")
log.debug('Sending anonymous stats..')
class SendInfoThread(threading.Thread):
def __init__(self, config):
@ -357,33 +357,33 @@ class PreferencesManager(component.Component):
import time
now = time.time()
# check if we've done this within the last week or never
if (now - self.config["info_sent"]) >= (60 * 60 * 24 * 7):
if (now - self.config['info_sent']) >= (60 * 60 * 24 * 7):
from urllib import quote_plus
from urllib2 import urlopen
import platform
try:
url = "http://deluge-torrent.org/stats_get.php?processor=" + \
platform.machine() + "&python=" + platform.python_version() \
+ "&deluge=" + deluge.common.get_version() \
+ "&os=" + platform.system() \
+ "&plugins=" + quote_plus(":".join(self.config["enabled_plugins"]))
url = 'http://deluge-torrent.org/stats_get.php?processor=' + \
platform.machine() + '&python=' + platform.python_version() \
+ '&deluge=' + deluge.common.get_version() \
+ '&os=' + platform.system() \
+ '&plugins=' + quote_plus(':'.join(self.config['enabled_plugins']))
urlopen(url)
except IOError as ex:
log.debug("Network error while trying to send info: %s", ex)
log.debug('Network error while trying to send info: %s', ex)
else:
self.config["info_sent"] = now
self.config['info_sent'] = now
if value:
SendInfoThread(self.config).start()
def _on_set_new_release_check(self, key, value):
if value:
log.debug("Checking for new release..")
log.debug('Checking for new release..')
threading.Thread(target=self.core.get_new_release).start()
if self.new_release_timer and self.new_release_timer.running:
self.new_release_timer.stop()
# Set a timer to check for a new release every 3 days
self.new_release_timer = LoopingCall(
self._on_set_new_release_check, "new_release_check", True)
self._on_set_new_release_check, 'new_release_check', True)
self.new_release_timer.start(72 * 60 * 60, False)
else:
if self.new_release_timer and self.new_release_timer.running:
@ -391,46 +391,46 @@ class PreferencesManager(component.Component):
def _on_set_proxy(self, key, value):
try:
if key == "i2p_proxy":
self.session.apply_settings("proxy_type", lt.proxy_type("i2p_proxy"))
self.session.apply_settings("i2p_hostname", value["hostname"])
self.session.apply_settings("i2p_port", value["port"])
if key == 'i2p_proxy':
self.session.apply_settings('proxy_type', lt.proxy_type('i2p_proxy'))
self.session.apply_settings('i2p_hostname', value['hostname'])
self.session.apply_settings('i2p_port', value['port'])
else:
self.session.apply_settings("proxy_type", lt.proxy_type(value["type"]))
self.session.apply_settings("proxy_hostname", value["hostname"])
self.session.apply_settings("proxy_port", value["port"])
self.session.apply_settings("proxy_username", value["username"])
self.session.apply_settings("proxy_password", value["password"])
self.session.apply_settings("proxy_hostnames", value["proxy_hostnames"])
self.session.apply_settings("proxy_peer_connections", value["proxy_peer_connections"])
self.session.apply_settings("proxy_tracker_connections", value["proxy_tracker_connections"])
self.session.apply_settings('proxy_type', lt.proxy_type(value['type']))
self.session.apply_settings('proxy_hostname', value['hostname'])
self.session.apply_settings('proxy_port', value['port'])
self.session.apply_settings('proxy_username', value['username'])
self.session.apply_settings('proxy_password', value['password'])
self.session.apply_settings('proxy_hostnames', value['proxy_hostnames'])
self.session.apply_settings('proxy_peer_connections', value['proxy_peer_connections'])
self.session.apply_settings('proxy_tracker_connections', value['proxy_tracker_connections'])
except AttributeError:
proxy_settings = lt.proxy_settings()
proxy_settings.hostname = value["hostname"]
proxy_settings.port = value["port"]
if key == "i2p_proxy":
proxy_settings.hostname = value['hostname']
proxy_settings.port = value['port']
if key == 'i2p_proxy':
try:
self.session.set_i2p_proxy(proxy_settings)
except RuntimeError as ex:
log.error("Unable to set I2P Proxy: %s", ex)
log.error('Unable to set I2P Proxy: %s', ex)
else:
proxy_settings.type = lt.proxy_type(value["type"])
proxy_settings.username = value["username"]
proxy_settings.password = value["password"]
proxy_settings.hostname = value["hostname"]
proxy_settings.port = value["port"]
proxy_settings.proxy_hostnames = value["proxy_hostnames"]
proxy_settings.proxy_peer_connections = value["proxy_peer_connections"]
proxy_settings.type = lt.proxy_type(value['type'])
proxy_settings.username = value['username']
proxy_settings.password = value['password']
proxy_settings.hostname = value['hostname']
proxy_settings.port = value['port']
proxy_settings.proxy_hostnames = value['proxy_hostnames']
proxy_settings.proxy_peer_connections = value['proxy_peer_connections']
self.session.set_proxy(proxy_settings)
def _on_set_i2p_proxy(self, key, value):
self._on_set_proxy(key, value)
def _on_set_rate_limit_ip_overhead(self, key, value):
self.session_set_setting("rate_limit_ip_overhead", value)
self.session_set_setting('rate_limit_ip_overhead', value)
def _on_set_anonymous_mode(self, key, value):
self.session_set_setting("anonymous_mode", value)
self.session_set_setting('anonymous_mode', value)
def _on_set_geoip_db_location(self, key, geoipdb_path):
# Load the GeoIP DB for country look-ups if available
@ -438,15 +438,15 @@ class PreferencesManager(component.Component):
try:
self.core.geoip_instance = GeoIP.open(geoipdb_path, GeoIP.GEOIP_STANDARD)
except AttributeError:
log.warning("GeoIP Unavailable")
log.warning('GeoIP Unavailable')
else:
log.warning("Unable to find GeoIP database file: %s", geoipdb_path)
log.warning('Unable to find GeoIP database file: %s', geoipdb_path)
def _on_set_cache_size(self, key, value):
self.session_set_setting("cache_size", value)
self.session_set_setting('cache_size', value)
def _on_set_cache_expiry(self, key, value):
self.session_set_setting("cache_expiry", value)
self.session_set_setting('cache_expiry', value)
def _on_auto_manage_prefer_seeds(self, key, value):
self.session_set_setting("auto_manage_prefer_seeds", value)
self.session_set_setting('auto_manage_prefer_seeds', value)

View File

@ -49,7 +49,7 @@ def export(auth_level=AUTH_LEVEL_DEFAULT):
func._rpcserver_export = True
func._rpcserver_auth_level = auth_level
doc = func.__doc__
func.__doc__ = "**RPC Exported Function** (*Auth Level: %s*)\n\n" % auth_level
func.__doc__ = '**RPC Exported Function** (*Auth Level: %s*)\n\n' % auth_level
if doc:
func.__doc__ += doc
@ -75,16 +75,16 @@ def format_request(call):
"""
try:
s = call[1] + "("
s = call[1] + '('
if call[2]:
s += ", ".join([str(x) for x in call[2]])
s += ', '.join([str(x) for x in call[2]])
if call[3]:
if call[2]:
s += ", "
s += ", ".join([key + "=" + str(value) for key, value in call[3].items()])
s += ")"
s += ', '
s += ', '.join([key + '=' + str(value) for key, value in call[3].items()])
s += ')'
except UnicodeEncodeError:
return "UnicodeEncodeError, call: %s" % call
return 'UnicodeEncodeError, call: %s' % call
else:
return s
@ -97,11 +97,11 @@ class ServerContextFactory(object):
This loads the servers cert/private key SSL files for use with the
SSL transport.
"""
ssl_dir = deluge.configmanager.get_config_dir("ssl")
ssl_dir = deluge.configmanager.get_config_dir('ssl')
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3)
ctx.use_certificate_file(os.path.join(ssl_dir, "daemon.cert"))
ctx.use_privatekey_file(os.path.join(ssl_dir, "daemon.pkey"))
ctx.use_certificate_file(os.path.join(ssl_dir, 'daemon.cert'))
ctx.use_privatekey_file(os.path.join(ssl_dir, 'daemon.pkey'))
return ctx
@ -118,17 +118,17 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
"""
if not isinstance(request, tuple):
log.debug("Received invalid message: type is not tuple")
log.debug('Received invalid message: type is not tuple')
return
if len(request) < 1:
log.debug("Received invalid message: there are no items")
log.debug('Received invalid message: there are no items')
return
for call in request:
if len(call) != 4:
log.debug("Received invalid rpc request: number of items "
"in request is %s", len(call))
log.debug('Received invalid rpc request: number of items '
'in request is %s', len(call))
continue
# log.debug("RPCRequest: %s", format_request(call))
reactor.callLater(0, self.dispatch, *call)
@ -145,7 +145,7 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
try:
self.transfer_message(data)
except Exception as ex:
log.warn("Error occurred when sending message: %s.", ex)
log.warn('Error occurred when sending message: %s.', ex)
log.exception(ex)
raise
@ -154,7 +154,7 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
This method is called when a new client connects.
"""
peer = self.transport.getPeer()
log.info("Deluge Client connection made from: %s:%s",
log.info('Deluge Client connection made from: %s:%s',
peer.host, peer.port)
# Set the initial auth level of this session to AUTH_LEVEL_NONE
self.factory.authorized_sessions[self.transport.sessionno] = AUTH_LEVEL_NONE
@ -175,9 +175,9 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
if self.transport.sessionno in self.factory.interested_events:
del self.factory.interested_events[self.transport.sessionno]
if self.factory.state == "running":
component.get("EventManager").emit(ClientDisconnectedEvent(self.factory.session_id))
log.info("Deluge client disconnected: %s", reason.value)
if self.factory.state == 'running':
component.get('EventManager').emit(ClientDisconnectedEvent(self.factory.session_id))
log.info('Deluge client disconnected: %s', reason.value)
def valid_session(self):
return self.transport.sessionno in self.factory.authorized_sessions
@ -215,29 +215,29 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
))
except AttributeError:
# This is not a deluge exception (object has no attribute '_args), let's wrap it
log.warning("An exception occurred while sending RPC_ERROR to "
"client. Wrapping it and resending. Error to "
"send(causing exception goes next):\n%s", formated_tb)
log.warning('An exception occurred while sending RPC_ERROR to '
'client. Wrapping it and resending. Error to '
'send(causing exception goes next):\n%s', formated_tb)
try:
raise WrappedException(str(exceptionValue), exceptionType.__name__, formated_tb)
except WrappedException:
send_error()
except Exception as ex:
log.error("An exception occurred while sending RPC_ERROR to client: %s", ex)
log.error('An exception occurred while sending RPC_ERROR to client: %s', ex)
if method == "daemon.info":
if method == 'daemon.info':
# This is a special case and used in the initial connection process
self.sendData((RPC_RESPONSE, request_id, deluge.common.get_version()))
return
elif method == "daemon.login":
elif method == 'daemon.login':
# This is a special case and used in the initial connection process
# We need to authenticate the user here
log.debug("RPC dispatch daemon.login")
log.debug('RPC dispatch daemon.login')
try:
client_version = kwargs.pop('client_version', None)
if client_version is None:
raise IncompatibleClient(deluge.common.get_version())
ret = component.get("AuthManager").authorize(*args, **kwargs)
ret = component.get('AuthManager').authorize(*args, **kwargs)
if ret:
self.factory.authorized_sessions[self.transport.sessionno] = (ret, args[0])
self.factory.session_protocols[self.transport.sessionno] = self
@ -255,8 +255,8 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
if not self.valid_session():
return
if method == "daemon.set_event_interest":
log.debug("RPC dispatch daemon.set_event_interest")
if method == 'daemon.set_event_interest':
log.debug('RPC dispatch daemon.set_event_interest')
# This special case is to allow clients to set which events they are
# interested in receiving.
# We are expecting a sequence from the client.
@ -278,13 +278,13 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
send_error()
return
log.debug("RPC dispatch %s", method)
log.debug('RPC dispatch %s', method)
try:
method_auth_requirement = self.factory.methods[method]._rpcserver_auth_level
auth_level = self.factory.authorized_sessions[self.transport.sessionno][0]
if auth_level < method_auth_requirement:
# This session is not allowed to call this method
log.debug("Session %s is attempting an unauthorized method call!",
log.debug('Session %s is attempting an unauthorized method call!',
self.transport.sessionno)
raise NotAuthorizedError(auth_level, method_auth_requirement)
# Set the session_id in the factory so that methods can know
@ -296,7 +296,7 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
# Don't bother printing out DelugeErrors, because they are just
# for the client
if not isinstance(ex, DelugeError):
log.exception("Exception calling RPC request: %s", ex)
log.exception('Exception calling RPC request: %s', ex)
else:
# Check if the return value is a deferred, since we'll need to
# wait for it to fire before sending the RPC_RESPONSE
@ -336,13 +336,13 @@ class RPCServer(component.Component):
:type listen: bool
"""
def __init__(self, port=58846, interface="", allow_remote=False, listen=True):
component.Component.__init__(self, "RPCServer")
def __init__(self, port=58846, interface='', allow_remote=False, listen=True):
component.Component.__init__(self, 'RPCServer')
self.factory = Factory()
self.factory.protocol = DelugeRPCProtocol
self.factory.session_id = -1
self.factory.state = "running"
self.factory.state = 'running'
# Holds the registered methods
self.factory.methods = {}
@ -358,14 +358,14 @@ class RPCServer(component.Component):
return
if allow_remote:
hostname = ""
hostname = ''
else:
hostname = "localhost"
hostname = 'localhost'
if interface:
hostname = interface
log.info("Starting DelugeRPC server %s:%s", hostname, port)
log.info('Starting DelugeRPC server %s:%s', hostname, port)
# Check for SSL keys and generate some if needed
check_ssl_keys()
@ -373,7 +373,7 @@ class RPCServer(component.Component):
try:
reactor.listenSSL(port, self.factory, ServerContextFactory(), interface=hostname)
except Exception as ex:
log.info("Daemon already running or port not available.")
log.info('Daemon already running or port not available.')
log.error(ex)
raise
@ -391,11 +391,11 @@ class RPCServer(component.Component):
name = obj.__class__.__name__.lower()
for d in dir(obj):
if d[0] == "_":
if d[0] == '_':
continue
if getattr(getattr(obj, d), '_rpcserver_export', False):
log.debug("Registering method: %s", name + "." + d)
self.factory.methods[name + "." + d] = getattr(obj, d)
log.debug('Registering method: %s', name + '.' + d)
self.factory.methods[name + '.' + d] = getattr(obj, d)
def deregister_object(self, obj):
"""
@ -450,13 +450,13 @@ class RPCServer(component.Component):
"""
if not self.listen:
return "localclient"
return 'localclient'
session_id = self.get_session_id()
if session_id > -1 and session_id in self.factory.authorized_sessions:
return self.factory.authorized_sessions[session_id][1]
else:
# No connections made yet
return ""
return ''
def get_session_auth_level(self):
"""
@ -498,11 +498,11 @@ class RPCServer(component.Component):
:param event: the event to emit
:type event: :class:`deluge.event.DelugeEvent`
"""
log.debug("intevents: %s", self.factory.interested_events)
log.debug('intevents: %s', self.factory.interested_events)
# Find sessions interested in this event
for session_id, interest in self.factory.interested_events.items():
if event.name in interest:
log.debug("Emit Event: %s %s", event.name, event.args)
log.debug('Emit Event: %s %s', event.name, event.args)
# This session is interested so send a RPC_EVENT
self.factory.session_protocols[session_id].sendData(
(RPC_EVENT, event.name, event.args)
@ -532,20 +532,20 @@ class RPCServer(component.Component):
self.factory.session_protocols[session_id].sendData((RPC_EVENT, event.name, event.args))
def stop(self):
self.factory.state = "stopping"
self.factory.state = 'stopping'
def check_ssl_keys():
"""
Check for SSL cert/key and create them if necessary
"""
ssl_dir = deluge.configmanager.get_config_dir("ssl")
ssl_dir = deluge.configmanager.get_config_dir('ssl')
if not os.path.exists(ssl_dir):
# The ssl folder doesn't exist so we need to create it
os.makedirs(ssl_dir)
generate_ssl_keys()
else:
for f in ("daemon.pkey", "daemon.cert"):
for f in ('daemon.pkey', 'daemon.cert'):
if not os.path.exists(os.path.join(ssl_dir, f)):
generate_ssl_keys()
break
@ -555,7 +555,7 @@ def generate_ssl_keys():
"""
This method generates a new SSL key/cert.
"""
digest = "sha256"
digest = 'sha256'
# Generate key pair
pkey = crypto.PKey()
pkey.generate_key(crypto.TYPE_RSA, 2048)
@ -563,7 +563,7 @@ def generate_ssl_keys():
# Generate cert request
req = crypto.X509Req()
subj = req.get_subject()
setattr(subj, "CN", "Deluge Daemon")
setattr(subj, 'CN', 'Deluge Daemon')
req.set_pubkey(pkey)
req.sign(pkey, digest)
@ -578,11 +578,11 @@ def generate_ssl_keys():
cert.sign(pkey, digest)
# Write out files
ssl_dir = deluge.configmanager.get_config_dir("ssl")
with open(os.path.join(ssl_dir, "daemon.pkey"), "w") as _file:
ssl_dir = deluge.configmanager.get_config_dir('ssl')
with open(os.path.join(ssl_dir, 'daemon.pkey'), 'w') as _file:
_file.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey))
with open(os.path.join(ssl_dir, "daemon.cert"), "w") as _file:
with open(os.path.join(ssl_dir, 'daemon.cert'), 'w') as _file:
_file.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
# Make the files only readable by this user
for f in ("daemon.pkey", "daemon.cert"):
for f in ('daemon.pkey', 'daemon.cert'):
os.chmod(os.path.join(ssl_dir, f), stat.S_IREAD | stat.S_IWRITE)

View File

@ -34,14 +34,14 @@ from deluge.event import TorrentFolderRenamedEvent, TorrentStateChangedEvent, To
log = logging.getLogger(__name__)
LT_TORRENT_STATE_MAP = {
"queued_for_checking": "Checking",
"checking_files": "Checking",
"downloading_metadata": "Downloading",
"downloading": "Downloading",
"finished": "Seeding",
"seeding": "Seeding",
"allocating": "Allocating",
"checking_resume_data": "Checking"
'queued_for_checking': 'Checking',
'checking_files': 'Checking',
'downloading_metadata': 'Downloading',
'downloading': 'Downloading',
'finished': 'Seeding',
'seeding': 'Seeding',
'allocating': 'Allocating',
'checking_resume_data': 'Checking'
}
@ -57,19 +57,19 @@ def sanitize_filepath(filepath, folder=False):
def clean_filename(filename):
"""Strips whitespace and discards dotted filenames"""
filename = filename.strip()
if filename.replace(".", "") == "":
return ""
if filename.replace('.', '') == '':
return ''
return filename
if "\\" in filepath or "/" in filepath:
folderpath = filepath.replace("\\", "/").split("/")
if '\\' in filepath or '/' in filepath:
folderpath = filepath.replace('\\', '/').split('/')
folderpath = [clean_filename(x) for x in folderpath]
newfilepath = "/".join([path for path in folderpath if path])
newfilepath = '/'.join([path for path in folderpath if path])
else:
newfilepath = clean_filename(filepath)
if folder is True:
newfilepath += "/"
newfilepath += '/'
return newfilepath
@ -95,10 +95,10 @@ def convert_lt_files(files):
filelist = []
for index, _file in enumerate(files):
filelist.append({
"index": index,
"path": _file.path.decode("utf8").replace("\\", "/"),
"size": _file.size,
"offset": _file.offset
'index': index,
'path': _file.path.decode('utf8').replace('\\', '/'),
'size': _file.size,
'offset': _file.offset
})
return filelist
@ -139,34 +139,34 @@ class TorrentOptions(dict):
"""
def __init__(self):
super(TorrentOptions, self).__init__()
config = ConfigManager("core.conf").config
config = ConfigManager('core.conf').config
options_conf_map = {
"max_connections": "max_connections_per_torrent",
"max_upload_slots": "max_upload_slots_per_torrent",
"max_upload_speed": "max_upload_speed_per_torrent",
"max_download_speed": "max_download_speed_per_torrent",
"prioritize_first_last_pieces": "prioritize_first_last_pieces",
"sequential_download": "sequential_download",
"pre_allocate_storage": "pre_allocate_storage",
"download_location": "download_location",
"auto_managed": "auto_managed",
"stop_at_ratio": "stop_seed_at_ratio",
"stop_ratio": "stop_seed_ratio",
"remove_at_ratio": "remove_seed_at_ratio",
"move_completed": "move_completed",
"move_completed_path": "move_completed_path",
"add_paused": "add_paused",
"shared": "shared",
"super_seeding": "super_seeding",
"priority": "priority",
'max_connections': 'max_connections_per_torrent',
'max_upload_slots': 'max_upload_slots_per_torrent',
'max_upload_speed': 'max_upload_speed_per_torrent',
'max_download_speed': 'max_download_speed_per_torrent',
'prioritize_first_last_pieces': 'prioritize_first_last_pieces',
'sequential_download': 'sequential_download',
'pre_allocate_storage': 'pre_allocate_storage',
'download_location': 'download_location',
'auto_managed': 'auto_managed',
'stop_at_ratio': 'stop_seed_at_ratio',
'stop_ratio': 'stop_seed_ratio',
'remove_at_ratio': 'remove_seed_at_ratio',
'move_completed': 'move_completed',
'move_completed_path': 'move_completed_path',
'add_paused': 'add_paused',
'shared': 'shared',
'super_seeding': 'super_seeding',
'priority': 'priority',
}
for opt_k, conf_k in options_conf_map.iteritems():
self[opt_k] = config[conf_k]
self["file_priorities"] = []
self["mapped_files"] = {}
self["owner"] = ""
self["name"] = ""
self["seed_mode"] = False
self['file_priorities'] = []
self['mapped_files'] = {}
self['owner'] = ''
self['name'] = ''
self['seed_mode'] = False
class TorrentError(object):
@ -216,11 +216,11 @@ class Torrent(object):
def __init__(self, handle, options, state=None, filename=None, magnet=None):
self.torrent_id = str(handle.info_hash())
if log.isEnabledFor(logging.DEBUG):
log.debug("Creating torrent object %s", self.torrent_id)
log.debug('Creating torrent object %s', self.torrent_id)
# Get the core config
self.config = ConfigManager("core.conf")
self.rpcserver = component.get("RPCServer")
self.config = ConfigManager('core.conf')
self.rpcserver = component.get('RPCServer')
self.handle = handle
self.handle.resolve_countries(True)
@ -253,7 +253,7 @@ class Torrent(object):
self.state = None
self.moving_storage = False
self.moving_storage_dest_path = None
self.tracker_status = ""
self.tracker_status = ''
self.tracker_host = None
self.forcing_recheck = False
self.forcing_recheck_paused = False
@ -267,13 +267,13 @@ class Torrent(object):
self.update_state()
if log.isEnabledFor(logging.DEBUG):
log.debug("Torrent object created.")
log.debug('Torrent object created.')
def on_metadata_received(self):
"""Process the metadata received alert for this torrent"""
self.has_metadata = True
self.torrent_info = self.handle.get_torrent_info()
if self.options["prioritize_first_last_pieces"]:
if self.options['prioritize_first_last_pieces']:
self.set_prioritize_first_last_pieces(True)
self.write_torrentfile()
@ -286,13 +286,13 @@ class Torrent(object):
"""
# set_prioritize_first_last is called by set_file_priorities so only run if not in options
skip_func = []
if "file_priorities" in options:
self.options["prioritize_first_last_pieces"] = options["prioritize_first_last_pieces"]
skip_func.append("prioritize_first_last_pieces")
if 'file_priorities' in options:
self.options['prioritize_first_last_pieces'] = options['prioritize_first_last_pieces']
skip_func.append('prioritize_first_last_pieces')
for key, value in options.items():
if key in self.options:
options_set_func = getattr(self, "set_" + key, None)
options_set_func = getattr(self, 'set_' + key, None)
if options_set_func and key not in skip_func:
options_set_func(value)
else:
@ -323,7 +323,7 @@ class Torrent(object):
elif max_connections == 1:
max_connections = 2
self.options["max_connections"] = max_connections
self.options['max_connections'] = max_connections
self.handle.set_max_connections(max_connections)
def set_max_upload_slots(self, max_slots):
@ -332,7 +332,7 @@ class Torrent(object):
Args:
max_slots (int): Maximum upload slots
"""
self.options["max_upload_slots"] = max_slots
self.options['max_upload_slots'] = max_slots
self.handle.set_max_uploads(max_slots)
def set_max_upload_speed(self, m_up_speed):
@ -341,7 +341,7 @@ class Torrent(object):
Args:
m_up_speed (float): Maximum upload speed in KiB/s.
"""
self.options["max_upload_speed"] = m_up_speed
self.options['max_upload_speed'] = m_up_speed
if m_up_speed < 0:
value = -1
else:
@ -354,7 +354,7 @@ class Torrent(object):
Args:
m_up_speed (float): Maximum download speed in KiB/s.
"""
self.options["max_download_speed"] = m_down_speed
self.options['max_download_speed'] = m_down_speed
if m_down_speed < 0:
value = -1
else:
@ -374,11 +374,11 @@ class Torrent(object):
Returns:
tuple of lists: The prioritized pieces and the torrent piece priorities.
"""
self.options["prioritize_first_last_pieces"] = prioritize
self.options['prioritize_first_last_pieces'] = prioritize
if not prioritize:
# If we are turning off this option, call set_file_priorities to
# reset all the piece priorities
self.set_file_priorities(self.options["file_priorities"])
self.set_file_priorities(self.options['file_priorities'])
return None, None
if not self.has_metadata:
return None, None
@ -414,7 +414,7 @@ class Torrent(object):
Args:
set_sequencial (bool): Enable sequencial downloading.
"""
self.options["sequential_download"] = set_sequencial
self.options['sequential_download'] = set_sequencial
self.handle.set_sequential_download(set_sequencial)
def set_auto_managed(self, auto_managed):
@ -423,7 +423,7 @@ class Torrent(object):
Args:
auto_managed (bool): Enable auto managed.
"""
self.options["auto_managed"] = auto_managed
self.options['auto_managed'] = auto_managed
if not (self.status.paused and not self.status.auto_managed):
self.handle.auto_managed(auto_managed)
self.update_state()
@ -435,10 +435,10 @@ class Torrent(object):
super_seeding (bool): Enable super seeding.
"""
if self.status.is_seeding:
self.options["super_seeding"] = super_seeding
self.options['super_seeding'] = super_seeding
self.handle.super_seeding(super_seeding)
else:
self.options["super_seeding"] = False
self.options['super_seeding'] = False
def set_stop_ratio(self, stop_ratio):
"""The seeding ratio to stop (or remove) the torrent at.
@ -446,7 +446,7 @@ class Torrent(object):
Args:
stop_ratio (float): The seeding ratio.
"""
self.options["stop_ratio"] = stop_ratio
self.options['stop_ratio'] = stop_ratio
def set_stop_at_ratio(self, stop_at_ratio):
"""Stop the torrent when it has reached stop_ratio.
@ -454,7 +454,7 @@ class Torrent(object):
Args:
stop_at_ratio (bool): Stop the torrent.
"""
self.options["stop_at_ratio"] = stop_at_ratio
self.options['stop_at_ratio'] = stop_at_ratio
def set_remove_at_ratio(self, remove_at_ratio):
"""Remove the torrent when it has reached the stop_ratio.
@ -462,7 +462,7 @@ class Torrent(object):
Args:
remove_at_ratio (bool): Remove the torrent.
"""
self.options["remove_at_ratio"] = remove_at_ratio
self.options['remove_at_ratio'] = remove_at_ratio
def set_move_completed(self, move_completed):
"""Set whether to move the torrent when downloading has finished.
@ -471,7 +471,7 @@ class Torrent(object):
move_completed (bool): Move the torrent.
"""
self.options["move_completed"] = move_completed
self.options['move_completed'] = move_completed
def set_move_completed_path(self, move_completed_path):
"""Set the path to move torrent to when downloading has finished.
@ -479,7 +479,7 @@ class Torrent(object):
Args:
move_completed_path (str): The move path.
"""
self.options["move_completed_path"] = move_completed_path
self.options['move_completed_path'] = move_completed_path
def set_file_priorities(self, file_priorities):
"""Sets the file priotities.
@ -490,8 +490,8 @@ class Torrent(object):
if not self.has_metadata:
return
if len(file_priorities) != self.torrent_info.num_files():
log.debug("file_priorities len != num_files")
self.options["file_priorities"] = self.handle.file_priorities()
log.debug('file_priorities len != num_files')
self.options['file_priorities'] = self.handle.file_priorities()
return
if log.isEnabledFor(logging.DEBUG):
@ -499,10 +499,10 @@ class Torrent(object):
self.handle.prioritize_files(file_priorities)
if 0 in self.options["file_priorities"]:
if 0 in self.options['file_priorities']:
# We have previously marked a file 'Do Not Download'
# Check to see if we have changed any 0's to >0 and change state accordingly
for index, priority in enumerate(self.options["file_priorities"]):
for index, priority in enumerate(self.options['file_priorities']):
if priority == 0 and file_priorities[index] > 0:
# We have a changed 'Do Not Download' to a download priority
self.is_finished = False
@ -511,11 +511,11 @@ class Torrent(object):
# In case values in file_priorities were faulty (old state?)
# we make sure the stored options are in sync
self.options["file_priorities"] = self.handle.file_priorities()
self.options['file_priorities'] = self.handle.file_priorities()
# Set the first/last priorities if needed
if self.options["prioritize_first_last_pieces"]:
self.set_prioritize_first_last_pieces(self.options["prioritize_first_last_pieces"])
if self.options['prioritize_first_last_pieces']:
self.set_prioritize_first_last_pieces(self.options['prioritize_first_last_pieces'])
def set_save_path(self, download_location):
"""Deprecated, use set_download_location."""
@ -523,7 +523,7 @@ class Torrent(object):
def set_download_location(self, download_location):
"""The location for downloading torrent data."""
self.options["download_location"] = download_location
self.options['download_location'] = download_location
def set_priority(self, priority):
"""Sets the bandwidth priority of this torrent.
@ -537,10 +537,10 @@ class Torrent(object):
ValueError: If value of priority is not in range [0..255]
"""
if 0 <= priority <= 255:
self.options["priority"] = priority
self.options['priority'] = priority
return self.handle.set_priority(priority)
else:
raise ValueError("Torrent priority, %s, is invalid, should be [0..255]", priority)
raise ValueError('Torrent priority, %s, is invalid, should be [0..255]', priority)
def set_owner(self, account):
"""Sets the owner of this torrent.
@ -548,7 +548,7 @@ class Torrent(object):
Only a user with admin level auth can change this value.
"""
if self.rpcserver.get_session_auth_level() == AUTH_LEVEL_ADMIN:
self.options["owner"] = account
self.options['owner'] = account
# End Options methods #
@ -564,21 +564,21 @@ class Torrent(object):
return
if log.isEnabledFor(logging.DEBUG):
log.debug("Setting trackers for %s: %s", self.torrent_id, trackers)
log.debug('Setting trackers for %s: %s', self.torrent_id, trackers)
tracker_list = []
for tracker in trackers:
new_entry = lt.announce_entry(str(tracker["url"]))
new_entry.tier = tracker["tier"]
new_entry = lt.announce_entry(str(tracker['url']))
new_entry.tier = tracker['tier']
tracker_list.append(new_entry)
self.handle.replace_trackers(tracker_list)
# Print out the trackers
if log.isEnabledFor(logging.DEBUG):
log.debug("Trackers set for %s:", self.torrent_id)
log.debug('Trackers set for %s:', self.torrent_id)
for tracker in self.handle.trackers():
log.debug(" [tier %s]: %s", tracker["tier"], tracker["url"])
log.debug(' [tier %s]: %s', tracker['tier'], tracker['url'])
# Set the tracker list in the torrent object
self.trackers = trackers
if len(trackers) > 0:
@ -601,26 +601,26 @@ class Torrent(object):
if self.tracker_status != status:
self.tracker_status = status
component.get("EventManager").emit(TorrentTrackerStatusEvent(self.torrent_id, self.tracker_status))
component.get('EventManager').emit(TorrentTrackerStatusEvent(self.torrent_id, self.tracker_status))
def merge_trackers(self, torrent_info):
"""Merges new trackers in torrent_info into torrent"""
log.info("Adding any new trackers to torrent (%s) already in session...", self.torrent_id)
log.info('Adding any new trackers to torrent (%s) already in session...', self.torrent_id)
if not torrent_info:
return
# Don't merge trackers if either torrent has private flag set.
if torrent_info.priv() or self.get_status(["private"])["private"]:
log.info("Adding trackers aborted: Torrent has private flag set.")
if torrent_info.priv() or self.get_status(['private'])['private']:
log.info('Adding trackers aborted: Torrent has private flag set.')
else:
for tracker in torrent_info.trackers():
self.handle.add_tracker({"url": tracker.url, "tier": tracker.tier})
self.handle.add_tracker({'url': tracker.url, 'tier': tracker.tier})
# Update torrent.trackers from libtorrent handle.
self.set_trackers()
def update_state(self):
"""Updates the state, based on libtorrent's torrent state"""
status = self.handle.status()
session_paused = component.get("Core").session.is_paused()
session_paused = component.get('Core').session.is_paused()
old_state = self.state
self.set_status_message()
try:
@ -630,30 +630,30 @@ class Torrent(object):
status_error = status.error
if self.forced_error:
self.state = "Error"
self.state = 'Error'
self.set_status_message(self.forced_error.error_message)
elif status_error:
self.state = "Error"
self.state = 'Error'
# auto-manage status will be reverted upon resuming.
self.handle.auto_managed(False)
self.set_status_message(decode_string(status_error))
elif self.moving_storage:
self.state = "Moving"
self.state = 'Moving'
elif not session_paused and status.paused and status.auto_managed:
self.state = "Queued"
self.state = 'Queued'
elif session_paused or status.paused:
self.state = "Paused"
self.state = 'Paused'
else:
self.state = LT_TORRENT_STATE_MAP.get(str(status.state), str(status.state))
if self.state != old_state:
component.get("EventManager").emit(TorrentStateChangedEvent(self.torrent_id, self.state))
component.get('EventManager').emit(TorrentStateChangedEvent(self.torrent_id, self.state))
if log.isEnabledFor(logging.DEBUG):
log.debug("State from lt was: %s | Session is paused: %s\nTorrent state set from '%s' to '%s' (%s)",
"error" if status_error else status.state, session_paused, old_state, self.state, self.torrent_id)
'error' if status_error else status.state, session_paused, old_state, self.state, self.torrent_id)
if self.forced_error:
log.debug("Torrent Error state message: %s", self.forced_error.error_message)
log.debug('Torrent Error state message: %s', self.forced_error.error_message)
def set_status_message(self, message=None):
"""Sets the torrent status message.
@ -665,7 +665,7 @@ class Torrent(object):
"""
if not message:
message = "OK"
message = 'OK'
self.statusmsg = message
def force_error_state(self, message, restart_to_resume=True):
@ -690,12 +690,12 @@ class Torrent(object):
return
if self.forced_error.restart_to_resume:
log.error("Restart deluge to clear this torrent error")
log.error('Restart deluge to clear this torrent error')
if not self.forced_error.was_paused and self.options["auto_managed"]:
if not self.forced_error.was_paused and self.options['auto_managed']:
self.handle.auto_managed(True)
self.forced_error = None
self.set_status_message("OK")
self.set_status_message('OK')
if update_state:
self.update_state()
@ -708,9 +708,9 @@ class Torrent(object):
"""
status = self.status
eta = 0
if self.is_finished and self.options["stop_at_ratio"] and status.upload_payload_rate:
if self.is_finished and self.options['stop_at_ratio'] and status.upload_payload_rate:
# We're a seed, so calculate the time to the 'stop_share_ratio'
eta = ((status.all_time_download * self.options["stop_ratio"]) -
eta = ((status.all_time_download * self.options['stop_ratio']) -
status.all_time_upload) // status.upload_payload_rate
elif status.download_payload_rate:
left = status.total_wanted - status.total_wanted_done
@ -788,20 +788,20 @@ class Torrent(object):
client = decode_string(peer.client)
try:
country = component.get("Core").geoip_instance.country_code_by_addr(peer.ip[0])
country = component.get('Core').geoip_instance.country_code_by_addr(peer.ip[0])
except AttributeError:
country = ""
country = ''
else:
country = "".join([char if char.isalpha() else " " for char in country])
country = ''.join([char if char.isalpha() else ' ' for char in country])
ret.append({
"client": client,
"country": country,
"down_speed": peer.payload_down_speed,
"ip": "%s:%s" % (peer.ip[0], peer.ip[1]),
"progress": peer.progress,
"seed": peer.flags & peer.seed,
"up_speed": peer.payload_up_speed,
'client': client,
'country': country,
'down_speed': peer.payload_down_speed,
'ip': '%s:%s' % (peer.ip[0], peer.ip[1]),
'progress': peer.progress,
'seed': peer.flags & peer.seed,
'up_speed': peer.payload_up_speed,
})
return ret
@ -838,12 +838,12 @@ class Torrent(object):
tracker = self.status.current_tracker
if not tracker and self.trackers:
tracker = self.trackers[0]["url"]
tracker = self.trackers[0]['url']
if tracker:
url = urlparse(tracker.replace("udp://", "http://"))
if hasattr(url, "hostname"):
host = (url.hostname or "DHT")
url = urlparse(tracker.replace('udp://', 'http://'))
if hasattr(url, 'hostname'):
host = (url.hostname or 'DHT')
# Check if hostname is an IP address and just return it if that's the case
try:
socket.inet_aton(host)
@ -853,15 +853,15 @@ class Torrent(object):
# This is an IP address because an exception wasn't raised
return url.hostname
parts = host.split(".")
parts = host.split('.')
if len(parts) > 2:
if parts[-2] in ("co", "com", "net", "org") or parts[-1] == "uk":
host = ".".join(parts[-3:])
if parts[-2] in ('co', 'com', 'net', 'org') or parts[-1] == 'uk':
host = '.'.join(parts[-3:])
else:
host = ".".join(parts[-2:])
host = '.'.join(parts[-2:])
self.tracker_host = host
return host
return ""
return ''
def get_magnet_uri(self):
"""Returns a magnet uri for this torrent"""
@ -878,14 +878,14 @@ class Torrent(object):
str: the name of the torrent.
"""
if not self.options["name"]:
if not self.options['name']:
handle_name = self.handle.name()
if handle_name:
name = decode_string(handle_name)
else:
name = self.torrent_id
else:
name = self.options["name"]
name = self.options['name']
return name
@ -902,12 +902,12 @@ class Torrent(object):
files = [os.path.join(path, f) for f in files]
return sum(os.stat(f).st_size for f in files if os.path.exists(f))
if self.state == "Error":
if self.state == 'Error':
progress = 100.0
elif self.moving_storage:
# Check if torrent has downloaded any data yet.
if self.status.total_done:
torrent_files = [f["path"] for f in self.get_files()]
torrent_files = [f['path'] for f in self.get_files()]
dest_path_size = get_size(torrent_files, self.moving_storage_dest_path)
progress = dest_path_size / self.status.total_done * 100
else:
@ -972,81 +972,81 @@ class Torrent(object):
def _create_status_funcs(self):
"""Creates the functions for getting torrent status"""
self.status_funcs = {
"active_time": lambda: self.status.active_time,
"seeding_time": lambda: self.status.seeding_time,
"finished_time": lambda: self.status.finished_time,
"all_time_download": lambda: self.status.all_time_download,
"storage_mode": lambda: self.status.storage_mode.name.split("_")[2], # sparse or allocate
"distributed_copies": lambda: max(0.0, self.status.distributed_copies),
"download_payload_rate": lambda: self.status.download_payload_rate,
"file_priorities": lambda: self.options["file_priorities"],
"hash": lambda: self.torrent_id,
"is_auto_managed": lambda: self.options["auto_managed"],
"is_finished": lambda: self.is_finished,
"max_connections": lambda: self.options["max_connections"],
"max_download_speed": lambda: self.options["max_download_speed"],
"max_upload_slots": lambda: self.options["max_upload_slots"],
"max_upload_speed": lambda: self.options["max_upload_speed"],
"message": lambda: self.statusmsg,
"move_on_completed_path": lambda: self.options["move_completed_path"], # Depr, use move_completed_path
"move_on_completed": lambda: self.options["move_completed"], # Deprecated, use move_completed
"move_completed_path": lambda: self.options["move_completed_path"],
"move_completed": lambda: self.options["move_completed"],
"next_announce": lambda: self.status.next_announce.seconds,
"num_peers": lambda: self.status.num_peers - self.status.num_seeds,
"num_seeds": lambda: self.status.num_seeds,
"owner": lambda: self.options["owner"],
"paused": lambda: self.status.paused,
"prioritize_first_last": lambda: self.options["prioritize_first_last_pieces"],
"sequential_download": lambda: self.options["sequential_download"],
"progress": self.get_progress,
"shared": lambda: self.options["shared"],
"remove_at_ratio": lambda: self.options["remove_at_ratio"],
"save_path": lambda: self.options["download_location"], # Deprecated, use download_location
"download_location": lambda: self.options["download_location"],
"seeds_peers_ratio": lambda: -1.0 if self.status.num_incomplete == 0 else ( # Use -1.0 to signify infinity
'active_time': lambda: self.status.active_time,
'seeding_time': lambda: self.status.seeding_time,
'finished_time': lambda: self.status.finished_time,
'all_time_download': lambda: self.status.all_time_download,
'storage_mode': lambda: self.status.storage_mode.name.split('_')[2], # sparse or allocate
'distributed_copies': lambda: max(0.0, self.status.distributed_copies),
'download_payload_rate': lambda: self.status.download_payload_rate,
'file_priorities': lambda: self.options['file_priorities'],
'hash': lambda: self.torrent_id,
'is_auto_managed': lambda: self.options['auto_managed'],
'is_finished': lambda: self.is_finished,
'max_connections': lambda: self.options['max_connections'],
'max_download_speed': lambda: self.options['max_download_speed'],
'max_upload_slots': lambda: self.options['max_upload_slots'],
'max_upload_speed': lambda: self.options['max_upload_speed'],
'message': lambda: self.statusmsg,
'move_on_completed_path': lambda: self.options['move_completed_path'], # Depr, use move_completed_path
'move_on_completed': lambda: self.options['move_completed'], # Deprecated, use move_completed
'move_completed_path': lambda: self.options['move_completed_path'],
'move_completed': lambda: self.options['move_completed'],
'next_announce': lambda: self.status.next_announce.seconds,
'num_peers': lambda: self.status.num_peers - self.status.num_seeds,
'num_seeds': lambda: self.status.num_seeds,
'owner': lambda: self.options['owner'],
'paused': lambda: self.status.paused,
'prioritize_first_last': lambda: self.options['prioritize_first_last_pieces'],
'sequential_download': lambda: self.options['sequential_download'],
'progress': self.get_progress,
'shared': lambda: self.options['shared'],
'remove_at_ratio': lambda: self.options['remove_at_ratio'],
'save_path': lambda: self.options['download_location'], # Deprecated, use download_location
'download_location': lambda: self.options['download_location'],
'seeds_peers_ratio': lambda: -1.0 if self.status.num_incomplete == 0 else ( # Use -1.0 to signify infinity
self.status.num_complete / self.status.num_incomplete),
"seed_rank": lambda: self.status.seed_rank,
"state": lambda: self.state,
"stop_at_ratio": lambda: self.options["stop_at_ratio"],
"stop_ratio": lambda: self.options["stop_ratio"],
"time_added": lambda: self.status.added_time,
"total_done": lambda: self.status.total_done,
"total_payload_download": lambda: self.status.total_payload_download,
"total_payload_upload": lambda: self.status.total_payload_upload,
"total_peers": lambda: self.status.num_incomplete,
"total_seeds": lambda: self.status.num_complete,
"total_uploaded": lambda: self.status.all_time_upload,
"total_wanted": lambda: self.status.total_wanted,
"total_remaining": lambda: self.status.total_wanted - self.status.total_wanted_done,
"tracker": lambda: self.status.current_tracker,
"tracker_host": self.get_tracker_host,
"trackers": lambda: self.trackers,
"tracker_status": lambda: self.tracker_status,
"upload_payload_rate": lambda: self.status.upload_payload_rate,
"comment": lambda: decode_string(self.torrent_info.comment()) if self.has_metadata else "",
"num_files": lambda: self.torrent_info.num_files() if self.has_metadata else 0,
"num_pieces": lambda: self.torrent_info.num_pieces() if self.has_metadata else 0,
"piece_length": lambda: self.torrent_info.piece_length() if self.has_metadata else 0,
"private": lambda: self.torrent_info.priv() if self.has_metadata else False,
"total_size": lambda: self.torrent_info.total_size() if self.has_metadata else 0,
"eta": self.get_eta,
"file_progress": self.get_file_progress,
"files": self.get_files,
"orig_files": self.get_orig_files,
"is_seed": lambda: self.status.is_seeding,
"peers": self.get_peers,
"queue": lambda: self.status.queue_position,
"ratio": self.get_ratio,
"completed_time": lambda: self.status.completed_time,
"last_seen_complete": lambda: self.status.last_seen_complete,
"name": self.get_name,
"pieces": self._get_pieces_info,
"seed_mode": lambda: self.status.seed_mode,
"super_seeding": lambda: self.status.super_seeding,
"time_since_download": lambda: self.status.time_since_download,
"time_since_upload": lambda: self.status.time_since_upload,
"priority": lambda: self.status.priority,
'seed_rank': lambda: self.status.seed_rank,
'state': lambda: self.state,
'stop_at_ratio': lambda: self.options['stop_at_ratio'],
'stop_ratio': lambda: self.options['stop_ratio'],
'time_added': lambda: self.status.added_time,
'total_done': lambda: self.status.total_done,
'total_payload_download': lambda: self.status.total_payload_download,
'total_payload_upload': lambda: self.status.total_payload_upload,
'total_peers': lambda: self.status.num_incomplete,
'total_seeds': lambda: self.status.num_complete,
'total_uploaded': lambda: self.status.all_time_upload,
'total_wanted': lambda: self.status.total_wanted,
'total_remaining': lambda: self.status.total_wanted - self.status.total_wanted_done,
'tracker': lambda: self.status.current_tracker,
'tracker_host': self.get_tracker_host,
'trackers': lambda: self.trackers,
'tracker_status': lambda: self.tracker_status,
'upload_payload_rate': lambda: self.status.upload_payload_rate,
'comment': lambda: decode_string(self.torrent_info.comment()) if self.has_metadata else '',
'num_files': lambda: self.torrent_info.num_files() if self.has_metadata else 0,
'num_pieces': lambda: self.torrent_info.num_pieces() if self.has_metadata else 0,
'piece_length': lambda: self.torrent_info.piece_length() if self.has_metadata else 0,
'private': lambda: self.torrent_info.priv() if self.has_metadata else False,
'total_size': lambda: self.torrent_info.total_size() if self.has_metadata else 0,
'eta': self.get_eta,
'file_progress': self.get_file_progress,
'files': self.get_files,
'orig_files': self.get_orig_files,
'is_seed': lambda: self.status.is_seeding,
'peers': self.get_peers,
'queue': lambda: self.status.queue_position,
'ratio': self.get_ratio,
'completed_time': lambda: self.status.completed_time,
'last_seen_complete': lambda: self.status.last_seen_complete,
'name': self.get_name,
'pieces': self._get_pieces_info,
'seed_mode': lambda: self.status.seed_mode,
'super_seeding': lambda: self.status.super_seeding,
'time_since_download': lambda: self.status.time_since_download,
'time_since_upload': lambda: self.status.time_since_upload,
'priority': lambda: self.status.priority,
}
def pause(self):
@ -1058,7 +1058,7 @@ class Torrent(object):
"""
# Turn off auto-management so the torrent will not be unpaused by lt queueing
self.handle.auto_managed(False)
if self.state == "Error":
if self.state == 'Error':
return False
elif self.status.paused:
# This torrent was probably paused due to being auto managed by lt
@ -1066,37 +1066,37 @@ class Torrent(object):
# show it as 'Paused'. We need to emit a torrent_paused signal because
# the torrent_paused alert from libtorrent will not be generated.
self.update_state()
component.get("EventManager").emit(TorrentStateChangedEvent(self.torrent_id, "Paused"))
component.get('EventManager').emit(TorrentStateChangedEvent(self.torrent_id, 'Paused'))
else:
try:
self.handle.pause()
except RuntimeError as ex:
log.debug("Unable to pause torrent: %s", ex)
log.debug('Unable to pause torrent: %s', ex)
return False
return True
def resume(self):
"""Resumes this torrent."""
if self.status.paused and self.status.auto_managed:
log.debug("Resume not possible for auto-managed torrent!")
log.debug('Resume not possible for auto-managed torrent!')
elif self.forced_error and self.forced_error.was_paused:
log.debug("Resume skipped for error'd torrent as it was originally paused.")
elif (self.status.is_finished and self.options["stop_at_ratio"] and
self.get_ratio() >= self.options["stop_ratio"]):
elif (self.status.is_finished and self.options['stop_at_ratio'] and
self.get_ratio() >= self.options['stop_ratio']):
log.debug("Resume skipped for torrent as it has reached 'stop_seed_ratio'.")
else:
# Check if torrent was originally being auto-managed.
if self.options["auto_managed"]:
if self.options['auto_managed']:
self.handle.auto_managed(True)
try:
self.handle.resume()
except RuntimeError as ex:
log.debug("Unable to resume torrent: %s", ex)
log.debug('Unable to resume torrent: %s', ex)
# Clear torrent error state.
if self.forced_error and not self.forced_error.restart_to_resume:
self.clear_forced_error_state()
elif self.state == "Error" and not self.forced_error:
elif self.state == 'Error' and not self.forced_error:
self.handle.clear_error()
def connect_peer(self, peer_ip, peer_port):
@ -1112,7 +1112,7 @@ class Torrent(object):
try:
self.handle.connect_peer((peer_ip, peer_port), 0)
except RuntimeError as ex:
log.debug("Unable to connect to peer: %s", ex)
log.debug('Unable to connect to peer: %s', ex)
return False
return True
@ -1132,8 +1132,8 @@ class Torrent(object):
try:
os.makedirs(dest)
except OSError as ex:
log.error("Could not move storage for torrent %s since %s does "
"not exist and could not create the directory: %s",
log.error('Could not move storage for torrent %s since %s does '
'not exist and could not create the directory: %s',
self.torrent_id, dest, ex)
return False
@ -1145,7 +1145,7 @@ class Torrent(object):
except TypeError:
self.handle.move_storage(utf8_encoded(dest), flags=1)
except RuntimeError as ex:
log.error("Error calling libtorrent move_storage: %s", ex)
log.error('Error calling libtorrent move_storage: %s', ex)
return False
self.moving_storage = True
self.moving_storage_dest_path = dest
@ -1164,12 +1164,12 @@ class Torrent(object):
"""
if log.isEnabledFor(logging.DEBUG):
log.debug("Requesting save_resume_data for torrent: %s", self.torrent_id)
log.debug('Requesting save_resume_data for torrent: %s', self.torrent_id)
flags = lt.save_resume_flags_t.flush_disk_cache if flush_disk_cache else 0
# Don't generate fastresume data if torrent is in a Deluge Error state.
if self.forced_error:
component.get("TorrentManager").waiting_on_resume_data[self.torrent_id].errback(
UserWarning("Skipped creating resume_data while in Error state"))
component.get('TorrentManager').waiting_on_resume_data[self.torrent_id].errback(
UserWarning('Skipped creating resume_data while in Error state'))
else:
self.handle.save_resume_data(flags)
@ -1183,48 +1183,48 @@ class Torrent(object):
def write_file(filepath, filedump):
"""Write out the torrent file"""
log.debug("Writing torrent file to: %s", filepath)
log.debug('Writing torrent file to: %s', filepath)
try:
with open(filepath, "wb") as save_file:
with open(filepath, 'wb') as save_file:
save_file.write(filedump)
except IOError as ex:
log.error("Unable to save torrent file to: %s", ex)
log.error('Unable to save torrent file to: %s', ex)
filepath = os.path.join(get_config_dir(), "state", self.torrent_id + ".torrent")
filepath = os.path.join(get_config_dir(), 'state', self.torrent_id + '.torrent')
# Regenerate the file priorities
self.set_file_priorities([])
if filedump is None:
metadata = lt.bdecode(self.torrent_info.metadata())
torrent_file = {"info": metadata}
torrent_file = {'info': metadata}
filedump = lt.bencode(torrent_file)
write_file(filepath, filedump)
# If the user has requested a copy of the torrent be saved elsewhere we need to do that.
if self.config["copy_torrent_file"]:
if self.config['copy_torrent_file']:
if not self.filename:
self.filename = self.get_name() + ".torrent"
filepath = os.path.join(self.config["torrentfiles_location"], self.filename)
self.filename = self.get_name() + '.torrent'
filepath = os.path.join(self.config['torrentfiles_location'], self.filename)
write_file(filepath, filedump)
def delete_torrentfile(self, delete_copies=False):
"""Deletes the .torrent file in the state directory in config"""
torrent_files = [os.path.join(get_config_dir(), "state", self.torrent_id + ".torrent")]
torrent_files = [os.path.join(get_config_dir(), 'state', self.torrent_id + '.torrent')]
if delete_copies:
torrent_files.append(os.path.join(self.config["torrentfiles_location"], self.filename))
torrent_files.append(os.path.join(self.config['torrentfiles_location'], self.filename))
for torrent_file in torrent_files:
log.debug("Deleting torrent file: %s", torrent_file)
log.debug('Deleting torrent file: %s', torrent_file)
try:
os.remove(torrent_file)
except OSError as ex:
log.warning("Unable to delete the torrent file: %s", ex)
log.warning('Unable to delete the torrent file: %s', ex)
def force_reannounce(self):
"""Force a tracker reannounce"""
try:
self.handle.force_reannounce()
except RuntimeError as ex:
log.debug("Unable to force reannounce: %s", ex)
log.debug('Unable to force reannounce: %s', ex)
return False
return True
@ -1237,7 +1237,7 @@ class Torrent(object):
try:
self.handle.scrape_tracker()
except RuntimeError as ex:
log.debug("Unable to scrape tracker: %s", ex)
log.debug('Unable to scrape tracker: %s', ex)
return False
return True
@ -1254,7 +1254,7 @@ class Torrent(object):
self.handle.resume()
self.forcing_recheck = True
except RuntimeError as ex:
log.debug("Unable to force recheck: %s", ex)
log.debug('Unable to force recheck: %s', ex)
self.forcing_recheck = False
return self.forcing_recheck
@ -1285,7 +1285,7 @@ class Torrent(object):
Returns:
twisted.internet.defer.Deferred: A deferred which fires when the rename is complete
"""
log.debug("Attempting to rename folder: %s to %s", folder, new_folder)
log.debug('Attempting to rename folder: %s to %s', folder, new_folder)
# Empty string means remove the dir and move its content to the parent
if len(new_folder) > 0:
@ -1298,24 +1298,24 @@ class Torrent(object):
wait_on_folder = {}
self.waiting_on_folder_rename.append(wait_on_folder)
for _file in self.get_files():
if _file["path"].startswith(folder):
if _file['path'].startswith(folder):
# Keep track of filerenames we're waiting on
wait_on_folder[_file["index"]] = Deferred().addBoth(
on_file_rename_complete, wait_on_folder, _file["index"]
wait_on_folder[_file['index']] = Deferred().addBoth(
on_file_rename_complete, wait_on_folder, _file['index']
)
new_path = _file["path"].replace(folder, new_folder, 1)
new_path = _file['path'].replace(folder, new_folder, 1)
try:
self.handle.rename_file(_file["index"], new_path)
self.handle.rename_file(_file['index'], new_path)
except TypeError:
self.handle.rename_file(_file["index"], utf8_encoded(new_path))
self.handle.rename_file(_file['index'], utf8_encoded(new_path))
def on_folder_rename_complete(dummy_result, torrent, folder, new_folder):
"""Folder rename complete"""
component.get("EventManager").emit(TorrentFolderRenamedEvent(torrent.torrent_id, folder, new_folder))
component.get('EventManager').emit(TorrentFolderRenamedEvent(torrent.torrent_id, folder, new_folder))
# Empty folders are removed after libtorrent folder renames
self.remove_empty_folders(folder)
torrent.waiting_on_folder_rename = [_dir for _dir in torrent.waiting_on_folder_rename if _dir]
component.get("TorrentManager").save_resume_data((self.torrent_id,))
component.get('TorrentManager').save_resume_data((self.torrent_id,))
d = DeferredList(wait_on_folder.values())
d.addBoth(on_folder_rename_complete, self, folder, new_folder)
@ -1330,24 +1330,24 @@ class Torrent(object):
folder (str): The folder to recursively check
"""
# Removes leading slashes that can cause join to ignore download_location
download_location = self.options["download_location"]
folder_full_path = os.path.normpath(os.path.join(download_location, folder.lstrip("\\/")))
download_location = self.options['download_location']
folder_full_path = os.path.normpath(os.path.join(download_location, folder.lstrip('\\/')))
try:
if not os.listdir(folder_full_path):
os.removedirs(folder_full_path)
log.debug("Removed Empty Folder %s", folder_full_path)
log.debug('Removed Empty Folder %s', folder_full_path)
else:
for root, dirs, dummy_files in os.walk(folder_full_path, topdown=False):
for name in dirs:
try:
os.removedirs(os.path.join(root, name))
log.debug("Removed Empty Folder %s", os.path.join(root, name))
log.debug('Removed Empty Folder %s', os.path.join(root, name))
except OSError as ex:
log.debug(ex)
except OSError as ex:
log.debug("Cannot Remove Folder: %s", ex)
log.debug('Cannot Remove Folder: %s', ex)
def cleanup_prev_status(self):
"""Checks the validity of the keys in the prev_status dict.

View File

@ -46,7 +46,7 @@ class TorrentState: # pylint: disable=old-style-class
torrent_id=None,
filename=None,
trackers=None,
storage_mode="sparse",
storage_mode='sparse',
paused=False,
save_path=None,
max_connections=-1,
@ -72,7 +72,7 @@ class TorrentState: # pylint: disable=old-style-class
name=None):
# Build the class atrribute list from args
for key, value in locals().items():
if key == "self":
if key == 'self':
continue
setattr(self, key, value)
@ -96,21 +96,21 @@ class TorrentManager(component.Component):
"""
def __init__(self):
component.Component.__init__(self, "TorrentManager", interval=5,
depend=["CorePluginManager", "AlertManager"])
log.debug("TorrentManager init...")
component.Component.__init__(self, 'TorrentManager', interval=5,
depend=['CorePluginManager', 'AlertManager'])
log.debug('TorrentManager init...')
# Set the libtorrent session
self.session = component.get("Core").session
self.session = component.get('Core').session
# Set the alertmanager
self.alerts = component.get("AlertManager")
self.alerts = component.get('AlertManager')
# Get the core config
self.config = ConfigManager("core.conf")
self.config = ConfigManager('core.conf')
# Make sure the state folder has been created
self.state_dir = os.path.join(get_config_dir(), "state")
self.state_dir = os.path.join(get_config_dir(), 'state')
if not os.path.exists(self.state_dir):
os.makedirs(self.state_dir)
self.temp_file = os.path.join(self.state_dir, ".safe_state_check")
self.temp_file = os.path.join(self.state_dir, '.safe_state_check')
# Create the torrents dict { torrent_id: Torrent }
self.torrents = {}
@ -134,38 +134,38 @@ class TorrentManager(component.Component):
self.last_state_update_alert_ts = 0
# Register set functions
self.config.register_set_function("max_connections_per_torrent",
self.config.register_set_function('max_connections_per_torrent',
self.on_set_max_connections_per_torrent)
self.config.register_set_function("max_upload_slots_per_torrent",
self.config.register_set_function('max_upload_slots_per_torrent',
self.on_set_max_upload_slots_per_torrent)
self.config.register_set_function("max_upload_speed_per_torrent",
self.config.register_set_function('max_upload_speed_per_torrent',
self.on_set_max_upload_speed_per_torrent)
self.config.register_set_function("max_download_speed_per_torrent",
self.config.register_set_function('max_download_speed_per_torrent',
self.on_set_max_download_speed_per_torrent)
# Register alert functions
self.alerts.register_handler("torrent_finished_alert", self.on_alert_torrent_finished)
self.alerts.register_handler("torrent_paused_alert", self.on_alert_torrent_paused)
self.alerts.register_handler("torrent_checked_alert", self.on_alert_torrent_checked)
self.alerts.register_handler("tracker_reply_alert", self.on_alert_tracker_reply)
self.alerts.register_handler("tracker_announce_alert", self.on_alert_tracker_announce)
self.alerts.register_handler("tracker_warning_alert", self.on_alert_tracker_warning)
self.alerts.register_handler("tracker_error_alert", self.on_alert_tracker_error)
self.alerts.register_handler("storage_moved_alert", self.on_alert_storage_moved)
self.alerts.register_handler("storage_moved_failed_alert", self.on_alert_storage_moved_failed)
self.alerts.register_handler("torrent_resumed_alert", self.on_alert_torrent_resumed)
self.alerts.register_handler("state_changed_alert", self.on_alert_state_changed)
self.alerts.register_handler("save_resume_data_alert", self.on_alert_save_resume_data)
self.alerts.register_handler("save_resume_data_failed_alert", self.on_alert_save_resume_data_failed)
self.alerts.register_handler("file_renamed_alert", self.on_alert_file_renamed)
self.alerts.register_handler("metadata_received_alert", self.on_alert_metadata_received)
self.alerts.register_handler("file_error_alert", self.on_alert_file_error)
self.alerts.register_handler("file_completed_alert", self.on_alert_file_completed)
self.alerts.register_handler("state_update_alert", self.on_alert_state_update)
self.alerts.register_handler("external_ip_alert", self.on_alert_external_ip)
self.alerts.register_handler("performance_alert", self.on_alert_performance)
self.alerts.register_handler("fastresume_rejected_alert", self.on_alert_fastresume_rejected)
self.alerts.register_handler("add_torrent_alert", self.on_add_torrent_alert)
self.alerts.register_handler('torrent_finished_alert', self.on_alert_torrent_finished)
self.alerts.register_handler('torrent_paused_alert', self.on_alert_torrent_paused)
self.alerts.register_handler('torrent_checked_alert', self.on_alert_torrent_checked)
self.alerts.register_handler('tracker_reply_alert', self.on_alert_tracker_reply)
self.alerts.register_handler('tracker_announce_alert', self.on_alert_tracker_announce)
self.alerts.register_handler('tracker_warning_alert', self.on_alert_tracker_warning)
self.alerts.register_handler('tracker_error_alert', self.on_alert_tracker_error)
self.alerts.register_handler('storage_moved_alert', self.on_alert_storage_moved)
self.alerts.register_handler('storage_moved_failed_alert', self.on_alert_storage_moved_failed)
self.alerts.register_handler('torrent_resumed_alert', self.on_alert_torrent_resumed)
self.alerts.register_handler('state_changed_alert', self.on_alert_state_changed)
self.alerts.register_handler('save_resume_data_alert', self.on_alert_save_resume_data)
self.alerts.register_handler('save_resume_data_failed_alert', self.on_alert_save_resume_data_failed)
self.alerts.register_handler('file_renamed_alert', self.on_alert_file_renamed)
self.alerts.register_handler('metadata_received_alert', self.on_alert_metadata_received)
self.alerts.register_handler('file_error_alert', self.on_alert_file_error)
self.alerts.register_handler('file_completed_alert', self.on_alert_file_completed)
self.alerts.register_handler('state_update_alert', self.on_alert_state_update)
self.alerts.register_handler('external_ip_alert', self.on_alert_external_ip)
self.alerts.register_handler('performance_alert', self.on_alert_performance)
self.alerts.register_handler('fastresume_rejected_alert', self.on_alert_fastresume_rejected)
self.alerts.register_handler('add_torrent_alert', self.on_add_torrent_alert)
# Define timers
self.save_state_timer = LoopingCall(self.save_state)
@ -178,24 +178,24 @@ class TorrentManager(component.Component):
def archive_file(filename):
"""Archives the file in 'archive' sub-directory with timestamp appended"""
filepath = os.path.join(self.state_dir, filename)
filepath_bak = filepath + ".bak"
archive_dir = os.path.join(get_config_dir(), "archive")
filepath_bak = filepath + '.bak'
archive_dir = os.path.join(get_config_dir(), 'archive')
if not os.path.exists(archive_dir):
os.makedirs(archive_dir)
for _filepath in (filepath, filepath_bak):
timestamp = datetime.datetime.now().replace(microsecond=0).isoformat().replace(':', '-')
archive_filepath = os.path.join(archive_dir, filename + "-" + timestamp)
archive_filepath = os.path.join(archive_dir, filename + '-' + timestamp)
try:
shutil.copy2(_filepath, archive_filepath)
except IOError:
log.error("Unable to archive: %s", filename)
log.error('Unable to archive: %s', filename)
else:
log.info("Archive of %s successful: %s", filename, archive_filepath)
log.info('Archive of %s successful: %s', filename, archive_filepath)
log.warning("Potential bad shutdown of Deluge detected, archiving torrent state files...")
archive_file("torrents.state")
archive_file("torrents.fastresume")
log.warning('Potential bad shutdown of Deluge detected, archiving torrent state files...')
archive_file('torrents.state')
archive_file('torrents.fastresume')
else:
with open(self.temp_file, 'a'):
os.utime(self.temp_file, None)
@ -233,15 +233,15 @@ class TorrentManager(component.Component):
def update(self):
for torrent_id, torrent in self.torrents.items():
# XXX: Should the state check be those that _can_ be stopped at ratio
if torrent.options["stop_at_ratio"] and torrent.state not in (
"Checking", "Allocating", "Paused", "Queued"):
if torrent.options['stop_at_ratio'] and torrent.state not in (
'Checking', 'Allocating', 'Paused', 'Queued'):
# If the global setting is set, but the per-torrent isn't...
# Just skip to the next torrent.
# This is so that a user can turn-off the stop at ratio option on a per-torrent basis
if not torrent.options["stop_at_ratio"]:
if not torrent.options['stop_at_ratio']:
continue
if torrent.get_ratio() >= torrent.options["stop_ratio"] and torrent.is_finished:
if torrent.options["remove_at_ratio"]:
if torrent.get_ratio() >= torrent.options['stop_ratio'] and torrent.is_finished:
if torrent.options['remove_at_ratio']:
self.remove(torrent_id)
break
if not torrent.handle.status().paused:
@ -267,13 +267,13 @@ class TorrentManager(component.Component):
"""
torrent_ids = self.torrents.keys()
if component.get("RPCServer").get_session_auth_level() == AUTH_LEVEL_ADMIN:
if component.get('RPCServer').get_session_auth_level() == AUTH_LEVEL_ADMIN:
return torrent_ids
current_user = component.get("RPCServer").get_session_user()
current_user = component.get('RPCServer').get_session_user()
for torrent_id in torrent_ids[:]:
torrent_status = self.torrents[torrent_id].get_status(["owner", "shared"])
if torrent_status["owner"] != current_user and not torrent_status["shared"]:
torrent_status = self.torrents[torrent_id].get_status(['owner', 'shared'])
if torrent_status['owner'] != current_user and not torrent_status['shared']:
torrent_ids.pop(torrent_ids.index(torrent_id))
return torrent_ids
@ -289,11 +289,11 @@ class TorrentManager(component.Component):
"""
# Get the torrent data from the torrent file
if log.isEnabledFor(logging.DEBUG):
log.debug("Attempting to extract torrent_info from %s", filepath)
log.debug('Attempting to extract torrent_info from %s', filepath)
try:
torrent_info = lt.torrent_info(filepath)
except RuntimeError as ex:
log.warning("Unable to open torrent file %s: %s", filepath, ex)
log.warning('Unable to open torrent file %s: %s', filepath, ex)
else:
return torrent_info
@ -319,39 +319,39 @@ class TorrentManager(component.Component):
"""
if not torrent_info and not filedump and not magnet:
raise AddTorrentError("You must specify a valid torrent_info, torrent state or magnet.")
raise AddTorrentError('You must specify a valid torrent_info, torrent state or magnet.')
if filedump:
try:
torrent_info = lt.torrent_info(lt.bdecode(filedump))
except RuntimeError as ex:
raise AddTorrentError("Unable to add torrent, decoding filedump failed: %s" % ex)
raise AddTorrentError('Unable to add torrent, decoding filedump failed: %s' % ex)
add_torrent_params = {}
if torrent_info:
add_torrent_params["ti"] = torrent_info
add_torrent_params['ti'] = torrent_info
name = torrent_info.name()
if not name:
name = torrent_info.file_at(0).path.replace("\\", "/", 1).split("/", 1)[0]
add_torrent_params["name"] = name
name = torrent_info.file_at(0).path.replace('\\', '/', 1).split('/', 1)[0]
add_torrent_params['name'] = name
torrent_id = str(torrent_info.info_hash())
elif magnet:
magnet = utf8_encoded(magnet)
magnet_info = get_magnet_info(magnet)
if magnet_info:
add_torrent_params["url"] = magnet
add_torrent_params["name"] = magnet_info["name"]
torrent_id = magnet_info["info_hash"]
add_torrent_params['url'] = magnet
add_torrent_params['name'] = magnet_info['name']
torrent_id = magnet_info['info_hash']
else:
raise AddTorrentError("Unable to add magnet, invalid magnet info: %s" % magnet)
raise AddTorrentError('Unable to add magnet, invalid magnet info: %s' % magnet)
# Check for existing torrent in session.
if torrent_id in self.get_torrent_list():
# Attempt merge trackers before returning.
self.torrents[torrent_id].merge_trackers(torrent_info)
raise AddTorrentError("Torrent already in session (%s)." % torrent_id)
raise AddTorrentError('Torrent already in session (%s).' % torrent_id)
elif torrent_id in self.torrents_loading:
raise AddTorrentError("Torrent already being added (%s)." % torrent_id)
raise AddTorrentError('Torrent already being added (%s).' % torrent_id)
# Load default options and update if needed.
_options = TorrentOptions()
@ -360,63 +360,63 @@ class TorrentManager(component.Component):
options = _options
# Check for renamed files and if so, rename them in the torrent_info before adding.
if options["mapped_files"] and torrent_info:
for index, fname in options["mapped_files"].items():
if options['mapped_files'] and torrent_info:
for index, fname in options['mapped_files'].items():
fname = sanitize_filepath(decode_string(fname))
log.debug("renaming file index %s to %s", index, fname)
log.debug('renaming file index %s to %s', index, fname)
try:
torrent_info.rename_file(index, fname)
except TypeError:
torrent_info.rename_file(index, utf8_encoded(fname))
add_torrent_params["ti"] = torrent_info
add_torrent_params['ti'] = torrent_info
if not options["owner"]:
options["owner"] = component.get("RPCServer").get_session_user()
if not component.get("AuthManager").has_account(options["owner"]):
options["owner"] = "localclient"
if not options['owner']:
options['owner'] = component.get('RPCServer').get_session_user()
if not component.get('AuthManager').has_account(options['owner']):
options['owner'] = 'localclient'
if log.isEnabledFor(logging.DEBUG):
log.debug("options: %s", options)
log.debug('options: %s', options)
# Fill in the rest of the add_torrent_params dictionary.
add_torrent_params["save_path"] = utf8_encoded(options["download_location"])
if options["name"]:
add_torrent_params["name"] = options["name"]
if options["pre_allocate_storage"]:
add_torrent_params["storage_mode"] = lt.storage_mode_t.storage_mode_allocate
add_torrent_params['save_path'] = utf8_encoded(options['download_location'])
if options['name']:
add_torrent_params['name'] = options['name']
if options['pre_allocate_storage']:
add_torrent_params['storage_mode'] = lt.storage_mode_t.storage_mode_allocate
if resume_data:
add_torrent_params["resume_data"] = resume_data
add_torrent_params['resume_data'] = resume_data
default_flags = (lt.add_torrent_params_flags_t.flag_paused |
lt.add_torrent_params_flags_t.flag_auto_managed |
lt.add_torrent_params_flags_t.flag_update_subscribe |
lt.add_torrent_params_flags_t.flag_apply_ip_filter)
# Set flags: enable duplicate_is_error & override_resume_data, disable auto_managed.
add_torrent_params["flags"] = ((default_flags |
add_torrent_params['flags'] = ((default_flags |
lt.add_torrent_params_flags_t.flag_duplicate_is_error |
lt.add_torrent_params_flags_t.flag_override_resume_data) ^
lt.add_torrent_params_flags_t.flag_auto_managed)
if options["seed_mode"]:
add_torrent_params["flags"] |= lt.add_torrent_params_flags_t.flag_seed_mode
if options['seed_mode']:
add_torrent_params['flags'] |= lt.add_torrent_params_flags_t.flag_seed_mode
d = Deferred()
try:
self.torrents_loading[torrent_id] = (d, options, state, filename, magnet, resume_data, filedump, save_state)
self.session.async_add_torrent(add_torrent_params)
except RuntimeError as ex:
raise AddTorrentError("Unable to add torrent to session: %s" % ex)
raise AddTorrentError('Unable to add torrent to session: %s' % ex)
return d
def on_add_torrent_alert(self, alert):
"""Alert handler for libtorrent add_torrent_alert"""
if not alert.handle.is_valid():
log.warn("Torrent handle is invalid!")
log.warn('Torrent handle is invalid!')
return
try:
torrent_id = str(alert.handle.info_hash())
except RuntimeError as ex:
log.warn("Failed to get torrent id from handle: %s", ex)
log.warn('Failed to get torrent id from handle: %s', ex)
return
d, options, state, filename, magnet, resume_data, filedump, save_state = self.torrents_loading.pop(torrent_id)
@ -431,25 +431,25 @@ class TorrentManager(component.Component):
# Add to queued torrents set.
self.queued_torrents.add(torrent.torrent_id)
if self.config["queue_new_to_top"]:
if self.config['queue_new_to_top']:
self.queue_top(torrent.torrent_id)
# Resume the torrent if needed.
if not options["add_paused"]:
if not options['add_paused']:
torrent.resume()
# Emit torrent_added signal.
from_state = state is not None
component.get("EventManager").emit(TorrentAddedEvent(torrent.torrent_id, from_state))
component.get('EventManager').emit(TorrentAddedEvent(torrent.torrent_id, from_state))
if log.isEnabledFor(logging.DEBUG):
log.debug("Torrent added: %s", str(alert.handle.info_hash()))
log.debug('Torrent added: %s', str(alert.handle.info_hash()))
if log.isEnabledFor(logging.INFO):
name_and_owner = torrent.get_status(["name", "owner"])
name_and_owner = torrent.get_status(['name', 'owner'])
log.info("Torrent %s from user \"%s\" %s",
name_and_owner["name"],
name_and_owner["owner"],
from_state and "loaded" or "added")
name_and_owner['name'],
name_and_owner['owner'],
from_state and 'loaded' or 'added')
# Write the .torrent file to the state directory.
if filedump:
@ -485,22 +485,22 @@ class TorrentManager(component.Component):
except KeyError:
raise InvalidTorrentError("torrent_id '%s' not in session." % torrent_id)
torrent_name = torrent.get_status(["name"])["name"]
torrent_name = torrent.get_status(['name'])['name']
# Emit the signal to the clients
component.get("EventManager").emit(PreTorrentRemovedEvent(torrent_id))
component.get('EventManager').emit(PreTorrentRemovedEvent(torrent_id))
try:
self.session.remove_torrent(torrent.handle, 1 if remove_data else 0)
except RuntimeError as ex:
log.warning("Error removing torrent: %s", ex)
log.warning('Error removing torrent: %s', ex)
return False
# Remove fastresume data if it is exists
self.resume_data.pop(torrent_id, None)
# Remove the .torrent file in the state and copy location, if user requested.
delete_copies = self.config["copy_torrent_file"] and self.config["del_copy_torrent_file"]
delete_copies = self.config['copy_torrent_file'] and self.config['del_copy_torrent_file']
torrent.delete_torrentfile(delete_copies)
# Remove from set if it wasn't finished
@ -518,8 +518,8 @@ class TorrentManager(component.Component):
self.save_state()
# Emit the signal to the clients
component.get("EventManager").emit(TorrentRemovedEvent(torrent_id))
log.info("Torrent %s removed by user: %s", torrent_name, component.get("RPCServer").get_session_user())
component.get('EventManager').emit(TorrentRemovedEvent(torrent_id))
log.info('Torrent %s removed by user: %s', torrent_name, component.get('RPCServer').get_session_user())
return True
def fixup_state(self, state):
@ -540,7 +540,7 @@ class TorrentManager(component.Component):
for t_state in state.torrents:
setattr(t_state, attr, getattr(t_state_tmp, attr, None))
except AttributeError as ex:
log.error("Unable to update state file to a compatible version: %s", ex)
log.error('Unable to update state file to a compatible version: %s', ex)
return state
def open_state(self):
@ -550,17 +550,17 @@ class TorrentManager(component.Component):
TorrentManagerState: The TorrentManager state.
"""
torrents_state = os.path.join(self.state_dir, "torrents.state")
for filepath in (torrents_state, torrents_state + ".bak"):
log.info("Loading torrent state: %s", filepath)
torrents_state = os.path.join(self.state_dir, 'torrents.state')
for filepath in (torrents_state, torrents_state + '.bak'):
log.info('Loading torrent state: %s', filepath)
try:
with open(filepath, "rb") as _file:
with open(filepath, 'rb') as _file:
state = cPickle.load(_file)
except (IOError, EOFError, cPickle.UnpicklingError) as ex:
log.warning("Unable to load %s: %s", filepath, ex)
log.warning('Unable to load %s: %s', filepath, ex)
state = None
else:
log.info("Successfully loaded %s", filepath)
log.info('Successfully loaded %s', filepath)
break
if state is None:
@ -579,7 +579,7 @@ class TorrentManager(component.Component):
state = self.fixup_state(state)
# Reorder the state.torrents list to add torrents in the correct queue order.
state.torrents.sort(key=operator.attrgetter("queue"), reverse=self.config["queue_new_to_top"])
state.torrents.sort(key=operator.attrgetter('queue'), reverse=self.config['queue_new_to_top'])
resume_data = self.load_resume_data_file()
deferreds = []
@ -592,14 +592,14 @@ class TorrentManager(component.Component):
except AttributeError:
pass
# Manually update unmatched attributes
options["download_location"] = t_state.save_path
options["pre_allocate_storage"] = t_state.storage_mode == "allocate"
options["prioritize_first_last_pieces"] = t_state.prioritize_first_last
options["add_paused"] = t_state.paused
options['download_location'] = t_state.save_path
options['pre_allocate_storage'] = t_state.storage_mode == 'allocate'
options['prioritize_first_last_pieces'] = t_state.prioritize_first_last
options['add_paused'] = t_state.paused
magnet = t_state.magnet
torrent_info = self.get_torrent_info_from_file(
os.path.join(self.state_dir, t_state.torrent_id + ".torrent"))
os.path.join(self.state_dir, t_state.torrent_id + '.torrent'))
if torrent_info:
magnet = None
@ -614,8 +614,8 @@ class TorrentManager(component.Component):
deferred_list = DeferredList(deferreds, consumeErrors=False)
def on_complete(result):
log.info("Finished loading %d torrents in %s", len(state.torrents), str(datetime.datetime.now() - start))
component.get("EventManager").emit(SessionStartedEvent())
log.info('Finished loading %d torrents in %s', len(state.torrents), str(datetime.datetime.now() - start))
component.get('EventManager').emit(SessionStartedEvent())
deferred_list.addCallback(on_complete)
def create_state(self):
@ -632,7 +632,7 @@ class TorrentManager(component.Component):
paused = torrent.handle.is_paused()
elif torrent.forced_error:
paused = torrent.forced_error.was_paused
elif torrent.state == "Paused":
elif torrent.state == 'Paused':
paused = True
else:
paused = False
@ -641,30 +641,30 @@ class TorrentManager(component.Component):
torrent.torrent_id,
torrent.filename,
torrent.trackers,
torrent.get_status(["storage_mode"])["storage_mode"],
torrent.get_status(['storage_mode'])['storage_mode'],
paused,
torrent.options["download_location"],
torrent.options["max_connections"],
torrent.options["max_upload_slots"],
torrent.options["max_upload_speed"],
torrent.options["max_download_speed"],
torrent.options["prioritize_first_last_pieces"],
torrent.options["sequential_download"],
torrent.options["file_priorities"],
torrent.options['download_location'],
torrent.options['max_connections'],
torrent.options['max_upload_slots'],
torrent.options['max_upload_speed'],
torrent.options['max_download_speed'],
torrent.options['prioritize_first_last_pieces'],
torrent.options['sequential_download'],
torrent.options['file_priorities'],
torrent.get_queue_position(),
torrent.options["auto_managed"],
torrent.options['auto_managed'],
torrent.is_finished,
torrent.options["stop_ratio"],
torrent.options["stop_at_ratio"],
torrent.options["remove_at_ratio"],
torrent.options["move_completed"],
torrent.options["move_completed_path"],
torrent.options['stop_ratio'],
torrent.options['stop_at_ratio'],
torrent.options['remove_at_ratio'],
torrent.options['move_completed'],
torrent.options['move_completed_path'],
torrent.magnet,
torrent.options["owner"],
torrent.options["shared"],
torrent.options["super_seeding"],
torrent.options["priority"],
torrent.options["name"]
torrent.options['owner'],
torrent.options['shared'],
torrent.options['super_seeding'],
torrent.options['priority'],
torrent.options['name']
)
state.torrents.append(torrent_state)
return state
@ -692,41 +692,41 @@ class TorrentManager(component.Component):
"""Save the state of the TorrentManager to the torrents.state file."""
state = self.create_state()
if not state.torrents:
log.debug("Skipping saving state with no torrents loaded")
log.debug('Skipping saving state with no torrents loaded')
return
filename = "torrents.state"
filename = 'torrents.state'
filepath = os.path.join(self.state_dir, filename)
filepath_bak = filepath + ".bak"
filepath_tmp = filepath + ".tmp"
filepath_bak = filepath + '.bak'
filepath_tmp = filepath + '.tmp'
try:
log.debug("Creating the temporary file: %s", filepath_tmp)
with open(filepath_tmp, "wb", 0) as _file:
log.debug('Creating the temporary file: %s', filepath_tmp)
with open(filepath_tmp, 'wb', 0) as _file:
cPickle.dump(state, _file)
_file.flush()
os.fsync(_file.fileno())
except (OSError, cPickle.PicklingError) as ex:
log.error("Unable to save %s: %s", filename, ex)
log.error('Unable to save %s: %s', filename, ex)
return
try:
log.debug("Creating backup of %s at: %s", filename, filepath_bak)
log.debug('Creating backup of %s at: %s', filename, filepath_bak)
if os.path.isfile(filepath_bak):
os.remove(filepath_bak)
if os.path.isfile(filepath):
os.rename(filepath, filepath_bak)
except OSError as ex:
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
log.error('Unable to backup %s to %s: %s', filepath, filepath_bak, ex)
return
try:
log.debug("Saving %s to: %s", filename, filepath)
log.debug('Saving %s to: %s', filename, filepath)
os.rename(filepath_tmp, filepath)
except OSError as ex:
log.error("Failed to set new state file %s: %s", filepath, ex)
log.error('Failed to set new state file %s: %s', filepath, ex)
if os.path.isfile(filepath_bak):
log.info("Restoring backup of state from: %s", filepath_bak)
log.info('Restoring backup of state from: %s', filepath_bak)
os.rename(filepath_bak, filepath)
def save_resume_data(self, torrent_ids=None, flush_disk_cache=False):
@ -781,22 +781,22 @@ class TorrentManager(component.Component):
dict: A dict of torrents and their resume_data.
"""
filename = "torrents.fastresume"
filename = 'torrents.fastresume'
filepath = os.path.join(self.state_dir, filename)
filepath_bak = filepath + ".bak"
filepath_bak = filepath + '.bak'
old_data_filepath = os.path.join(get_config_dir(), filename)
for _filepath in (filepath, filepath_bak, old_data_filepath):
log.info("Opening %s for load: %s", filename, _filepath)
log.info('Opening %s for load: %s', filename, _filepath)
try:
with open(_filepath, "rb") as _file:
with open(_filepath, 'rb') as _file:
resume_data = lt.bdecode(_file.read())
except (IOError, EOFError, RuntimeError) as ex:
if self.torrents:
log.warning("Unable to load %s: %s", _filepath, ex)
log.warning('Unable to load %s: %s', _filepath, ex)
resume_data = None
else:
log.info("Successfully loaded %s: %s", filename, _filepath)
log.info('Successfully loaded %s: %s', filename, _filepath)
break
# If the libtorrent bdecode doesn't happen properly, it will return None
# so we need to make sure we return a {}
@ -836,38 +836,38 @@ class TorrentManager(component.Component):
if not self.resume_data:
return True
filename = "torrents.fastresume"
filename = 'torrents.fastresume'
filepath = os.path.join(self.state_dir, filename)
filepath_bak = filepath + ".bak"
filepath_tmp = filepath + ".tmp"
filepath_bak = filepath + '.bak'
filepath_tmp = filepath + '.tmp'
try:
log.debug("Creating the temporary file: %s", filepath_tmp)
with open(filepath_tmp, "wb", 0) as _file:
log.debug('Creating the temporary file: %s', filepath_tmp)
with open(filepath_tmp, 'wb', 0) as _file:
_file.write(lt.bencode(self.resume_data))
_file.flush()
os.fsync(_file.fileno())
except (OSError, EOFError) as ex:
log.error("Unable to save %s: %s", filename, ex)
log.error('Unable to save %s: %s', filename, ex)
return False
try:
log.debug("Creating backup of %s at: %s", filename, filepath_bak)
log.debug('Creating backup of %s at: %s', filename, filepath_bak)
if os.path.isfile(filepath_bak):
os.remove(filepath_bak)
if os.path.isfile(filepath):
os.rename(filepath, filepath_bak)
except OSError as ex:
log.error("Unable to backup %s to %s: %s", filepath, filepath_bak, ex)
log.error('Unable to backup %s to %s: %s', filepath, filepath_bak, ex)
return False
try:
log.debug("Saving %s to: %s", filename, filepath)
log.debug('Saving %s to: %s', filename, filepath)
os.rename(filepath_tmp, filepath)
except OSError as ex:
log.error("Failed to set new file %s: %s", filepath, ex)
log.error('Failed to set new file %s: %s', filepath, ex)
if os.path.isfile(filepath_bak):
log.info("Restoring backup from: %s", filepath_bak)
log.info('Restoring backup from: %s', filepath_bak)
os.rename(filepath_bak, filepath)
else:
# Sync the rename operations for the directory
@ -920,58 +920,58 @@ class TorrentManager(component.Component):
def on_set_max_connections_per_torrent(self, key, value):
"""Sets the per-torrent connection limit"""
log.debug("max_connections_per_torrent set to %s...", value)
log.debug('max_connections_per_torrent set to %s...', value)
for key in self.torrents:
self.torrents[key].set_max_connections(value)
def on_set_max_upload_slots_per_torrent(self, key, value):
"""Sets the per-torrent upload slot limit"""
log.debug("max_upload_slots_per_torrent set to %s...", value)
log.debug('max_upload_slots_per_torrent set to %s...', value)
for key in self.torrents:
self.torrents[key].set_max_upload_slots(value)
def on_set_max_upload_speed_per_torrent(self, key, value):
"""Sets the per-torrent upload speed limit"""
log.debug("max_upload_speed_per_torrent set to %s...", value)
log.debug('max_upload_speed_per_torrent set to %s...', value)
for key in self.torrents:
self.torrents[key].set_max_upload_speed(value)
def on_set_max_download_speed_per_torrent(self, key, value):
"""Sets the per-torrent download speed limit"""
log.debug("max_download_speed_per_torrent set to %s...", value)
log.debug('max_download_speed_per_torrent set to %s...', value)
for key in self.torrents:
self.torrents[key].set_max_download_speed(value)
# --- Alert handlers ---
def on_alert_torrent_finished(self, alert):
"""Alert handler for libtorrent torrent_finished_alert"""
log.debug("on_alert_torrent_finished")
log.debug('on_alert_torrent_finished')
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
except (RuntimeError, KeyError):
return
log.debug("Finished %s ", torrent_id)
log.debug('Finished %s ', torrent_id)
# If total_download is 0, do not move, it's likely the torrent wasn't downloaded, but just added.
# Get fresh data from libtorrent, the cache isn't always up to date
total_download = torrent.get_status(["total_payload_download"], update=True)["total_payload_download"]
total_download = torrent.get_status(['total_payload_download'], update=True)['total_payload_download']
if log.isEnabledFor(logging.DEBUG):
log.debug("Torrent settings: is_finished: %s, total_download: %s, move_completed: %s, move_path: %s",
torrent.is_finished, total_download, torrent.options["move_completed"],
torrent.options["move_completed_path"])
log.debug('Torrent settings: is_finished: %s, total_download: %s, move_completed: %s, move_path: %s',
torrent.is_finished, total_download, torrent.options['move_completed'],
torrent.options['move_completed_path'])
torrent.update_state()
if not torrent.is_finished and total_download:
# Move completed download to completed folder if needed
if torrent.options["move_completed"] and \
torrent.options["download_location"] != torrent.options["move_completed_path"]:
if torrent.options['move_completed'] and \
torrent.options['download_location'] != torrent.options['move_completed_path']:
self.waiting_on_finish_moving.append(torrent_id)
torrent.move_storage(torrent.options["move_completed_path"])
torrent.move_storage(torrent.options['move_completed_path'])
else:
torrent.is_finished = True
component.get("EventManager").emit(TorrentFinishedEvent(torrent_id))
component.get('EventManager').emit(TorrentFinishedEvent(torrent_id))
else:
torrent.is_finished = True
@ -994,7 +994,7 @@ class TorrentManager(component.Component):
def on_alert_torrent_paused(self, alert):
"""Alert handler for libtorrent torrent_paused_alert"""
if log.isEnabledFor(logging.DEBUG):
log.debug("on_alert_torrent_paused")
log.debug('on_alert_torrent_paused')
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
@ -1008,7 +1008,7 @@ class TorrentManager(component.Component):
def on_alert_torrent_checked(self, alert):
"""Alert handler for libtorrent torrent_checked_alert"""
if log.isEnabledFor(logging.DEBUG):
log.debug("on_alert_torrent_checked")
log.debug('on_alert_torrent_checked')
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except (RuntimeError, KeyError):
@ -1025,14 +1025,14 @@ class TorrentManager(component.Component):
def on_alert_tracker_reply(self, alert):
"""Alert handler for libtorrent tracker_reply_alert"""
if log.isEnabledFor(logging.DEBUG):
log.debug("on_alert_tracker_reply: %s", decode_string(alert.message()))
log.debug('on_alert_tracker_reply: %s', decode_string(alert.message()))
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except (RuntimeError, KeyError):
return
# Set the tracker status for the torrent
torrent.set_tracker_status("Announce OK")
torrent.set_tracker_status('Announce OK')
# Check for peer information from the tracker, if none then send a scrape request.
if alert.handle.status().num_complete == -1 or alert.handle.status().num_incomplete == -1:
@ -1041,24 +1041,24 @@ class TorrentManager(component.Component):
def on_alert_tracker_announce(self, alert):
"""Alert handler for libtorrent tracker_announce_alert"""
if log.isEnabledFor(logging.DEBUG):
log.debug("on_alert_tracker_announce")
log.debug('on_alert_tracker_announce')
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except (RuntimeError, KeyError):
return
# Set the tracker status for the torrent
torrent.set_tracker_status("Announce Sent")
torrent.set_tracker_status('Announce Sent')
def on_alert_tracker_warning(self, alert):
"""Alert handler for libtorrent tracker_warning_alert"""
log.debug("on_alert_tracker_warning")
log.debug('on_alert_tracker_warning')
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except (RuntimeError, KeyError):
return
# Set the tracker status for the torrent
torrent.set_tracker_status("Warning: %s" % decode_string(alert.message()))
torrent.set_tracker_status('Warning: %s' % decode_string(alert.message()))
def on_alert_tracker_error(self, alert):
"""Alert handler for libtorrent tracker_error_alert"""
@ -1071,17 +1071,17 @@ class TorrentManager(component.Component):
# cannot be replaced by a.e.message because the code is included in the string (for non-'-1').
if not error_message:
error_message = decode_string(alert.error.message())
log.debug("Tracker Error Alert: %s [%s]", decode_string(alert.message()), error_message)
log.debug('Tracker Error Alert: %s [%s]', decode_string(alert.message()), error_message)
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except (RuntimeError, KeyError):
return
torrent.set_tracker_status("Error: " + error_message)
torrent.set_tracker_status('Error: ' + error_message)
def on_alert_storage_moved(self, alert):
"""Alert handler for libtorrent storage_moved_alert"""
log.debug("on_alert_storage_moved")
log.debug('on_alert_storage_moved')
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
@ -1100,11 +1100,11 @@ class TorrentManager(component.Component):
if torrent_id in self.waiting_on_finish_moving:
self.waiting_on_finish_moving.remove(torrent_id)
torrent.is_finished = True
component.get("EventManager").emit(TorrentFinishedEvent(torrent_id))
component.get('EventManager').emit(TorrentFinishedEvent(torrent_id))
def on_alert_storage_moved_failed(self, alert):
"""Alert handler for libtorrent storage_moved_failed_alert"""
log.warning("on_alert_storage_moved_failed: %s", decode_string(alert.message()))
log.warning('on_alert_storage_moved_failed: %s', decode_string(alert.message()))
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
@ -1113,23 +1113,23 @@ class TorrentManager(component.Component):
# Set an Error message and pause the torrent
alert_msg = decode_string(alert.message()).split(':', 1)[1].strip()
torrent.moving_storage = False
torrent.force_error_state("Failed to move download folder: %s" % alert_msg)
torrent.force_error_state('Failed to move download folder: %s' % alert_msg)
if torrent_id in self.waiting_on_finish_moving:
self.waiting_on_finish_moving.remove(torrent_id)
torrent.is_finished = True
component.get("EventManager").emit(TorrentFinishedEvent(torrent_id))
component.get('EventManager').emit(TorrentFinishedEvent(torrent_id))
def on_alert_torrent_resumed(self, alert):
"""Alert handler for libtorrent torrent_resumed_alert"""
log.debug("on_alert_torrent_resumed")
log.debug('on_alert_torrent_resumed')
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
except (RuntimeError, KeyError):
return
torrent.update_state()
component.get("EventManager").emit(TorrentResumedEvent(torrent_id))
component.get('EventManager').emit(TorrentResumedEvent(torrent_id))
def on_alert_state_changed(self, alert):
"""Alert handler for libtorrent state_changed_alert.
@ -1139,7 +1139,7 @@ class TorrentManager(component.Component):
"""
if log.isEnabledFor(logging.DEBUG):
log.debug("on_alert_state_changed")
log.debug('on_alert_state_changed')
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
@ -1155,7 +1155,7 @@ class TorrentManager(component.Component):
def on_alert_save_resume_data(self, alert):
"""Alert handler for libtorrent save_resume_data_alert"""
if log.isEnabledFor(logging.DEBUG):
log.debug("on_alert_save_resume_data")
log.debug('on_alert_save_resume_data')
try:
torrent_id = str(alert.handle.info_hash())
except RuntimeError:
@ -1169,7 +1169,7 @@ class TorrentManager(component.Component):
def on_alert_save_resume_data_failed(self, alert):
"""Alert handler for libtorrent save_resume_data_failed_alert"""
log.debug("on_alert_save_resume_data_failed: %s", decode_string(alert.message()))
log.debug('on_alert_save_resume_data_failed: %s', decode_string(alert.message()))
try:
torrent_id = str(alert.handle.info_hash())
except RuntimeError:
@ -1181,7 +1181,7 @@ class TorrentManager(component.Component):
def on_alert_fastresume_rejected(self, alert):
"""Alert handler for libtorrent fastresume_rejected_alert"""
alert_msg = decode_string(alert.message())
log.error("on_alert_fastresume_rejected: %s", alert_msg)
log.error('on_alert_fastresume_rejected: %s', alert_msg)
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
@ -1189,12 +1189,12 @@ class TorrentManager(component.Component):
return
if alert.error.value() == 134:
if not os.path.isdir(torrent.options["download_location"]):
error_msg = "Unable to locate Download Folder!"
if not os.path.isdir(torrent.options['download_location']):
error_msg = 'Unable to locate Download Folder!'
else:
error_msg = "Missing or invalid torrent data!"
error_msg = 'Missing or invalid torrent data!'
else:
error_msg = "Problem with resume data: %s" % alert_msg.split(":", 1)[1].strip()
error_msg = 'Problem with resume data: %s' % alert_msg.split(':', 1)[1].strip()
torrent.force_error_state(error_msg, restart_to_resume=True)
def on_alert_file_renamed(self, alert):
@ -1204,13 +1204,13 @@ class TorrentManager(component.Component):
TorrentFileRenamedEvent: Files in the torrent have been renamed.
"""
log.debug("on_alert_file_renamed")
log.debug('on_alert_file_renamed')
try:
new_name = decode_string(alert.new_name)
except AttributeError:
# Deprecated in libtorrent 1.1
new_name = decode_string(alert.name)
log.debug("index: %s name: %s", alert.index, new_name)
log.debug('index: %s name: %s', alert.index, new_name)
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
@ -1224,12 +1224,12 @@ class TorrentManager(component.Component):
break
else:
# This is just a regular file rename so send the signal
component.get("EventManager").emit(TorrentFileRenamedEvent(torrent_id, alert.index, new_name))
component.get('EventManager').emit(TorrentFileRenamedEvent(torrent_id, alert.index, new_name))
self.save_resume_data((torrent_id,))
def on_alert_metadata_received(self, alert):
"""Alert handler for libtorrent metadata_received_alert"""
log.debug("on_alert_metadata_received")
log.debug('on_alert_metadata_received')
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except (RuntimeError, KeyError):
@ -1238,7 +1238,7 @@ class TorrentManager(component.Component):
def on_alert_file_error(self, alert):
"""Alert handler for libtorrent file_error_alert"""
log.debug("on_alert_file_error: %s", decode_string(alert.message()))
log.debug('on_alert_file_error: %s', decode_string(alert.message()))
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except (RuntimeError, KeyError):
@ -1252,13 +1252,13 @@ class TorrentManager(component.Component):
TorrentFileCompletedEvent: When an individual file completes downloading.
"""
log.debug("file_completed_alert: %s", decode_string(alert.message()))
log.debug('file_completed_alert: %s', decode_string(alert.message()))
try:
torrent_id = str(alert.handle.info_hash())
except RuntimeError:
return
if torrent_id in self.torrents:
component.get("EventManager").emit(TorrentFileCompletedEvent(torrent_id, alert.index))
component.get('EventManager').emit(TorrentFileCompletedEvent(torrent_id, alert.index))
def on_alert_state_update(self, alert):
"""Alert handler for libtorrent state_update_alert
@ -1267,7 +1267,7 @@ class TorrentManager(component.Component):
of all torrents that changed since last time this was posted.
"""
log.debug("on_status_notification: %s", decode_string(alert.message()))
log.debug('on_status_notification: %s', decode_string(alert.message()))
self.last_state_update_alert_ts = time.time()
for t_status in alert.status:
@ -1291,24 +1291,24 @@ class TorrentManager(component.Component):
"""
external_ip = decode_string(alert.message()).split(' ')[-1]
log.info("on_alert_external_ip: %s", external_ip)
component.get("EventManager").emit(ExternalIPEvent(external_ip))
log.info('on_alert_external_ip: %s', external_ip)
component.get('EventManager').emit(ExternalIPEvent(external_ip))
def on_alert_performance(self, alert):
"""Alert handler for libtorrent performance_alert"""
log.warning("on_alert_performance: %s, %s", decode_string(alert.message()), alert.warning_code)
log.warning('on_alert_performance: %s, %s', decode_string(alert.message()), alert.warning_code)
if alert.warning_code == lt.performance_warning_t.send_buffer_watermark_too_low:
max_send_buffer_watermark = 3 * 1024 * 1024 # 3MiB
settings = self.session.get_settings()
send_buffer_watermark = settings["send_buffer_watermark"]
send_buffer_watermark = settings['send_buffer_watermark']
# If send buffer is too small, try increasing its size by 512KiB (up to max_send_buffer_watermark)
if send_buffer_watermark < max_send_buffer_watermark:
value = send_buffer_watermark + (500 * 1024)
log.info("Increasing send_buffer_watermark from %s to %s Bytes", send_buffer_watermark, value)
component.get("Core").apply_session_setting("send_buffer_watermark", value)
log.info('Increasing send_buffer_watermark from %s to %s Bytes', send_buffer_watermark, value)
component.get('Core').apply_session_setting('send_buffer_watermark', value)
else:
log.warning("send_buffer_watermark reached maximum value: %s Bytes", max_send_buffer_watermark)
log.warning('send_buffer_watermark reached maximum value: %s Bytes', max_send_buffer_watermark)
def separate_keys(self, keys, torrent_ids):
"""Separates the input keys into torrent class keys and plugins keys"""

View File

@ -89,7 +89,7 @@ def _overrides(stack, method, explicit_base_classes=None):
if explicit_base_classes:
# One or more base classes are explicitly given, check only those classes
override_classes = re.search(r'\s*@overrides\((.+)\)\s*', stack[1][4][0]).group(1)
override_classes = [c.strip() for c in override_classes.split(",")]
override_classes = [c.strip() for c in override_classes.split(',')]
check_classes = override_classes
for c in base_classes + check_classes:
@ -108,9 +108,9 @@ def _overrides(stack, method, explicit_base_classes=None):
for cls in check_classes:
if not hasattr(classes[cls], method.__name__):
raise Exception("Function override '%s' not found in superclass: '%s'\n%s"
% (method.__name__, cls, "File: %s:%s" % (stack[1][1], stack[1][2])))
% (method.__name__, cls, 'File: %s:%s' % (stack[1][1], stack[1][2])))
if not any(hasattr(classes[cls], method.__name__) for cls in check_classes):
raise Exception("Function override '%s' not found in any superclass: '%s'\n%s"
% (method.__name__, check_classes, "File: %s:%s" % (stack[1][1], stack[1][2])))
% (method.__name__, check_classes, 'File: %s:%s' % (stack[1][1], stack[1][2])))
return method

View File

@ -49,7 +49,7 @@ class WrappedException(DelugeError):
self.traceback = traceback
def __str__(self):
return "%s\n%s" % (self.message, self.traceback)
return '%s\n%s' % (self.message, self.traceback)
class _ClientSideRecreateError(DelugeError):
@ -60,8 +60,8 @@ class IncompatibleClient(_ClientSideRecreateError):
def __init__(self, daemon_version):
self.daemon_version = daemon_version
msg = "Your deluge client is not compatible with the daemon. "\
"Please upgrade your client to %(daemon_version)s" % \
msg = 'Your deluge client is not compatible with the daemon. '\
'Please upgrade your client to %(daemon_version)s' % \
dict(daemon_version=self.daemon_version)
super(IncompatibleClient, self).__init__(message=msg)
@ -69,7 +69,7 @@ class IncompatibleClient(_ClientSideRecreateError):
class NotAuthorizedError(_ClientSideRecreateError):
def __init__(self, current_level, required_level):
msg = "Auth level too low: %(current_level)s < %(required_level)s" % \
msg = 'Auth level too low: %(current_level)s < %(required_level)s' % \
dict(current_level=current_level, required_level=required_level)
super(NotAuthorizedError, self).__init__(message=msg)
self.current_level = current_level

View File

@ -24,7 +24,7 @@ class DelugeEventMetaClass(type):
"""
def __init__(self, name, bases, dct): # pylint: disable=bad-mcs-method-argument
super(DelugeEventMetaClass, self).__init__(name, bases, dct)
if name != "DelugeEvent":
if name != 'DelugeEvent':
known_events[name] = self
@ -44,7 +44,7 @@ class DelugeEvent(object):
return self.__class__.__name__
def _get_args(self):
if not hasattr(self, "_args"):
if not hasattr(self, '_args'):
return []
return self._args

View File

@ -49,7 +49,7 @@ class HTTPDownloader(client.HTTPDownloader):
self.force_filename = force_filename
self.allow_compression = allow_compression
self.code = None
agent = "Deluge/%s (http://deluge-torrent.org)" % get_version()
agent = 'Deluge/%s (http://deluge-torrent.org)' % get_version()
client.HTTPDownloader.__init__(self, url, filename, headers=headers, agent=agent)
def gotStatus(self, version, status, message): # NOQA
@ -58,19 +58,19 @@ class HTTPDownloader(client.HTTPDownloader):
def gotHeaders(self, headers): # NOQA
if self.code == http.OK:
if "content-length" in headers:
self.total_length = int(headers["content-length"][0])
if 'content-length' in headers:
self.total_length = int(headers['content-length'][0])
else:
self.total_length = 0
if self.allow_compression and "content-encoding" in headers and \
headers["content-encoding"][0] in ("gzip", "x-gzip", "deflate"):
if self.allow_compression and 'content-encoding' in headers and \
headers['content-encoding'][0] in ('gzip', 'x-gzip', 'deflate'):
# Adding 32 to the wbits enables gzip & zlib decoding (with automatic header detection)
# Adding 16 just enables gzip decoding (no zlib)
self.decoder = zlib.decompressobj(zlib.MAX_WBITS + 32)
if "content-disposition" in headers and not self.force_filename:
new_file_name = str(headers["content-disposition"][0]).split(";")[1].split("=")[1]
if 'content-disposition' in headers and not self.force_filename:
new_file_name = str(headers['content-disposition'][0]).split(';')[1].split('=')[1]
new_file_name = sanitise_filename(new_file_name)
new_file_name = os.path.join(os.path.split(self.value)[0], new_file_name)
@ -79,14 +79,14 @@ class HTTPDownloader(client.HTTPDownloader):
fileext = os.path.splitext(new_file_name)[1]
while os.path.isfile(new_file_name):
# Increment filename if already exists
new_file_name = "%s-%s%s" % (fileroot, count, fileext)
new_file_name = '%s-%s%s' % (fileroot, count, fileext)
count += 1
self.fileName = new_file_name
self.value = new_file_name
elif self.code in (http.MOVED_PERMANENTLY, http.FOUND, http.SEE_OTHER, http.TEMPORARY_REDIRECT):
location = headers["location"][0]
location = headers['location'][0]
error = PageRedirect(self.code, location=location)
self.noPage(Failure(error))
@ -133,7 +133,7 @@ def sanitise_filename(filename):
filename = os.path.basename(filename)
filename = filename.strip()
if filename.startswith(".") or ";" in filename or "|" in filename:
if filename.startswith('.') or ';' in filename or '|' in filename:
# Dodgy server, log it
log.warning("Potentially malicious server: trying to write to file '%s'", filename)
@ -172,11 +172,11 @@ def _download_file(url, filename, callback=None, headers=None, force_filename=Fa
if allow_compression:
if not headers:
headers = {}
headers["accept-encoding"] = "deflate, gzip, x-gzip"
headers['accept-encoding'] = 'deflate, gzip, x-gzip'
# In Twisted 13.1.0 _parse() function replaced by _URI class.
# In Twisted 15.0.0 _URI class renamed to URI.
if hasattr(client, "_parse"):
if hasattr(client, '_parse'):
scheme, host, port, dummy_path = client._parse(url)
else:
try:
@ -190,7 +190,7 @@ def _download_file(url, filename, callback=None, headers=None, force_filename=Fa
port = uri.port
factory = HTTPDownloader(url, filename, callback, headers, force_filename, allow_compression)
if scheme == "https":
if scheme == 'https':
from twisted.internet import ssl
# ClientTLSOptions in Twisted >= 14, see ticket #2765 for details on this addition.
try:
@ -241,12 +241,12 @@ def download_file(url, filename, callback=None, headers=None, force_filename=Fal
"""
def on_download_success(result):
log.debug("Download success!")
log.debug('Download success!')
return result
def on_download_fail(failure):
if failure.check(PageRedirect) and handle_redirects:
new_url = urljoin(url, failure.getErrorMessage().split(" to ")[1])
new_url = urljoin(url, failure.getErrorMessage().split(' to ')[1])
result = _download_file(new_url, filename, callback=callback, headers=headers,
force_filename=force_filename,
allow_compression=allow_compression)

View File

@ -21,14 +21,14 @@ from twisted.python.log import PythonLoggingObserver
from deluge import common
__all__ = ("setup_logger", "set_logger_level", "get_plugin_logger", "LOG")
__all__ = ('setup_logger', 'set_logger_level', 'get_plugin_logger', 'LOG')
LoggingLoggerClass = logging.getLoggerClass()
if "dev" in common.get_version():
DEFAULT_LOGGING_FORMAT = "%%(asctime)s.%%(msecs)03.0f [%%(levelname)-8s][%%(name)-%ds:%%(lineno)-4d] %%(message)s"
if 'dev' in common.get_version():
DEFAULT_LOGGING_FORMAT = '%%(asctime)s.%%(msecs)03.0f [%%(levelname)-8s][%%(name)-%ds:%%(lineno)-4d] %%(message)s'
else:
DEFAULT_LOGGING_FORMAT = "%%(asctime)s [%%(levelname)-8s][%%(name)-%ds:%%(lineno)-4d] %%(message)s"
DEFAULT_LOGGING_FORMAT = '%%(asctime)s [%%(levelname)-8s][%%(name)-%ds:%%(lineno)-4d] %%(message)s'
MAX_LOGGER_NAME_LENGTH = 10
@ -44,7 +44,7 @@ class Logging(LoggingLoggerClass):
for handler in logging.getLogger().handlers:
handler.setFormatter(logging.Formatter(
DEFAULT_LOGGING_FORMAT % MAX_LOGGER_NAME_LENGTH,
datefmt="%H:%M:%S"
datefmt='%H:%M:%S'
))
@defer.inlineCallbacks
@ -83,12 +83,12 @@ class Logging(LoggingLoggerClass):
def findCaller(self): # NOQA
f = logging.currentframe().f_back
rv = "(unknown file)", 0, "(unknown function)"
while hasattr(f, "f_code"):
rv = '(unknown file)', 0, '(unknown function)'
while hasattr(f, 'f_code'):
co = f.f_code
filename = os.path.normcase(co.co_filename)
if filename in (__file__.replace(".pyc", ".py"),
defer.__file__.replace(".pyc", ".py")):
if filename in (__file__.replace('.pyc', '.py'),
defer.__file__.replace('.pyc', '.py')):
f = f.f_back
continue
rv = (filename, f.f_lineno, co.co_name)
@ -96,18 +96,18 @@ class Logging(LoggingLoggerClass):
return rv
levels = {
"info": logging.INFO,
"warn": logging.WARNING,
"warning": logging.WARNING,
"error": logging.ERROR,
"none": logging.CRITICAL,
"debug": logging.DEBUG,
"trace": 5,
"garbage": 1
'info': logging.INFO,
'warn': logging.WARNING,
'warning': logging.WARNING,
'error': logging.ERROR,
'none': logging.CRITICAL,
'debug': logging.DEBUG,
'trace': 5,
'garbage': 1
}
def setup_logger(level="error", filename=None, filemode="w", logrotate=None,
def setup_logger(level='error', filename=None, filemode='w', logrotate=None,
output_stream=sys.stdout, twisted_observer=True):
"""
Sets up the basic logger and if `:param:filename` is set, then it will log
@ -125,8 +125,8 @@ def setup_logger(level="error", filename=None, filemode="w", logrotate=None,
"""
if logging.getLoggerClass() is not Logging:
logging.setLoggerClass(Logging)
logging.addLevelName(5, "TRACE")
logging.addLevelName(1, "GARBAGE")
logging.addLevelName(5, 'TRACE')
logging.addLevelName(1, 'GARBAGE')
level = levels.get(level, logging.ERROR)
@ -135,13 +135,13 @@ def setup_logger(level="error", filename=None, filemode="w", logrotate=None,
if filename and logrotate:
handler = logging.handlers.RotatingFileHandler(
filename, maxBytes=logrotate,
backupCount=5, encoding="utf-8"
backupCount=5, encoding='utf-8'
)
elif filename and filemode == "w":
elif filename and filemode == 'w':
handler_cls = logging.FileHandler
if not common.windows_check():
handler_cls = getattr(logging.handlers, "WatchedFileHandler", logging.FileHandler)
handler = handler_cls(filename, mode=filemode, encoding="utf-8")
handler_cls = getattr(logging.handlers, 'WatchedFileHandler', logging.FileHandler)
handler = handler_cls(filename, mode=filemode, encoding='utf-8')
else:
handler = logging.StreamHandler(stream=output_stream)
@ -149,7 +149,7 @@ def setup_logger(level="error", filename=None, filemode="w", logrotate=None,
formatter = logging.Formatter(
DEFAULT_LOGGING_FORMAT % MAX_LOGGER_NAME_LENGTH,
datefmt="%H:%M:%S"
datefmt='%H:%M:%S'
)
handler.setFormatter(formatter)
@ -182,9 +182,9 @@ class TwistedLoggingObserver(PythonLoggingObserver):
def emit(self, event_dict):
log = logging.getLogger(__name__)
if "log_failure" in event_dict:
fmt = "%(log_namespace)s \n%(log_failure)s"
getattr(LoggingLoggerClass, event_dict["log_level"].name)(log, fmt % (event_dict))
if 'log_failure' in event_dict:
fmt = '%(log_namespace)s \n%(log_failure)s'
getattr(LoggingLoggerClass, event_dict['log_level'].name)(log, fmt % (event_dict))
else:
PythonLoggingObserver.emit(self, event_dict)
@ -208,17 +208,17 @@ def tweak_logging_levels():
the command line.
"""
from deluge import configmanager
logging_config_file = os.path.join(configmanager.get_config_dir(), "logging.conf")
logging_config_file = os.path.join(configmanager.get_config_dir(), 'logging.conf')
if not os.path.isfile(logging_config_file):
return
log = logging.getLogger(__name__)
log.warn("logging.conf found! tweaking logging levels from %s",
log.warn('logging.conf found! tweaking logging levels from %s',
logging_config_file)
with open(logging_config_file, "r") as _file:
with open(logging_config_file, 'r') as _file:
for line in _file:
if line.strip().startswith("#"):
if line.strip().startswith('#'):
continue
name, level = line.strip().split(":")
name, level = line.strip().split(':')
if level not in levels:
continue
@ -236,7 +236,7 @@ def set_logger_level(level, logger_name=None):
tweak the root logger level.
"""
logging.getLogger(logger_name).setLevel(levels.get(level, "error"))
logging.getLogger(logger_name).setLevel(levels.get(level, 'error'))
def get_plugin_logger(logger_name):
@ -246,14 +246,14 @@ def get_plugin_logger(logger_name):
module_stack = stack.pop(0) # The module that called the log function
caller_module = inspect.getmodule(module_stack[0])
# In some weird cases caller_module might be None, try to continue
caller_module_name = getattr(caller_module, "__name__", "")
caller_module_name = getattr(caller_module, '__name__', '')
warnings.warn_explicit(DEPRECATION_WARNING, DeprecationWarning,
module_stack[1], module_stack[2],
caller_module_name)
if "deluge.plugins." in logger_name:
if 'deluge.plugins.' in logger_name:
return logging.getLogger(logger_name)
return logging.getLogger("deluge.plugin.%s" % logger_name)
return logging.getLogger('deluge.plugin.%s' % logger_name)
DEPRECATION_WARNING = """You seem to be using old style logging on your code, ie:
@ -282,13 +282,13 @@ Triggering code:"""
class _BackwardsCompatibleLOG(object):
def __getattribute__(self, name):
import warnings
logger_name = "deluge"
logger_name = 'deluge'
stack = inspect.stack()
stack.pop(0) # The logging call from this module
module_stack = stack.pop(0) # The module that called the log function
caller_module = inspect.getmodule(module_stack[0])
# In some weird cases caller_module might be None, try to continue
caller_module_name = getattr(caller_module, "__name__", "")
caller_module_name = getattr(caller_module, '__name__', '')
warnings.warn_explicit(DEPRECATION_WARNING, DeprecationWarning,
module_stack[1], module_stack[2],
caller_module_name)
@ -297,16 +297,16 @@ class _BackwardsCompatibleLOG(object):
module = inspect.getmodule(member[0])
if not module:
continue
if module.__name__ in ("deluge.plugins.pluginbase",
"deluge.plugins.init"):
logger_name += ".plugin.%s" % caller_module_name
if module.__name__ in ('deluge.plugins.pluginbase',
'deluge.plugins.init'):
logger_name += '.plugin.%s' % caller_module_name
# Monkey Patch The Plugin Module
caller_module.log = logging.getLogger(logger_name)
break
else:
logging.getLogger(logger_name).warning(
"Unable to monkey-patch the calling module's `log` attribute! "
"You should really update and rebuild your plugins..."
'You should really update and rebuild your plugins...'
)
return getattr(logging.getLogger(logger_name), name)

View File

@ -46,7 +46,7 @@ class TorrentMetadata(object):
def __init__(self):
self.__data_path = None
self.__piece_size = 0
self.__comment = ""
self.__comment = ''
self.__private = False
self.__trackers = []
self.__webseeds = []
@ -65,37 +65,37 @@ class TorrentMetadata(object):
"""
if not self.data_path:
raise InvalidPath("Need to set a data_path!")
raise InvalidPath('Need to set a data_path!')
torrent = {
"info": {}
'info': {}
}
if self.comment:
torrent["comment"] = self.comment.encode("UTF-8")
torrent['comment'] = self.comment.encode('UTF-8')
if self.private:
torrent["info"]["private"] = True
torrent['info']['private'] = True
if self.trackers:
torrent["announce"] = self.trackers[0][0]
torrent["announce-list"] = self.trackers
torrent['announce'] = self.trackers[0][0]
torrent['announce-list'] = self.trackers
else:
torrent["announce"] = ""
torrent['announce'] = ''
if self.webseeds:
httpseeds = []
webseeds = []
for w in self.webseeds:
if w.endswith(".php"):
if w.endswith('.php'):
httpseeds.append(w)
else:
webseeds.append(w)
if httpseeds:
torrent["httpseeds"] = httpseeds
torrent['httpseeds'] = httpseeds
if webseeds:
torrent["url-list"] = webseeds
torrent['url-list'] = webseeds
datasize = get_path_size(self.data_path)
@ -112,11 +112,11 @@ class TorrentMetadata(object):
if datasize % piece_size:
num_pieces += 1
torrent["info"]["piece length"] = piece_size
torrent['info']['piece length'] = piece_size
# Create the info
if os.path.isdir(self.data_path):
torrent["info"]["name"] = os.path.split(self.data_path)[1]
torrent['info']['name'] = os.path.split(self.data_path)[1]
files = []
padding_count = 0
# Collect a list of file paths and add padding files if necessary
@ -124,8 +124,8 @@ class TorrentMetadata(object):
for index, filename in enumerate(filenames):
size = get_path_size(os.path.join(self.data_path, dirpath, filename))
p = dirpath[len(self.data_path):]
p = p.lstrip("/")
p = p.split("/")
p = p.lstrip('/')
p = p.split('/')
if p[0]:
p += [filename]
else:
@ -136,7 +136,7 @@ class TorrentMetadata(object):
left = size % piece_size
if left:
p = list(p)
p[-1] = "_____padding_file_" + str(padding_count)
p[-1] = '_____padding_file_' + str(padding_count)
files.append((piece_size - left, p))
padding_count += 1
@ -147,17 +147,17 @@ class TorrentMetadata(object):
fs = []
pieces = []
# Create the piece hashes
buf = ""
buf = ''
for size, path in files:
path = [s.decode(sys.getfilesystemencoding()).encode("UTF-8") for s in path]
fs.append({"length": size, "path": path})
if path[-1].startswith("_____padding_file_"):
buf += "\0" * size
path = [s.decode(sys.getfilesystemencoding()).encode('UTF-8') for s in path]
fs.append({'length': size, 'path': path})
if path[-1].startswith('_____padding_file_'):
buf += '\0' * size
pieces.append(sha(buf).digest())
buf = ""
fs[-1]["attr"] = "p"
buf = ''
fs[-1]['attr'] = 'p'
else:
with open(os.path.join(self.data_path, *path), "rb") as _file:
with open(os.path.join(self.data_path, *path), 'rb') as _file:
r = _file.read(piece_size - len(buf))
while r:
buf += r
@ -166,7 +166,7 @@ class TorrentMetadata(object):
# Run the progress function if necessary
if progress:
progress(len(pieces), num_pieces)
buf = ""
buf = ''
else:
break
r = _file.read(piece_size - len(buf))
@ -175,17 +175,17 @@ class TorrentMetadata(object):
pieces.append(sha(buf).digest())
if progress:
progress(len(pieces), num_pieces)
buf = ""
buf = ''
torrent["info"]["pieces"] = "".join(pieces)
torrent["info"]["files"] = fs
torrent['info']['pieces'] = ''.join(pieces)
torrent['info']['files'] = fs
elif os.path.isfile(self.data_path):
torrent["info"]["name"] = os.path.split(self.data_path)[1]
torrent["info"]["length"] = get_path_size(self.data_path)
torrent['info']['name'] = os.path.split(self.data_path)[1]
torrent['info']['length'] = get_path_size(self.data_path)
pieces = []
with open(self.data_path, "rb") as _file:
with open(self.data_path, 'rb') as _file:
r = _file.read(piece_size)
while r:
pieces.append(sha(r).digest())
@ -194,10 +194,10 @@ class TorrentMetadata(object):
r = _file.read(piece_size)
torrent["info"]["pieces"] = "".join(pieces)
torrent['info']['pieces'] = ''.join(pieces)
# Write out the torrent file
with open(torrent_path, "wb") as _file:
with open(torrent_path, 'wb') as _file:
_file.write(bencode(torrent))
def get_data_path(self):
@ -228,7 +228,7 @@ class TorrentMetadata(object):
if os.path.exists(path) and (os.path.isdir(path) or os.path.isfile(path)):
self.__data_path = os.path.abspath(path)
else:
raise InvalidPath("No such file or directory: %s" % path)
raise InvalidPath('No such file or directory: %s' % path)
def get_piece_size(self):
"""The size of the pieces.
@ -254,7 +254,7 @@ class TorrentMetadata(object):
"""
if size % 16 and size:
raise InvalidPieceSize("Piece size must be a multiple of 16 KiB")
raise InvalidPieceSize('Piece size must be a multiple of 16 KiB')
self.__piece_size = size
def get_comment(self):

View File

@ -47,10 +47,10 @@ def get_filesystem_encoding():
def decode_from_filesystem(path):
encoding = get_filesystem_encoding()
if encoding is None:
assert isinstance(path, unicode), "Path should be unicode not %s" % type(path)
assert isinstance(path, unicode), 'Path should be unicode not %s' % type(path)
decoded_path = path
else:
assert isinstance(path, str), "Path should be str not %s" % type(path)
assert isinstance(path, str), 'Path should be str not %s' % type(path)
decoded_path = path.decode(encoding)
return decoded_path
@ -65,7 +65,7 @@ class RemoteFileProgress(object):
self.session_id = session_id
def __call__(self, piece_count, num_pieces):
component.get("RPCServer").emit_event_for_session_id(
component.get('RPCServer').emit_event_for_session_id(
self.session_id, CreateTorrentProgressEvent(piece_count, num_pieces)
)
@ -86,11 +86,11 @@ def make_meta_file(path, url, piece_length, progress=None, title=None, comment=N
f = target
if progress is None:
session_id = component.get("RPCServer").get_session_id()
session_id = component.get('RPCServer').get_session_id()
if not session_id:
progress = dummy
else:
progress = RemoteFileProgress(component.get("RPCServer").get_session_id())
progress = RemoteFileProgress(component.get('RPCServer').get_session_id())
info = makeinfo(path, piece_length, progress, name, content_type, private)
@ -99,18 +99,18 @@ def make_meta_file(path, url, piece_length, progress=None, title=None, comment=N
data['info'] = info
if title:
data['title'] = title.encode("utf8")
data['title'] = title.encode('utf8')
if comment:
data['comment'] = comment.encode("utf8")
data['comment'] = comment.encode('utf8')
if safe:
data['safe'] = safe.encode("utf8")
data['safe'] = safe.encode('utf8')
httpseeds = []
url_list = []
if webseeds:
for webseed in webseeds:
if webseed.endswith(".php"):
if webseed.endswith('.php'):
httpseeds.append(webseed)
else:
url_list.append(webseed)
@ -120,12 +120,12 @@ def make_meta_file(path, url, piece_length, progress=None, title=None, comment=N
if httpseeds:
data['httpseeds'] = httpseeds
if created_by:
data['created by'] = created_by.encode("utf8")
data['created by'] = created_by.encode('utf8')
if trackers and (len(trackers[0]) > 1 or len(trackers) > 1):
data['announce-list'] = trackers
data["encoding"] = "UTF-8"
data['encoding'] = 'UTF-8'
h.write(bencode(data))
h.close()

View File

@ -41,9 +41,9 @@ def get_completion_paths(args):
:rtype: list
"""
args["paths"] = []
path_value = args["completion_text"]
hidden_files = args["show_hidden_files"]
args['paths'] = []
path_value = args['completion_text']
hidden_files = args['show_hidden_files']
def get_subdirs(dirname):
try:
@ -78,5 +78,5 @@ def get_completion_paths(args):
p += os.path.sep
matching_dirs.append(p)
args["paths"] = sorted(matching_dirs)
args['paths'] = sorted(matching_dirs)
return args

View File

@ -24,15 +24,15 @@ import deluge.configmanager
log = logging.getLogger(__name__)
METADATA_KEYS = [
"Name",
"License",
"Author",
"Home-page",
"Summary",
"Platform",
"Version",
"Author-email",
"Description",
'Name',
'License',
'Author',
'Home-page',
'Summary',
'Platform',
'Version',
'Author-email',
'Description',
]
DEPRECATION_WARNING = """
@ -50,13 +50,13 @@ class PluginManagerBase(object):
"""PluginManagerBase is a base class for PluginManagers to inherit"""
def __init__(self, config_file, entry_name):
log.debug("Plugin manager init..")
log.debug('Plugin manager init..')
self.config = deluge.configmanager.ConfigManager(config_file)
# Create the plugins folder if it doesn't exist
if not os.path.exists(os.path.join(deluge.configmanager.get_config_dir(), "plugins")):
os.mkdir(os.path.join(deluge.configmanager.get_config_dir(), "plugins"))
if not os.path.exists(os.path.join(deluge.configmanager.get_config_dir(), 'plugins')):
os.mkdir(os.path.join(deluge.configmanager.get_config_dir(), 'plugins'))
# This is the entry we want to load..
self.entry_name = entry_name
@ -69,7 +69,7 @@ class PluginManagerBase(object):
def enable_plugins(self):
# Load plugins that are enabled in the config.
for name in self.config["enabled_plugins"]:
for name in self.config['enabled_plugins']:
self.enable_plugin(name)
def disable_plugins(self):
@ -91,9 +91,9 @@ class PluginManagerBase(object):
def scan_for_plugins(self):
"""Scans for available plugins"""
base_plugin_dir = deluge.common.resource_filename("deluge", "plugins")
base_plugin_dir = deluge.common.resource_filename('deluge', 'plugins')
pkg_resources.working_set.add_entry(base_plugin_dir)
user_plugin_dir = os.path.join(deluge.configmanager.get_config_dir(), "plugins")
user_plugin_dir = os.path.join(deluge.configmanager.get_config_dir(), 'plugins')
plugins_dirs = [base_plugin_dir]
for dirname in os.listdir(base_plugin_dir):
@ -107,7 +107,7 @@ class PluginManagerBase(object):
self.available_plugins = []
for name in self.pkg_env:
log.debug("Found plugin: %s %s at %s",
log.debug('Found plugin: %s %s at %s',
self.pkg_env[name][0].project_name,
self.pkg_env[name][0].version,
self.pkg_env[name][0].location)
@ -125,14 +125,14 @@ class PluginManagerBase(object):
"""
if plugin_name not in self.available_plugins:
log.warning("Cannot enable non-existant plugin %s", plugin_name)
log.warning('Cannot enable non-existant plugin %s', plugin_name)
return defer.succeed(False)
if plugin_name in self.plugins:
log.warning("Cannot enable already enabled plugin %s", plugin_name)
log.warning('Cannot enable already enabled plugin %s', plugin_name)
return defer.succeed(True)
plugin_name = plugin_name.replace(" ", "-")
plugin_name = plugin_name.replace(' ', '-')
egg = self.pkg_env[plugin_name][0]
egg.activate()
return_d = defer.succeed(True)
@ -141,12 +141,12 @@ class PluginManagerBase(object):
entry_point = egg.get_entry_info(self.entry_name, name)
try:
cls = entry_point.load()
instance = cls(plugin_name.replace("-", "_"))
instance = cls(plugin_name.replace('-', '_'))
except component.ComponentAlreadyRegistered as ex:
log.error(ex)
return defer.succeed(False)
except Exception as ex:
log.error("Unable to instantiate plugin %r from %r!", name, egg.location)
log.error('Unable to instantiate plugin %r from %r!', name, egg.location)
log.exception(ex)
continue
try:
@ -156,25 +156,25 @@ class PluginManagerBase(object):
log.exception(ex)
return_d = defer.fail(False)
if not instance.__module__.startswith("deluge.plugins."):
if not instance.__module__.startswith('deluge.plugins.'):
import warnings
warnings.warn_explicit(
DEPRECATION_WARNING % name,
DeprecationWarning,
instance.__module__, 0
)
if self._component_state == "Started":
if self._component_state == 'Started':
def on_enabled(result, instance):
return component.start([instance.plugin._component_name])
return_d.addCallback(on_enabled, instance)
def on_started(result, instance):
plugin_name_space = plugin_name.replace("-", " ")
plugin_name_space = plugin_name.replace('-', ' ')
self.plugins[plugin_name_space] = instance
if plugin_name_space not in self.config["enabled_plugins"]:
log.debug("Adding %s to enabled_plugins list in config", plugin_name_space)
self.config["enabled_plugins"].append(plugin_name_space)
log.info("Plugin %s enabled..", plugin_name_space)
if plugin_name_space not in self.config['enabled_plugins']:
log.debug('Adding %s to enabled_plugins list in config', plugin_name_space)
self.config['enabled_plugins'].append(plugin_name_space)
log.info('Plugin %s enabled..', plugin_name_space)
return True
def on_started_error(result, instance):
@ -218,13 +218,13 @@ class PluginManagerBase(object):
try:
component.deregister(self.plugins[name].plugin)
del self.plugins[name]
self.config["enabled_plugins"].remove(name)
self.config['enabled_plugins'].remove(name)
except Exception as ex:
log.error("Unable to disable plugin '%s'!", name)
log.exception(ex)
ret = False
else:
log.info("Plugin %s disabled..", name)
log.info('Plugin %s disabled..', name)
return ret
d.addBoth(on_disabled)
@ -233,25 +233,25 @@ class PluginManagerBase(object):
def get_plugin_info(self, name):
"""Returns a dictionary of plugin info from the metadata"""
info = {}.fromkeys(METADATA_KEYS)
last_header = ""
last_header = ''
cont_lines = []
# Missing plugin info
if not self.pkg_env[name]:
log.warn("Failed to retrive info for plugin '%s'", name)
for k in info:
info[k] = "not available"
info[k] = 'not available'
return info
for line in self.pkg_env[name][0].get_metadata("PKG-INFO").splitlines():
for line in self.pkg_env[name][0].get_metadata('PKG-INFO').splitlines():
if not line:
continue
if line[0] in ' \t' and (len(line.split(":", 1)) == 1 or line.split(":", 1)[0] not in info.keys()):
if line[0] in ' \t' and (len(line.split(':', 1)) == 1 or line.split(':', 1)[0] not in info.keys()):
# This is a continuation
cont_lines.append(line.strip())
else:
if cont_lines:
info[last_header] = "\n".join(cont_lines).strip()
info[last_header] = '\n'.join(cont_lines).strip()
cont_lines = []
if line.split(":", 1)[0] in info.keys():
last_header = line.split(":", 1)[0]
info[last_header] = line.split(":", 1)[1].strip()
if line.split(':', 1)[0] in info.keys():
last_header = line.split(':', 1)[0]
info[last_header] = line.split(':', 1)[1].strip()
return info

View File

@ -18,4 +18,4 @@ import pkg_resources
def get_resource(filename):
return pkg_resources.resource_filename("deluge.plugins.autoadd", os.path.join("data", filename))
return pkg_resources.resource_filename('deluge.plugins.autoadd', os.path.join('data', filename))

View File

@ -33,35 +33,35 @@ log = logging.getLogger(__name__)
DEFAULT_PREFS = {
"watchdirs": {},
"next_id": 1
'watchdirs': {},
'next_id': 1
}
OPTIONS_AVAILABLE = { # option: builtin
"enabled": False,
"path": False,
"append_extension": False,
"copy_torrent": False,
"delete_copy_torrent_toggle": False,
"abspath": False,
"download_location": True,
"max_download_speed": True,
"max_upload_speed": True,
"max_connections": True,
"max_upload_slots": True,
"prioritize_first_last": True,
"auto_managed": True,
"stop_at_ratio": True,
"stop_ratio": True,
"remove_at_ratio": True,
"move_completed": True,
"move_completed_path": True,
"label": False,
"add_paused": True,
"queue_to_top": False,
"owner": True,
"seed_mode": True
'enabled': False,
'path': False,
'append_extension': False,
'copy_torrent': False,
'delete_copy_torrent_toggle': False,
'abspath': False,
'download_location': True,
'max_download_speed': True,
'max_upload_speed': True,
'max_connections': True,
'max_upload_slots': True,
'prioritize_first_last': True,
'auto_managed': True,
'stop_at_ratio': True,
'stop_ratio': True,
'remove_at_ratio': True,
'move_completed': True,
'move_completed_path': True,
'label': False,
'add_paused': True,
'queue_to_top': False,
'owner': True,
'seed_mode': True
}
MAX_NUM_ATTEMPTS = 10
@ -82,13 +82,13 @@ class Core(CorePluginBase):
def enable(self):
# reduce typing, assigning some values to self...
self.config = deluge.configmanager.ConfigManager("autoadd.conf", DEFAULT_PREFS)
self.config = deluge.configmanager.ConfigManager('autoadd.conf', DEFAULT_PREFS)
self.config.run_converter((0, 1), 2, self.__migrate_config_1_to_2)
self.config.save()
self.watchdirs = self.config["watchdirs"]
self.watchdirs = self.config['watchdirs']
component.get("EventManager").register_event_handler(
"PreTorrentRemovedEvent", self.__on_pre_torrent_removed
component.get('EventManager').register_event_handler(
'PreTorrentRemovedEvent', self.__on_pre_torrent_removed
)
# Dict of Filename:Attempts
@ -100,13 +100,13 @@ class Core(CorePluginBase):
def enable_looping(self):
# Enable all looping calls for enabled watchdirs here
for watchdir_id, watchdir in self.watchdirs.iteritems():
if watchdir["enabled"]:
if watchdir['enabled']:
self.enable_watchdir(watchdir_id)
def disable(self):
# disable all running looping calls
component.get("EventManager").deregister_event_handler(
"PreTorrentRemovedEvent", self.__on_pre_torrent_removed
component.get('EventManager').deregister_event_handler(
'PreTorrentRemovedEvent', self.__on_pre_torrent_removed
)
for loopingcall in self.update_timers.itervalues():
loopingcall.stop()
@ -121,45 +121,45 @@ class Core(CorePluginBase):
watchdir_id = str(watchdir_id)
options = self._make_unicode(options)
check_input(
watchdir_id in self.watchdirs, _("Watch folder does not exist.")
watchdir_id in self.watchdirs, _('Watch folder does not exist.')
)
if "path" in options:
options["abspath"] = os.path.abspath(options["path"])
if 'path' in options:
options['abspath'] = os.path.abspath(options['path'])
check_input(
os.path.isdir(options["abspath"]), _("Path does not exist.")
os.path.isdir(options['abspath']), _('Path does not exist.')
)
for w_id, w in self.watchdirs.iteritems():
if options["abspath"] == w["abspath"] and watchdir_id != w_id:
raise Exception("Path is already being watched.")
if options['abspath'] == w['abspath'] and watchdir_id != w_id:
raise Exception('Path is already being watched.')
for key in options:
if key not in OPTIONS_AVAILABLE:
if key not in [key2 + "_toggle" for key2 in OPTIONS_AVAILABLE.iterkeys()]:
raise Exception("autoadd: Invalid options key:%s" % key)
if key not in [key2 + '_toggle' for key2 in OPTIONS_AVAILABLE.iterkeys()]:
raise Exception('autoadd: Invalid options key:%s' % key)
# disable the watch loop if it was active
if watchdir_id in self.update_timers:
self.disable_watchdir(watchdir_id)
self.watchdirs[watchdir_id].update(options)
# re-enable watch loop if appropriate
if self.watchdirs[watchdir_id]["enabled"]:
if self.watchdirs[watchdir_id]['enabled']:
self.enable_watchdir(watchdir_id)
self.config.save()
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
component.get('EventManager').emit(AutoaddOptionsChangedEvent())
def load_torrent(self, filename, magnet):
try:
log.debug("Attempting to open %s for add.", filename)
log.debug('Attempting to open %s for add.', filename)
if magnet:
with open(filename, "r") as _file:
with open(filename, 'r') as _file:
filedump = _file.read()
else:
with open(filename, "rb") as _file:
with open(filename, 'rb') as _file:
filedump = _file.read()
if not filedump:
raise RuntimeError("Torrent is 0 bytes!")
raise RuntimeError('Torrent is 0 bytes!')
except IOError as ex:
log.warning("Unable to open %s: %s", filename, ex)
log.warning('Unable to open %s: %s', filename, ex)
raise ex
# Get the info to see if any exceptions are raised
@ -169,16 +169,16 @@ class Core(CorePluginBase):
return base64.encodestring(filedump)
def split_magnets(self, filename):
log.debug("Attempting to open %s for splitting magnets.", filename)
log.debug('Attempting to open %s for splitting magnets.', filename)
magnets = []
try:
with open(filename, "r") as _file:
with open(filename, 'r') as _file:
for line in _file:
line = line.strip()
if line:
magnets.append(line)
except IOError as ex:
log.warning("Unable to open %s: %s", filename, ex)
log.warning('Unable to open %s: %s', filename, ex)
if len(magnets) < 2:
return []
@ -186,79 +186,79 @@ class Core(CorePluginBase):
n = 0
path = filename.rsplit(os.sep, 1)[0]
for magnet in magnets:
for part in magnet.split("&"):
if part.startswith("dn="):
mname = os.sep.join([path, part[3:] + ".magnet"])
for part in magnet.split('&'):
if part.startswith('dn='):
mname = os.sep.join([path, part[3:] + '.magnet'])
break
else:
mname = ".".join([filename, str(n), "magnet"])
mname = '.'.join([filename, str(n), 'magnet'])
n += 1
try:
with open(mname, "w") as _mfile:
with open(mname, 'w') as _mfile:
_mfile.write(magnet)
except IOError as ex:
log.warning("Unable to open %s: %s", mname, ex)
log.warning('Unable to open %s: %s', mname, ex)
return magnets
def update_watchdir(self, watchdir_id):
"""Check the watch folder for new torrents to add."""
log.trace("Updating watchdir id: %s", watchdir_id)
log.trace('Updating watchdir id: %s', watchdir_id)
watchdir_id = str(watchdir_id)
watchdir = self.watchdirs[watchdir_id]
if not watchdir["enabled"]:
if not watchdir['enabled']:
# We shouldn't be updating because this watchdir is not enabled
log.debug("Watchdir id %s is not enabled. Disabling it.",
log.debug('Watchdir id %s is not enabled. Disabling it.',
watchdir_id)
self.disable_watchdir(watchdir_id)
return
if not os.path.isdir(watchdir["abspath"]):
log.warning("Invalid AutoAdd folder: %s", watchdir["abspath"])
if not os.path.isdir(watchdir['abspath']):
log.warning('Invalid AutoAdd folder: %s', watchdir['abspath'])
self.disable_watchdir(watchdir_id)
return
# Generate options dict for watchdir
opts = {}
if "stop_at_ratio_toggle" in watchdir:
watchdir["stop_ratio_toggle"] = watchdir["stop_at_ratio_toggle"]
if 'stop_at_ratio_toggle' in watchdir:
watchdir['stop_ratio_toggle'] = watchdir['stop_at_ratio_toggle']
# We default to True when reading _toggle values, so a config
# without them is valid, and applies all its settings.
for option, value in watchdir.iteritems():
if OPTIONS_AVAILABLE.get(option):
if watchdir.get(option + "_toggle", True) or option in ["owner", "seed_mode"]:
if watchdir.get(option + '_toggle', True) or option in ['owner', 'seed_mode']:
opts[option] = value
# Check for .magnet files containing multiple magnet links and
# create a new .magnet file for each of them.
for filename in os.listdir(watchdir["abspath"]):
for filename in os.listdir(watchdir['abspath']):
try:
filepath = os.path.join(watchdir["abspath"], filename)
filepath = os.path.join(watchdir['abspath'], filename)
except UnicodeDecodeError as ex:
log.error("Unable to auto add torrent due to improper filename encoding: %s", ex)
log.error('Unable to auto add torrent due to improper filename encoding: %s', ex)
continue
if os.path.isdir(filepath):
# Skip directories
continue
elif os.path.splitext(filename)[1] == ".magnet" and self.split_magnets(filepath):
elif os.path.splitext(filename)[1] == '.magnet' and self.split_magnets(filepath):
os.remove(filepath)
for filename in os.listdir(watchdir["abspath"]):
for filename in os.listdir(watchdir['abspath']):
try:
filepath = os.path.join(watchdir["abspath"], filename)
filepath = os.path.join(watchdir['abspath'], filename)
except UnicodeDecodeError as ex:
log.error("Unable to auto add torrent due to improper filename encoding: %s", ex)
log.error('Unable to auto add torrent due to improper filename encoding: %s', ex)
continue
if os.path.isdir(filepath):
# Skip directories
continue
else:
ext = os.path.splitext(filename)[1].lower()
if ext == ".torrent":
if ext == '.torrent':
magnet = False
elif ext == ".magnet":
elif ext == '.magnet':
magnet = True
else:
log.debug("File checked for auto-loading is invalid: %s", filename)
log.debug('File checked for auto-loading is invalid: %s', filename)
continue
try:
filedump = self.load_torrent(filepath, magnet)
@ -266,15 +266,15 @@ class Core(CorePluginBase):
# If the torrent is invalid, we keep track of it so that we
# can try again on the next pass. This is because some
# torrents may not be fully saved during the pass.
log.debug("Torrent is invalid: %s", ex)
log.debug('Torrent is invalid: %s', ex)
if filename in self.invalid_torrents:
self.invalid_torrents[filename] += 1
if self.invalid_torrents[filename] >= MAX_NUM_ATTEMPTS:
log.warning(
"Maximum attempts reached while trying to add the "
"torrent file with the path %s", filepath
'Maximum attempts reached while trying to add the '
'torrent file with the path %s', filepath
)
os.rename(filepath, filepath + ".invalid")
os.rename(filepath, filepath + '.invalid')
del self.invalid_torrents[filename]
else:
self.invalid_torrents[filename] = 1
@ -282,37 +282,37 @@ class Core(CorePluginBase):
# The torrent looks good, so lets add it to the session.
if magnet:
torrent_id = component.get("Core").add_torrent_magnet(filedump, opts)
torrent_id = component.get('Core').add_torrent_magnet(filedump, opts)
else:
torrent_id = component.get("Core").add_torrent_file(filename, filedump, opts)
torrent_id = component.get('Core').add_torrent_file(filename, filedump, opts)
# If the torrent added successfully, set the extra options.
if torrent_id:
if "Label" in component.get("CorePluginManager").get_enabled_plugins():
if watchdir.get("label_toggle", True) and watchdir.get("label"):
label = component.get("CorePlugin.Label")
if not watchdir["label"] in label.get_labels():
label.add(watchdir["label"])
label.set_torrent(torrent_id, watchdir["label"])
if watchdir.get("queue_to_top_toggle", True) and "queue_to_top" in watchdir:
if watchdir["queue_to_top"]:
component.get("TorrentManager").queue_top(torrent_id)
if 'Label' in component.get('CorePluginManager').get_enabled_plugins():
if watchdir.get('label_toggle', True) and watchdir.get('label'):
label = component.get('CorePlugin.Label')
if not watchdir['label'] in label.get_labels():
label.add(watchdir['label'])
label.set_torrent(torrent_id, watchdir['label'])
if watchdir.get('queue_to_top_toggle', True) and 'queue_to_top' in watchdir:
if watchdir['queue_to_top']:
component.get('TorrentManager').queue_top(torrent_id)
else:
component.get("TorrentManager").queue_bottom(torrent_id)
component.get('TorrentManager').queue_bottom(torrent_id)
else:
# torrent handle is invalid and so is the magnet link
if magnet:
log.debug("invalid magnet link")
os.rename(filepath, filepath + ".invalid")
log.debug('invalid magnet link')
os.rename(filepath, filepath + '.invalid')
continue
# Rename, copy or delete the torrent once added to deluge.
if watchdir.get("append_extension_toggle"):
if not watchdir.get("append_extension"):
watchdir["append_extension"] = ".added"
os.rename(filepath, filepath + watchdir["append_extension"])
elif watchdir.get("copy_torrent_toggle"):
copy_torrent_path = watchdir["copy_torrent"]
if watchdir.get('append_extension_toggle'):
if not watchdir.get('append_extension'):
watchdir['append_extension'] = '.added'
os.rename(filepath, filepath + watchdir['append_extension'])
elif watchdir.get('copy_torrent_toggle'):
copy_torrent_path = watchdir['copy_torrent']
copy_torrent_file = os.path.join(copy_torrent_path, filename)
log.debug("Moving added torrent file \"%s\" to \"%s\"",
os.path.basename(filepath), copy_torrent_path)
@ -325,7 +325,7 @@ class Core(CorePluginBase):
"""Disables any watch folders with un-handled exceptions."""
self.disable_watchdir(watchdir_id)
log.error("Disabling '%s', error during update: %s",
self.watchdirs[watchdir_id]["path"], failure)
self.watchdirs[watchdir_id]['path'], failure)
@export
def enable_watchdir(self, watchdir_id):
@ -337,10 +337,10 @@ class Core(CorePluginBase):
self.on_update_watchdir_error, w_id
)
# Update the config
if not self.watchdirs[w_id]["enabled"]:
self.watchdirs[w_id]["enabled"] = True
if not self.watchdirs[w_id]['enabled']:
self.watchdirs[w_id]['enabled'] = True
self.config.save()
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
component.get('EventManager').emit(AutoaddOptionsChangedEvent())
@export
def disable_watchdir(self, watchdir_id):
@ -351,10 +351,10 @@ class Core(CorePluginBase):
self.update_timers[w_id].stop()
del self.update_timers[w_id]
# Update the config
if self.watchdirs[w_id]["enabled"]:
self.watchdirs[w_id]["enabled"] = False
if self.watchdirs[w_id]['enabled']:
self.watchdirs[w_id]['enabled'] = False
self.config.save()
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
component.get('EventManager').emit(AutoaddOptionsChangedEvent())
@export
def set_config(self, config):
@ -363,7 +363,7 @@ class Core(CorePluginBase):
for key in config:
self.config[key] = config[key]
self.config.save()
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
component.get('EventManager').emit(AutoaddOptionsChangedEvent())
@export
def get_config(self):
@ -372,28 +372,28 @@ class Core(CorePluginBase):
@export
def get_watchdirs(self):
rpcserver = component.get("RPCServer")
rpcserver = component.get('RPCServer')
session_user = rpcserver.get_session_user()
session_auth_level = rpcserver.get_session_auth_level()
if session_auth_level == AUTH_LEVEL_ADMIN:
log.debug("Current logged in user %s is an ADMIN, send all "
"watchdirs", session_user)
log.debug('Current logged in user %s is an ADMIN, send all '
'watchdirs', session_user)
return self.watchdirs
watchdirs = {}
for watchdir_id, watchdir in self.watchdirs.iteritems():
if watchdir.get("owner", "localclient") == session_user:
if watchdir.get('owner', 'localclient') == session_user:
watchdirs[watchdir_id] = watchdir
log.debug("Current logged in user %s is not an ADMIN, send only "
"his watchdirs: %s", session_user, watchdirs.keys())
log.debug('Current logged in user %s is not an ADMIN, send only '
'his watchdirs: %s', session_user, watchdirs.keys())
return watchdirs
def _make_unicode(self, options):
opts = {}
for key in options:
if isinstance(options[key], str):
options[key] = unicode(options[key], "utf8")
options[key] = unicode(options[key], 'utf8')
opts[key] = options[key]
return opts
@ -403,58 +403,58 @@ class Core(CorePluginBase):
if options is None:
options = {}
options = self._make_unicode(options)
abswatchdir = os.path.abspath(options["path"])
check_input(os.path.isdir(abswatchdir), _("Path does not exist."))
abswatchdir = os.path.abspath(options['path'])
check_input(os.path.isdir(abswatchdir), _('Path does not exist.'))
check_input(
os.access(abswatchdir, os.R_OK | os.W_OK),
"You must have read and write access to watch folder."
'You must have read and write access to watch folder.'
)
if abswatchdir in [wd["abspath"] for wd in self.watchdirs.itervalues()]:
raise Exception("Path is already being watched.")
options.setdefault("enabled", False)
options["abspath"] = abswatchdir
watchdir_id = self.config["next_id"]
if abswatchdir in [wd['abspath'] for wd in self.watchdirs.itervalues()]:
raise Exception('Path is already being watched.')
options.setdefault('enabled', False)
options['abspath'] = abswatchdir
watchdir_id = self.config['next_id']
self.watchdirs[str(watchdir_id)] = options
if options.get("enabled"):
if options.get('enabled'):
self.enable_watchdir(watchdir_id)
self.config["next_id"] = watchdir_id + 1
self.config['next_id'] = watchdir_id + 1
self.config.save()
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
component.get('EventManager').emit(AutoaddOptionsChangedEvent())
return watchdir_id
@export
def remove(self, watchdir_id):
"""Remove a watch folder."""
watchdir_id = str(watchdir_id)
check_input(watchdir_id in self.watchdirs, "Unknown Watchdir: %s" % self.watchdirs)
if self.watchdirs[watchdir_id]["enabled"]:
check_input(watchdir_id in self.watchdirs, 'Unknown Watchdir: %s' % self.watchdirs)
if self.watchdirs[watchdir_id]['enabled']:
self.disable_watchdir(watchdir_id)
del self.watchdirs[watchdir_id]
self.config.save()
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
component.get('EventManager').emit(AutoaddOptionsChangedEvent())
def __migrate_config_1_to_2(self, config):
for watchdir_id in config["watchdirs"].iterkeys():
config["watchdirs"][watchdir_id]["owner"] = "localclient"
for watchdir_id in config['watchdirs'].iterkeys():
config['watchdirs'][watchdir_id]['owner'] = 'localclient'
return config
def __on_pre_torrent_removed(self, torrent_id):
try:
torrent = component.get("TorrentManager")[torrent_id]
torrent = component.get('TorrentManager')[torrent_id]
except KeyError:
log.warning("Unable to remove torrent file for torrent id %s. It"
"was already deleted from the TorrentManager",
log.warning('Unable to remove torrent file for torrent id %s. It'
'was already deleted from the TorrentManager',
torrent_id)
return
torrent_fname = torrent.filename
for watchdir in self.watchdirs.itervalues():
if not watchdir.get("copy_torrent_toggle", False):
if not watchdir.get('copy_torrent_toggle', False):
# This watchlist does copy torrents
continue
elif not watchdir.get("delete_copy_torrent_toggle", False):
elif not watchdir.get('delete_copy_torrent_toggle', False):
# This watchlist is not set to delete finished torrents
continue
copy_torrent_path = watchdir["copy_torrent"]
copy_torrent_path = watchdir['copy_torrent']
torrent_fname_path = os.path.join(copy_torrent_path, torrent_fname)
if os.path.isfile(torrent_fname_path):
try:

View File

@ -34,10 +34,10 @@ class IncompatibleOption(Exception):
class OptionsDialog(object):
spin_ids = ["max_download_speed", "max_upload_speed", "stop_ratio"]
spin_int_ids = ["max_upload_slots", "max_connections"]
chk_ids = ["stop_at_ratio", "remove_at_ratio", "move_completed",
"add_paused", "auto_managed", "queue_to_top"]
spin_ids = ['max_download_speed', 'max_upload_speed', 'stop_ratio']
spin_int_ids = ['max_upload_slots', 'max_connections']
chk_ids = ['stop_at_ratio', 'remove_at_ratio', 'move_completed',
'add_paused', 'auto_managed', 'queue_to_top']
def __init__(self):
self.accounts = gtk.ListStore(str)
@ -47,16 +47,16 @@ class OptionsDialog(object):
def show(self, options=None, watchdir_id=None):
if options is None:
options = {}
self.glade = gtk.glade.XML(get_resource("autoadd_options.glade"))
self.glade = gtk.glade.XML(get_resource('autoadd_options.glade'))
self.glade.signal_autoconnect({
"on_opts_add": self.on_add,
"on_opts_apply": self.on_apply,
"on_opts_cancel": self.on_cancel,
"on_options_dialog_close": self.on_cancel,
"on_toggle_toggled": self.on_toggle_toggled
'on_opts_add': self.on_add,
'on_opts_apply': self.on_apply,
'on_opts_cancel': self.on_cancel,
'on_options_dialog_close': self.on_cancel,
'on_toggle_toggled': self.on_toggle_toggled
})
self.dialog = self.glade.get_widget("options_dialog")
self.dialog.set_transient_for(component.get("Preferences").pref_dialog)
self.dialog = self.glade.get_widget('options_dialog')
self.dialog.set_transient_for(component.get('Preferences').pref_dialog)
if watchdir_id:
# We have an existing watchdir_id, we are editing
@ -108,10 +108,10 @@ class OptionsDialog(object):
for spin_id in self.spin_ids + self.spin_int_ids:
self.glade.get_widget(spin_id).set_value(options.get(spin_id, 0))
self.glade.get_widget(spin_id + "_toggle").set_active(options.get(spin_id + "_toggle", False))
self.glade.get_widget(spin_id + '_toggle').set_active(options.get(spin_id + '_toggle', False))
for chk_id in self.chk_ids:
self.glade.get_widget(chk_id).set_active(bool(options.get(chk_id, True)))
self.glade.get_widget(chk_id + "_toggle").set_active(options.get(chk_id + "_toggle", False))
self.glade.get_widget(chk_id + '_toggle').set_active(options.get(chk_id + '_toggle', False))
if not options.get('add_paused', True):
self.glade.get_widget('isnt_add_paused').set_active(True)
if not options.get('queue_to_top', True):
@ -121,59 +121,59 @@ class OptionsDialog(object):
for field in ['move_completed_path', 'path', 'download_location',
'copy_torrent']:
if client.is_localhost():
self.glade.get_widget(field + "_chooser").set_current_folder(
options.get(field, os.path.expanduser("~"))
self.glade.get_widget(field + '_chooser').set_current_folder(
options.get(field, os.path.expanduser('~'))
)
self.glade.get_widget(field + "_chooser").show()
self.glade.get_widget(field + "_entry").hide()
self.glade.get_widget(field + '_chooser').show()
self.glade.get_widget(field + '_entry').hide()
else:
self.glade.get_widget(field + "_entry").set_text(
options.get(field, "")
self.glade.get_widget(field + '_entry').set_text(
options.get(field, '')
)
self.glade.get_widget(field + "_entry").show()
self.glade.get_widget(field + "_chooser").hide()
self.glade.get_widget(field + '_entry').show()
self.glade.get_widget(field + '_chooser').hide()
self.set_sensitive()
def on_core_config(config):
if client.is_localhost():
self.glade.get_widget('download_location_chooser').set_current_folder(
options.get('download_location', config["download_location"])
options.get('download_location', config['download_location'])
)
if options.get('move_completed_toggle', config["move_completed"]):
if options.get('move_completed_toggle', config['move_completed']):
self.glade.get_widget('move_completed_toggle').set_active(True)
self.glade.get_widget('move_completed_path_chooser').set_current_folder(
options.get('move_completed_path', config["move_completed_path"])
options.get('move_completed_path', config['move_completed_path'])
)
if options.get('copy_torrent_toggle', config["copy_torrent_file"]):
if options.get('copy_torrent_toggle', config['copy_torrent_file']):
self.glade.get_widget('copy_torrent_toggle').set_active(True)
self.glade.get_widget('copy_torrent_chooser').set_current_folder(
options.get('copy_torrent', config["torrentfiles_location"])
options.get('copy_torrent', config['torrentfiles_location'])
)
else:
self.glade.get_widget('download_location_entry').set_text(
options.get('download_location', config["download_location"])
options.get('download_location', config['download_location'])
)
if options.get('move_completed_toggle', config["move_completed"]):
if options.get('move_completed_toggle', config['move_completed']):
self.glade.get_widget('move_completed_toggle').set_active(
options.get('move_completed_toggle', False)
)
self.glade.get_widget('move_completed_path_entry').set_text(
options.get('move_completed_path', config["move_completed_path"])
options.get('move_completed_path', config['move_completed_path'])
)
if options.get('copy_torrent_toggle', config["copy_torrent_file"]):
if options.get('copy_torrent_toggle', config['copy_torrent_file']):
self.glade.get_widget('copy_torrent_toggle').set_active(True)
self.glade.get_widget('copy_torrent_entry').set_text(
options.get('copy_torrent', config["torrentfiles_location"])
options.get('copy_torrent', config['torrentfiles_location'])
)
if options.get('delete_copy_torrent_toggle', config["del_copy_torrent_file"]):
if options.get('delete_copy_torrent_toggle', config['del_copy_torrent_file']):
self.glade.get_widget('delete_copy_torrent_toggle').set_active(True)
if not options:
client.core.get_config().addCallback(on_core_config)
def on_accounts(accounts, owner):
log.debug("Got Accounts")
log.debug('Got Accounts')
selected_iter = None
for account in accounts:
acc_iter = self.accounts.append()
@ -185,14 +185,14 @@ class OptionsDialog(object):
self.glade.get_widget('OwnerCombobox').set_active_iter(selected_iter)
def on_accounts_failure(failure):
log.debug("Failed to get accounts!!! %s", failure)
log.debug('Failed to get accounts!!! %s', failure)
acc_iter = self.accounts.append()
self.accounts.set_value(acc_iter, 0, client.get_auth_user())
self.glade.get_widget('OwnerCombobox').set_active(0)
self.glade.get_widget('OwnerCombobox').set_sensitive(False)
def on_labels(labels):
log.debug("Got Labels: %s", labels)
log.debug('Got Labels: %s', labels)
for label in labels:
self.labels.set_value(self.labels.append(), 0, label)
label_widget = self.glade.get_widget('label')
@ -228,10 +228,10 @@ class OptionsDialog(object):
'max_upload_slots', 'add_paused', 'auto_managed',
'stop_at_ratio', 'queue_to_top', 'copy_torrent']
for maintoggle in maintoggles:
self.on_toggle_toggled(self.glade.get_widget(maintoggle + "_toggle"))
self.on_toggle_toggled(self.glade.get_widget(maintoggle + '_toggle'))
def on_toggle_toggled(self, tb):
toggle = str(tb.name).replace("_toggle", "")
toggle = str(tb.name).replace('_toggle', '')
isactive = tb.get_active()
if toggle == 'download_location':
self.glade.get_widget('download_location_chooser').set_sensitive(isactive)
@ -279,10 +279,10 @@ class OptionsDialog(object):
str(self.watchdir_id), options
).addCallbacks(self.on_added, self.on_error_show)
except IncompatibleOption as ex:
dialogs.ErrorDialog(_("Incompatible Option"), str(ex), self.dialog).run()
dialogs.ErrorDialog(_('Incompatible Option'), str(ex), self.dialog).run()
def on_error_show(self, result):
d = dialogs.ErrorDialog(_("Error"), result.value.exception_msg, self.dialog)
d = dialogs.ErrorDialog(_('Error'), result.value.exception_msg, self.dialog)
result.cleanFailure()
d.run()
@ -294,7 +294,7 @@ class OptionsDialog(object):
options = self.generate_opts()
client.autoadd.add(options).addCallbacks(self.on_added, self.on_error_show)
except IncompatibleOption as ex:
dialogs.ErrorDialog(_("Incompatible Option"), str(ex), self.dialog).run()
dialogs.ErrorDialog(_('Incompatible Option'), str(ex), self.dialog).run()
def on_cancel(self, event=None):
self.dialog.destroy()
@ -332,13 +332,13 @@ class OptionsDialog(object):
for spin_id in self.spin_ids:
options[spin_id] = self.glade.get_widget(spin_id).get_value()
options[spin_id + "_toggle"] = self.glade.get_widget(spin_id + "_toggle").get_active()
options[spin_id + '_toggle'] = self.glade.get_widget(spin_id + '_toggle').get_active()
for spin_int_id in self.spin_int_ids:
options[spin_int_id] = self.glade.get_widget(spin_int_id).get_value_as_int()
options[spin_int_id + "_toggle"] = self.glade.get_widget(spin_int_id + "_toggle").get_active()
options[spin_int_id + '_toggle'] = self.glade.get_widget(spin_int_id + '_toggle').get_active()
for chk_id in self.chk_ids:
options[chk_id] = self.glade.get_widget(chk_id).get_active()
options[chk_id + "_toggle"] = self.glade.get_widget(chk_id + "_toggle").get_active()
options[chk_id + '_toggle'] = self.glade.get_widget(chk_id + '_toggle').get_active()
if options['copy_torrent_toggle'] and options['path'] == options['copy_torrent']:
raise IncompatibleOption(_("\"Watch Folder\" directory and \"Copy of .torrent"
@ -349,27 +349,27 @@ class OptionsDialog(object):
class GtkUI(GtkPluginBase):
def enable(self):
self.glade = gtk.glade.XML(get_resource("config.glade"))
self.glade = gtk.glade.XML(get_resource('config.glade'))
self.glade.signal_autoconnect({
"on_add_button_clicked": self.on_add_button_clicked,
"on_edit_button_clicked": self.on_edit_button_clicked,
"on_remove_button_clicked": self.on_remove_button_clicked
'on_add_button_clicked': self.on_add_button_clicked,
'on_edit_button_clicked': self.on_edit_button_clicked,
'on_remove_button_clicked': self.on_remove_button_clicked
})
self.opts_dialog = OptionsDialog()
component.get("PluginManager").register_hook(
"on_apply_prefs", self.on_apply_prefs
component.get('PluginManager').register_hook(
'on_apply_prefs', self.on_apply_prefs
)
component.get("PluginManager").register_hook(
"on_show_prefs", self.on_show_prefs
component.get('PluginManager').register_hook(
'on_show_prefs', self.on_show_prefs
)
client.register_event_handler(
"AutoaddOptionsChangedEvent", self.on_options_changed_event
'AutoaddOptionsChangedEvent', self.on_options_changed_event
)
self.watchdirs = {}
vbox = self.glade.get_widget("watchdirs_vbox")
vbox = self.glade.get_widget('watchdirs_vbox')
sw = gtk.ScrolledWindow()
sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
@ -379,24 +379,24 @@ class GtkUI(GtkPluginBase):
self.store = self.create_model()
self.treeView = gtk.TreeView(self.store)
self.treeView.connect("cursor-changed", self.on_listitem_activated)
self.treeView.connect("row-activated", self.on_edit_button_clicked)
self.treeView.connect('cursor-changed', self.on_listitem_activated)
self.treeView.connect('row-activated', self.on_edit_button_clicked)
self.treeView.set_rules_hint(True)
self.create_columns(self.treeView)
sw.add(self.treeView)
sw.show_all()
component.get("Preferences").add_page(
_("AutoAdd"), self.glade.get_widget("prefs_box")
component.get('Preferences').add_page(
_('AutoAdd'), self.glade.get_widget('prefs_box')
)
def disable(self):
component.get("Preferences").remove_page(_("AutoAdd"))
component.get("PluginManager").deregister_hook(
"on_apply_prefs", self.on_apply_prefs
component.get('Preferences').remove_page(_('AutoAdd'))
component.get('PluginManager').deregister_hook(
'on_apply_prefs', self.on_apply_prefs
)
component.get("PluginManager").deregister_hook(
"on_show_prefs", self.on_show_prefs
component.get('PluginManager').deregister_hook(
'on_show_prefs', self.on_show_prefs
)
def create_model(self):
@ -411,7 +411,7 @@ class GtkUI(GtkPluginBase):
def create_columns(self, treeview):
renderer_toggle = gtk.CellRendererToggle()
column = gtk.TreeViewColumn(
_("Active"), renderer_toggle, activatable=1, active=1
_('Active'), renderer_toggle, activatable=1, active=1
)
column.set_sort_column_id(1)
treeview.append_column(column)
@ -420,7 +420,7 @@ class GtkUI(GtkPluginBase):
treeview.set_tooltip_cell(tt, None, None, renderer_toggle)
renderertext = gtk.CellRendererText()
column = gtk.TreeViewColumn(_("Owner"), renderertext, text=2)
column = gtk.TreeViewColumn(_('Owner'), renderertext, text=2)
column.set_sort_column_id(2)
treeview.append_column(column)
tt2 = gtk.Tooltip()
@ -428,7 +428,7 @@ class GtkUI(GtkPluginBase):
treeview.set_has_tooltip(True)
renderertext = gtk.CellRendererText()
column = gtk.TreeViewColumn(_("Path"), renderertext, text=3)
column = gtk.TreeViewColumn(_('Path'), renderertext, text=3)
column.set_sort_column_id(3)
treeview.append_column(column)
tt2 = gtk.Tooltip()
@ -455,7 +455,7 @@ class GtkUI(GtkPluginBase):
tree, tree_id = self.treeView.get_selection().get_selected()
watchdir_id = str(self.store.get_value(tree_id, 0))
if watchdir_id:
if col and col.get_title() == _("Active"):
if col and col.get_title() == _('Active'):
if self.watchdirs[watchdir_id]['enabled']:
client.autoadd.disable_watchdir(watchdir_id)
else:
@ -473,7 +473,7 @@ class GtkUI(GtkPluginBase):
self.glade.get_widget('remove_button').set_sensitive(False)
def on_apply_prefs(self):
log.debug("applying prefs for AutoAdd")
log.debug('applying prefs for AutoAdd')
for watchdir_id, watchdir in self.watchdirs.iteritems():
client.autoadd.set_options(watchdir_id, watchdir)
@ -485,7 +485,7 @@ class GtkUI(GtkPluginBase):
def cb_get_config(self, watchdirs):
"""callback for on show_prefs"""
log.trace("Got whatchdirs from core: %s", watchdirs)
log.trace('Got whatchdirs from core: %s', watchdirs)
self.watchdirs = watchdirs or {}
self.store.clear()
for watchdir_id, watchdir in self.watchdirs.iteritems():

View File

@ -23,7 +23,7 @@ log = logging.getLogger(__name__)
class WebUI(WebPluginBase):
scripts = [get_resource("autoadd.js")]
scripts = [get_resource('autoadd.js')]
def enable(self):
pass

View File

@ -15,15 +15,15 @@
from setuptools import find_packages, setup
__plugin_name__ = "AutoAdd"
__author__ = "Chase Sterling, Pedro Algarvio"
__author_email__ = "chase.sterling@gmail.com, pedro@algarvio.me"
__version__ = "1.05"
__url__ = "http://dev.deluge-torrent.org/wiki/Plugins/AutoAdd"
__license__ = "GPLv3"
__description__ = "Monitors folders for .torrent files."
__plugin_name__ = 'AutoAdd'
__author__ = 'Chase Sterling, Pedro Algarvio'
__author_email__ = 'chase.sterling@gmail.com, pedro@algarvio.me'
__version__ = '1.05'
__url__ = 'http://dev.deluge-torrent.org/wiki/Plugins/AutoAdd'
__license__ = 'GPLv3'
__description__ = 'Monitors folders for .torrent files.'
__long_description__ = """"""
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ["template/*", "data/*"]}
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ['template/*', 'data/*']}
setup(
name=__plugin_name__,
@ -35,7 +35,7 @@ setup(
license=__license__,
long_description=__long_description__ if __long_description__ else __description__,
packages=find_packages(),
namespace_packages=["deluge", "deluge.plugins"],
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
entry_points="""

View File

@ -15,8 +15,8 @@ import pkg_resources
def get_resource(filename):
return pkg_resources.resource_filename("deluge.plugins.blocklist",
os.path.join("data", filename))
return pkg_resources.resource_filename('deluge.plugins.blocklist',
os.path.join('data', filename))
def raises_errors_as(error):
@ -56,7 +56,7 @@ def remove_zeros(ip):
000.000.000.003 -> 0.0.0.3
"""
return ".".join([part.lstrip("0").zfill(1) for part in ip.split(".")])
return '.'.join([part.lstrip('0').zfill(1) for part in ip.split('.')])
class BadIP(Exception):

View File

@ -39,16 +39,16 @@ from .readers import ReaderParseError
log = logging.getLogger(__name__)
DEFAULT_PREFS = {
"url": "",
"load_on_start": False,
"check_after_days": 4,
"list_compression": "",
"list_type": "",
"last_update": 0.0,
"list_size": 0,
"timeout": 180,
"try_times": 3,
"whitelisted": [],
'url': '',
'load_on_start': False,
'check_after_days': 4,
'list_compression': '',
'list_type': '',
'last_update': 0.0,
'list_size': 0,
'timeout': 180,
'try_times': 3,
'whitelisted': [],
}
# Constants
@ -70,26 +70,26 @@ class Core(CorePluginBase):
self.num_blocked = 0
self.file_progress = 0.0
self.core = component.get("Core")
self.config = deluge.configmanager.ConfigManager("blocklist.conf", DEFAULT_PREFS)
if "whitelisted" not in self.config:
self.config["whitelisted"] = []
self.core = component.get('Core')
self.config = deluge.configmanager.ConfigManager('blocklist.conf', DEFAULT_PREFS)
if 'whitelisted' not in self.config:
self.config['whitelisted'] = []
self.reader = create_reader(self.config["list_type"], self.config["list_compression"])
self.reader = create_reader(self.config['list_type'], self.config['list_compression'])
if not isinstance(self.config["last_update"], float):
self.config.config["last_update"] = 0.0
if not isinstance(self.config['last_update'], float):
self.config.config['last_update'] = 0.0
update_now = False
if self.config["load_on_start"]:
if self.config['load_on_start']:
self.pause_session()
if self.config["last_update"]:
last_update = datetime.fromtimestamp(self.config["last_update"])
check_period = timedelta(days=self.config["check_after_days"])
if not self.config["last_update"] or last_update + check_period < datetime.now():
if self.config['last_update']:
last_update = datetime.fromtimestamp(self.config['last_update'])
check_period = timedelta(days=self.config['check_after_days'])
if not self.config['last_update'] or last_update + check_period < datetime.now():
update_now = True
else:
d = self.import_list(deluge.configmanager.get_config_dir("blocklist.cache"))
d = self.import_list(deluge.configmanager.get_config_dir('blocklist.cache'))
d.addCallbacks(self.on_import_complete, self.on_import_error)
if self.need_to_resume_session:
d.addBoth(self.resume_session)
@ -97,16 +97,16 @@ class Core(CorePluginBase):
# This function is called every 'check_after_days' days, to download
# and import a new list if needed.
self.update_timer = LoopingCall(self.check_import)
if self.config["check_after_days"] > 0:
if self.config['check_after_days'] > 0:
self.update_timer.start(
self.config["check_after_days"] * 24 * 60 * 60, update_now
self.config['check_after_days'] * 24 * 60 * 60, update_now
)
def disable(self):
self.config.save()
log.debug("Reset IP filter")
log.debug('Reset IP filter')
self.core.session.get_ip_filter().add_rule(
"0.0.0.0", "255.255.255.255", ALLOW_RANGE
'0.0.0.0', '255.255.255.255', ALLOW_RANGE
)
log.debug('Blocklist: Plugin disabled')
@ -125,7 +125,7 @@ class Core(CorePluginBase):
Deferred: A Deferred which fires when the blocklist has been imported.
"""
if not self.config["url"]:
if not self.config['url']:
return
# Reset variables
@ -136,7 +136,7 @@ class Core(CorePluginBase):
self.up_to_date = False
if force:
self.reader = None
self.is_url = is_url(self.config["url"])
self.is_url = is_url(self.config['url'])
# Start callback chain
if self.is_url:
@ -144,7 +144,7 @@ class Core(CorePluginBase):
d.addCallbacks(self.on_download_complete, self.on_download_error)
d.addCallback(self.import_list)
else:
d = self.import_list(self.config["url"])
d = self.import_list(self.config['url'])
d.addCallbacks(self.on_import_complete, self.on_import_error)
if self.need_to_resume_session:
d.addBoth(self.resume_session)
@ -176,7 +176,7 @@ class Core(CorePluginBase):
update = set(config[key])
diff = saved.symmetric_difference(update)
if diff:
log.debug("Whitelist changed. Updating...")
log.debug('Whitelist changed. Updating...')
added = update.intersection(diff)
removed = saved.intersection(diff)
if added:
@ -187,10 +187,10 @@ class Core(CorePluginBase):
ip.address, ip.address, ALLOW_RANGE
)
saved.add(ip.address)
log.debug("Added %s to whitelisted", ip)
log.debug('Added %s to whitelisted', ip)
self.num_whited += 1
except BadIP as ex:
log.error("Bad IP: %s", ex)
log.error('Bad IP: %s', ex)
continue
if removed:
needs_blocklist_import = True
@ -198,37 +198,37 @@ class Core(CorePluginBase):
try:
ip = IP.parse(ip)
saved.remove(ip.address)
log.debug("Removed %s from whitelisted", ip)
log.debug('Removed %s from whitelisted', ip)
except BadIP as ex:
log.error("Bad IP: %s", ex)
log.error('Bad IP: %s', ex)
continue
self.config[key] = list(saved)
continue
elif key == "check_after_days":
elif key == 'check_after_days':
if self.config[key] != config[key]:
self.config[key] = config[key]
update_now = False
if self.config["last_update"]:
last_update = datetime.fromtimestamp(self.config["last_update"])
check_period = timedelta(days=self.config["check_after_days"])
if not self.config["last_update"] or last_update + check_period < datetime.now():
if self.config['last_update']:
last_update = datetime.fromtimestamp(self.config['last_update'])
check_period = timedelta(days=self.config['check_after_days'])
if not self.config['last_update'] or last_update + check_period < datetime.now():
update_now = True
if self.update_timer.running:
self.update_timer.stop()
if self.config["check_after_days"] > 0:
if self.config['check_after_days'] > 0:
self.update_timer.start(
self.config["check_after_days"] * 24 * 60 * 60, update_now
self.config['check_after_days'] * 24 * 60 * 60, update_now
)
continue
self.config[key] = config[key]
if needs_blocklist_import:
log.debug("IP addresses were removed from the whitelist. Since we "
log.debug('IP addresses were removed from the whitelist. Since we '
"don't know if they were blocked before. Re-import "
"current blocklist and re-add whitelisted.")
'current blocklist and re-add whitelisted.')
self.has_imported = False
d = self.import_list(deluge.configmanager.get_config_dir("blocklist.cache"))
d = self.import_list(deluge.configmanager.get_config_dir('blocklist.cache'))
d.addCallbacks(self.on_import_complete, self.on_import_error)
@export
@ -241,23 +241,23 @@ class Core(CorePluginBase):
"""
status = {}
if self.is_downloading:
status["state"] = "Downloading"
status['state'] = 'Downloading'
elif self.is_importing:
status["state"] = "Importing"
status['state'] = 'Importing'
else:
status["state"] = "Idle"
status['state'] = 'Idle'
status["up_to_date"] = self.up_to_date
status["num_whited"] = self.num_whited
status["num_blocked"] = self.num_blocked
status["file_progress"] = self.file_progress
status["file_url"] = self.config["url"]
status["file_size"] = self.config["list_size"]
status["file_date"] = self.config["last_update"]
status["file_type"] = self.config["list_type"]
status["whitelisted"] = self.config["whitelisted"]
if self.config["list_compression"]:
status["file_type"] += " (%s)" % self.config["list_compression"]
status['up_to_date'] = self.up_to_date
status['num_whited'] = self.num_whited
status['num_blocked'] = self.num_blocked
status['file_progress'] = self.file_progress
status['file_url'] = self.config['url']
status['file_size'] = self.config['list_size']
status['file_date'] = self.config['last_update']
status['file_type'] = self.config['list_type']
status['whitelisted'] = self.config['whitelisted']
if self.config['list_compression']:
status['file_type'] += ' (%s)' % self.config['list_compression']
return status
####
@ -272,9 +272,9 @@ class Core(CorePluginBase):
str: Path of blocklist.
"""
log.debug("Updating blocklist info: %s", blocklist)
self.config["last_update"] = time.time()
self.config["list_size"] = os.path.getsize(blocklist)
log.debug('Updating blocklist info: %s', blocklist)
self.config['last_update'] = time.time()
self.config['list_size'] = os.path.getsize(blocklist)
self.filename = blocklist
return blocklist
@ -299,20 +299,20 @@ class Core(CorePluginBase):
self.file_progress = fp
import socket
socket.setdefaulttimeout(self.config["timeout"])
socket.setdefaulttimeout(self.config['timeout'])
if not url:
url = self.config["url"]
url = self.config['url']
headers = {}
if self.config["last_update"] and not self.force_download:
headers['If-Modified-Since'] = formatdate(self.config["last_update"], usegmt=True)
if self.config['last_update'] and not self.force_download:
headers['If-Modified-Since'] = formatdate(self.config['last_update'], usegmt=True)
log.debug("Attempting to download blocklist %s", url)
log.debug("Sending headers: %s", headers)
log.debug('Attempting to download blocklist %s', url)
log.debug('Sending headers: %s', headers)
self.is_downloading = True
return download_file(
url, deluge.configmanager.get_config_dir("blocklist.download"),
url, deluge.configmanager.get_config_dir('blocklist.download'),
on_retrieve_data, headers
)
@ -326,7 +326,7 @@ class Core(CorePluginBase):
Deferred: a Deferred which fires when clean up is done.
"""
log.debug("Blocklist download complete: %s", blocklist)
log.debug('Blocklist download complete: %s', blocklist)
self.is_downloading = False
return threads.deferToThread(self.update_info, blocklist)
@ -345,21 +345,21 @@ class Core(CorePluginBase):
d = f
if f.check(error.PageRedirect):
# Handle redirect errors
location = urljoin(self.config["url"], error_msg.split(" to ")[1])
if "Moved Permanently" in error_msg:
log.debug("Setting blocklist url to %s", location)
self.config["url"] = location
location = urljoin(self.config['url'], error_msg.split(' to ')[1])
if 'Moved Permanently' in error_msg:
log.debug('Setting blocklist url to %s', location)
self.config['url'] = location
d = self.download_list(location)
d.addCallbacks(self.on_download_complete, self.on_download_error)
else:
if "Not Modified" in error_msg:
log.debug("Blocklist is up-to-date!")
if 'Not Modified' in error_msg:
log.debug('Blocklist is up-to-date!')
self.up_to_date = True
blocklist = deluge.configmanager.get_config_dir("blocklist.cache")
blocklist = deluge.configmanager.get_config_dir('blocklist.cache')
d = threads.deferToThread(self.update_info, blocklist)
else:
log.warning("Blocklist download failed: %s", error_msg)
if self.failed_attempts < self.config["try_times"]:
log.warning('Blocklist download failed: %s', error_msg)
if self.failed_attempts < self.config['try_times']:
log.debug("Let's try again")
self.failed_attempts += 1
d = self.download_list()
@ -376,7 +376,7 @@ class Core(CorePluginBase):
Deferred: A Deferred that fires when the blocklist has been imported.
"""
log.trace("on import_list")
log.trace('on import_list')
def on_read_ip_range(start, end):
"""Add ip range to blocklist"""
@ -388,19 +388,19 @@ class Core(CorePluginBase):
"""Add any whitelisted IP's and add the blocklist to session"""
# White listing happens last because the last rules added have
# priority
log.info("Added %d ranges to ipfilter as blocked", self.num_blocked)
for ip in self.config["whitelisted"]:
log.info('Added %d ranges to ipfilter as blocked', self.num_blocked)
for ip in self.config['whitelisted']:
ip = IP.parse(ip)
self.blocklist.add_rule(ip.address, ip.address, ALLOW_RANGE)
self.num_whited += 1
log.trace("Added %s to the ipfiler as white-listed", ip.address)
log.info("Added %d ranges to ipfilter as white-listed", self.num_whited)
log.trace('Added %s to the ipfiler as white-listed', ip.address)
log.info('Added %d ranges to ipfilter as white-listed', self.num_whited)
self.core.session.set_ip_filter(self.blocklist)
return result
# TODO: double check logic
if self.up_to_date and self.has_imported:
log.debug("Latest blocklist is already imported")
log.debug('Latest blocklist is already imported')
return defer.succeed(blocklist)
self.is_importing = True
@ -416,12 +416,12 @@ class Core(CorePluginBase):
self.auto_detected = True
def on_reader_failure(failure):
log.error("Failed to read!!!!!!")
log.error('Failed to read!!!!!!')
log.exception(failure)
log.debug("Importing using reader: %s", self.reader)
log.debug("Reader type: %s compression: %s", self.config["list_type"], self.config["list_compression"])
log.debug("Clearing current ip filtering")
log.debug('Importing using reader: %s', self.reader)
log.debug('Reader type: %s compression: %s', self.config['list_type'], self.config['list_compression'])
log.debug('Clearing current ip filtering')
# self.blocklist.add_rule("0.0.0.0", "255.255.255.255", ALLOW_RANGE)
d = threads.deferToThread(self.reader(blocklist).read, on_read_ip_range)
d.addCallback(on_finish_read).addErrback(on_reader_failure)
@ -438,18 +438,18 @@ class Core(CorePluginBase):
Deferred: A Deferred that fires when clean up is done.
"""
log.trace("on_import_list_complete")
log.trace('on_import_list_complete')
d = blocklist
self.is_importing = False
self.has_imported = True
log.debug("Blocklist import complete!")
cache = deluge.configmanager.get_config_dir("blocklist.cache")
log.debug('Blocklist import complete!')
cache = deluge.configmanager.get_config_dir('blocklist.cache')
if blocklist != cache:
if self.is_url:
log.debug("Moving %s to %s", blocklist, cache)
log.debug('Moving %s to %s', blocklist, cache)
d = threads.deferToThread(shutil.move, blocklist, cache)
else:
log.debug("Copying %s to %s", blocklist, cache)
log.debug('Copying %s to %s', blocklist, cache)
d = threads.deferToThread(shutil.copy, blocklist, cache)
return d
@ -463,21 +463,21 @@ class Core(CorePluginBase):
Deferred or Failure: A Deferred if recovery was possible else original Failure.
"""
log.trace("on_import_error: %s", f)
log.trace('on_import_error: %s', f)
d = f
self.is_importing = False
try_again = False
cache = deluge.configmanager.get_config_dir("blocklist.cache")
cache = deluge.configmanager.get_config_dir('blocklist.cache')
if f.check(ReaderParseError) and not self.auto_detected:
# Invalid / corrupt list, let's detect it
log.warning("Invalid / corrupt blocklist")
log.warning('Invalid / corrupt blocklist')
self.reader = None
blocklist = None
try_again = True
elif self.filename != cache and os.path.exists(cache):
# If we have a backup and we haven't already used it
log.warning("Error reading blocklist: %s", f.getErrorMessage())
log.warning('Error reading blocklist: %s', f.getErrorMessage())
blocklist = cache
try_again = True
@ -497,14 +497,14 @@ class Core(CorePluginBase):
UnknownFormatError: If the format cannot be detected.
"""
self.config["list_compression"] = detect_compression(blocklist)
self.config["list_type"] = detect_format(blocklist, self.config["list_compression"])
log.debug("Auto-detected type: %s compression: %s", self.config["list_type"], self.config["list_compression"])
if not self.config["list_type"]:
self.config["list_compression"] = ""
self.config['list_compression'] = detect_compression(blocklist)
self.config['list_type'] = detect_format(blocklist, self.config['list_compression'])
log.debug('Auto-detected type: %s compression: %s', self.config['list_type'], self.config['list_compression'])
if not self.config['list_type']:
self.config['list_compression'] = ''
raise UnknownFormatError
else:
self.reader = create_reader(self.config["list_type"], self.config["list_compression"])
self.reader = create_reader(self.config['list_type'], self.config['list_compression'])
def pause_session(self):
self.need_to_resume_session = not self.core.session.is_paused()

View File

@ -11,21 +11,21 @@ from .decompressers import BZipped2, GZipped, Zipped
from .readers import EmuleReader, PeerGuardianReader, SafePeerReader
COMPRESSION_TYPES = {
"PK": "Zip",
"\x1f\x8b": "GZip",
"BZ": "BZip2"
'PK': 'Zip',
'\x1f\x8b': 'GZip',
'BZ': 'BZip2'
}
DECOMPRESSERS = {
"Zip": Zipped,
"GZip": GZipped,
"BZip2": BZipped2
'Zip': Zipped,
'GZip': GZipped,
'BZip2': BZipped2
}
READERS = {
"Emule": EmuleReader,
"SafePeer": SafePeerReader,
"PeerGuardian": PeerGuardianReader
'Emule': EmuleReader,
'SafePeer': SafePeerReader,
'PeerGuardian': PeerGuardianReader
}
@ -34,13 +34,13 @@ class UnknownFormatError(Exception):
def detect_compression(filename):
with open(filename, "rb") as _file:
with open(filename, 'rb') as _file:
magic_number = _file.read(2)
return COMPRESSION_TYPES.get(magic_number, "")
return COMPRESSION_TYPES.get(magic_number, '')
def detect_format(filename, compression=""):
file_format = ""
def detect_format(filename, compression=''):
file_format = ''
for reader in READERS:
if create_reader(reader, compression)(filename).is_valid():
file_format = reader
@ -48,7 +48,7 @@ def detect_format(filename, compression=""):
return file_format
def create_reader(file_format, compression=""):
def create_reader(file_format, compression=''):
reader = READERS.get(file_format)
if reader and compression:
decompressor = DECOMPRESSERS.get(compression)

View File

@ -25,102 +25,102 @@ log = logging.getLogger(__name__)
class GtkUI(GtkPluginBase):
def enable(self):
log.debug("Blocklist GtkUI enable..")
self.plugin = component.get("PluginManager")
log.debug('Blocklist GtkUI enable..')
self.plugin = component.get('PluginManager')
self.load_preferences_page()
self.status_item = component.get("StatusBar").add_item(
image=common.get_resource("blocklist16.png"),
text="",
self.status_item = component.get('StatusBar').add_item(
image=common.get_resource('blocklist16.png'),
text='',
callback=self._on_status_item_clicked,
tooltip=_("Blocked IP Ranges /Whitelisted IP Ranges")
tooltip=_('Blocked IP Ranges /Whitelisted IP Ranges')
)
# Register some hooks
self.plugin.register_hook("on_apply_prefs", self._on_apply_prefs)
self.plugin.register_hook("on_show_prefs", self._on_show_prefs)
self.plugin.register_hook('on_apply_prefs', self._on_apply_prefs)
self.plugin.register_hook('on_show_prefs', self._on_show_prefs)
def disable(self):
log.debug("Blocklist GtkUI disable..")
log.debug('Blocklist GtkUI disable..')
# Remove the preferences page
self.plugin.remove_preferences_page(_("Blocklist"))
self.plugin.remove_preferences_page(_('Blocklist'))
# Remove status item
component.get("StatusBar").remove_item(self.status_item)
component.get('StatusBar').remove_item(self.status_item)
del self.status_item
# Deregister the hooks
self.plugin.deregister_hook("on_apply_prefs", self._on_apply_prefs)
self.plugin.deregister_hook("on_show_prefs", self._on_show_prefs)
self.plugin.deregister_hook('on_apply_prefs', self._on_apply_prefs)
self.plugin.deregister_hook('on_show_prefs', self._on_show_prefs)
del self.glade
def update(self):
def _on_get_status(status):
if status["state"] == "Downloading":
if status['state'] == 'Downloading':
self.table_info.hide()
self.glade.get_widget("button_check_download").set_sensitive(False)
self.glade.get_widget("button_force_download").set_sensitive(False)
self.glade.get_widget("image_up_to_date").hide()
self.glade.get_widget('button_check_download').set_sensitive(False)
self.glade.get_widget('button_force_download').set_sensitive(False)
self.glade.get_widget('image_up_to_date').hide()
self.status_item.set_text(
"Downloading %.2f%%" % (status["file_progress"] * 100))
self.progress_bar.set_text("Downloading %.2f%%" % (status["file_progress"] * 100))
self.progress_bar.set_fraction(status["file_progress"])
'Downloading %.2f%%' % (status['file_progress'] * 100))
self.progress_bar.set_text('Downloading %.2f%%' % (status['file_progress'] * 100))
self.progress_bar.set_fraction(status['file_progress'])
self.progress_bar.show()
elif status["state"] == "Importing":
elif status['state'] == 'Importing':
self.table_info.hide()
self.glade.get_widget("button_check_download").set_sensitive(False)
self.glade.get_widget("button_force_download").set_sensitive(False)
self.glade.get_widget("image_up_to_date").hide()
self.glade.get_widget('button_check_download').set_sensitive(False)
self.glade.get_widget('button_force_download').set_sensitive(False)
self.glade.get_widget('image_up_to_date').hide()
self.status_item.set_text(
"Importing " + str(status["num_blocked"]))
self.progress_bar.set_text("Importing %s" % (status["num_blocked"]))
'Importing ' + str(status['num_blocked']))
self.progress_bar.set_text('Importing %s' % (status['num_blocked']))
self.progress_bar.pulse()
self.progress_bar.show()
elif status["state"] == "Idle":
elif status['state'] == 'Idle':
self.progress_bar.hide()
self.glade.get_widget("button_check_download").set_sensitive(True)
self.glade.get_widget("button_force_download").set_sensitive(True)
if status["up_to_date"]:
self.glade.get_widget("image_up_to_date").show()
self.glade.get_widget('button_check_download').set_sensitive(True)
self.glade.get_widget('button_force_download').set_sensitive(True)
if status['up_to_date']:
self.glade.get_widget('image_up_to_date').show()
else:
self.glade.get_widget("image_up_to_date").hide()
self.glade.get_widget('image_up_to_date').hide()
self.table_info.show()
self.status_item.set_text("%(num_blocked)s/%(num_whited)s" % status)
self.status_item.set_text('%(num_blocked)s/%(num_whited)s' % status)
self.glade.get_widget("label_filesize").set_text(
deluge.common.fsize(status["file_size"]))
self.glade.get_widget("label_modified").set_text(
datetime.fromtimestamp(status["file_date"]).strftime("%c"))
self.glade.get_widget("label_type").set_text(status["file_type"])
self.glade.get_widget("label_url").set_text(
status["file_url"])
self.glade.get_widget('label_filesize').set_text(
deluge.common.fsize(status['file_size']))
self.glade.get_widget('label_modified').set_text(
datetime.fromtimestamp(status['file_date']).strftime('%c'))
self.glade.get_widget('label_type').set_text(status['file_type'])
self.glade.get_widget('label_url').set_text(
status['file_url'])
client.blocklist.get_status().addCallback(_on_get_status)
def _on_show_prefs(self):
def _on_get_config(config):
log.trace("Loaded config: %s", config)
self.glade.get_widget("entry_url").set_text(config["url"])
self.glade.get_widget("spin_check_days").set_value(config["check_after_days"])
self.glade.get_widget("chk_import_on_start").set_active(config["load_on_start"])
self.populate_whitelist(config["whitelisted"])
log.trace('Loaded config: %s', config)
self.glade.get_widget('entry_url').set_text(config['url'])
self.glade.get_widget('spin_check_days').set_value(config['check_after_days'])
self.glade.get_widget('chk_import_on_start').set_active(config['load_on_start'])
self.populate_whitelist(config['whitelisted'])
client.blocklist.get_config().addCallback(_on_get_config)
def _on_apply_prefs(self):
config = {}
config["url"] = self.glade.get_widget("entry_url").get_text().strip()
config["check_after_days"] = self.glade.get_widget("spin_check_days").get_value_as_int()
config["load_on_start"] = self.glade.get_widget("chk_import_on_start").get_active()
config["whitelisted"] = [ip[0] for ip in self.whitelist_model if ip[0] != 'IP HERE']
config['url'] = self.glade.get_widget('entry_url').get_text().strip()
config['check_after_days'] = self.glade.get_widget('spin_check_days').get_value_as_int()
config['load_on_start'] = self.glade.get_widget('chk_import_on_start').get_active()
config['whitelisted'] = [ip[0] for ip in self.whitelist_model if ip[0] != 'IP HERE']
client.blocklist.set_config(config)
def _on_button_check_download_clicked(self, widget):
@ -132,16 +132,16 @@ class GtkUI(GtkPluginBase):
client.blocklist.check_import(force=True)
def _on_status_item_clicked(self, widget, event):
component.get("Preferences").show(_("Blocklist"))
component.get('Preferences').show(_('Blocklist'))
def load_preferences_page(self):
"""Initializes the preferences page and adds it to the preferences dialog"""
# Load the preferences page
self.glade = gtk.glade.XML(common.get_resource("blocklist_pref.glade"))
self.glade = gtk.glade.XML(common.get_resource('blocklist_pref.glade'))
self.whitelist_frame = self.glade.get_widget("whitelist_frame")
self.progress_bar = self.glade.get_widget("progressbar")
self.table_info = self.glade.get_widget("table_info")
self.whitelist_frame = self.glade.get_widget('whitelist_frame')
self.progress_bar = self.glade.get_widget('progressbar')
self.table_info = self.glade.get_widget('table_info')
# Hide the progress bar initially
self.progress_bar.hide()
@ -151,8 +151,8 @@ class GtkUI(GtkPluginBase):
self.build_whitelist_model_treeview()
self.glade.signal_autoconnect({
"on_button_check_download_clicked": self._on_button_check_download_clicked,
"on_button_force_download_clicked": self._on_button_force_download_clicked,
'on_button_check_download_clicked': self._on_button_check_download_clicked,
'on_button_force_download_clicked': self._on_button_force_download_clicked,
'on_whitelist_add_clicked': (self.on_add_button_clicked,
self.whitelist_treeview),
'on_whitelist_remove_clicked': (self.on_delete_button_clicked,
@ -160,32 +160,32 @@ class GtkUI(GtkPluginBase):
})
# Set button icons
self.glade.get_widget("image_download").set_from_file(
common.get_resource("blocklist_download24.png"))
self.glade.get_widget('image_download').set_from_file(
common.get_resource('blocklist_download24.png'))
self.glade.get_widget("image_import").set_from_file(
common.get_resource("blocklist_import24.png"))
self.glade.get_widget('image_import').set_from_file(
common.get_resource('blocklist_import24.png'))
# Update the preferences page with config values from the core
self._on_show_prefs()
# Add the page to the preferences dialog
self.plugin.add_preferences_page(
_("Blocklist"),
self.glade.get_widget("blocklist_prefs_box"))
_('Blocklist'),
self.glade.get_widget('blocklist_prefs_box'))
def build_whitelist_model_treeview(self):
self.whitelist_treeview = self.glade.get_widget("whitelist_treeview")
self.whitelist_treeview = self.glade.get_widget('whitelist_treeview')
treeview_selection = self.whitelist_treeview.get_selection()
treeview_selection.connect(
"changed", self.on_whitelist_treeview_selection_changed
'changed', self.on_whitelist_treeview_selection_changed
)
self.whitelist_model = gtk.ListStore(str, bool)
renderer = gtk.CellRendererText()
renderer.connect("edited", self.on_cell_edited, self.whitelist_model)
renderer.set_data("ip", 0)
renderer.connect('edited', self.on_cell_edited, self.whitelist_model)
renderer.set_data('ip', 0)
column = gtk.TreeViewColumn("IPs", renderer, text=0, editable=1)
column = gtk.TreeViewColumn('IPs', renderer, text=0, editable=1)
column.set_expand(True)
self.whitelist_treeview.append_column(column)
self.whitelist_treeview.set_model(self.whitelist_model)
@ -199,21 +199,21 @@ class GtkUI(GtkPluginBase):
except common.BadIP as ex:
model.remove(model.get_iter_from_string(path_string))
from deluge.ui.gtkui import dialogs
d = dialogs.ErrorDialog(_("Bad IP address"), ex.message)
d = dialogs.ErrorDialog(_('Bad IP address'), ex.message)
d.run()
def on_whitelist_treeview_selection_changed(self, selection):
model, selected_connection_iter = selection.get_selected()
if selected_connection_iter:
self.glade.get_widget("whitelist_delete").set_property('sensitive',
self.glade.get_widget('whitelist_delete').set_property('sensitive',
True)
else:
self.glade.get_widget("whitelist_delete").set_property('sensitive',
self.glade.get_widget('whitelist_delete').set_property('sensitive',
False)
def on_add_button_clicked(self, widget, treeview):
model = treeview.get_model()
model.set(model.append(), 0, "IP HERE", 1, True)
model.set(model.append(), 0, 'IP HERE', 1, True)
def on_delete_button_clicked(self, widget, treeview):
selection = treeview.get_selection()

View File

@ -24,35 +24,35 @@ class PGException(Exception):
class PGReader(object):
def __init__(self, filename):
log.debug("PGReader loading: %s", filename)
log.debug('PGReader loading: %s', filename)
try:
with gzip.open(filename, "rb") as _file:
with gzip.open(filename, 'rb') as _file:
self.fd = _file
except IOError:
log.debug("Blocklist: PGReader: Incorrect file type or list is corrupt")
log.debug('Blocklist: PGReader: Incorrect file type or list is corrupt')
# 4 bytes, should be 0xffffffff
buf = self.fd.read(4)
hdr = unpack("l", buf)[0]
hdr = unpack('l', buf)[0]
if hdr != -1:
raise PGException(_("Invalid leader") + " %d" % hdr)
raise PGException(_('Invalid leader') + ' %d' % hdr)
magic = self.fd.read(3)
if magic != "P2B":
raise PGException(_("Invalid magic code"))
if magic != 'P2B':
raise PGException(_('Invalid magic code'))
buf = self.fd.read(1)
ver = ord(buf)
if ver != 1 and ver != 2:
raise PGException(_("Invalid version") + " %d" % ver)
raise PGException(_('Invalid version') + ' %d' % ver)
def __next__(self):
# Skip over the string
buf = -1
while buf != 0:
buf = self.fd.read(1)
if buf == "": # EOF
if buf == '': # EOF
return False
buf = ord(buf)

View File

@ -39,7 +39,7 @@ class BaseReader(object):
try:
callback(IP.parse(start), IP.parse(end))
except BadIP as ex:
log.error("Failed to parse IP: %s", ex)
log.error('Failed to parse IP: %s', ex)
return self.file
def is_ignored(self, line):
@ -55,8 +55,8 @@ class BaseReader(object):
if not self.is_ignored(line):
try:
(start, end) = self.parse(line)
if not re.match(r"^(\d{1,3}\.){4}$", start + ".") or \
not re.match(r"^(\d{1,3}\.){4}$", end + "."):
if not re.match(r'^(\d{1,3}\.){4}$', start + '.') or \
not re.match(r'^(\d{1,3}\.){4}$', end + '.'):
valid = False
except Exception:
valid = False
@ -77,13 +77,13 @@ class BaseReader(object):
class EmuleReader(BaseReader):
"""Blocklist reader for emule style blocklists"""
def parse(self, line):
return line.strip().split(" , ")[0].split(" - ")
return line.strip().split(' , ')[0].split(' - ')
class SafePeerReader(BaseReader):
"""Blocklist reader for SafePeer style blocklists"""
def parse(self, line):
return line.strip().split(":")[-1].split("-")
return line.strip().split(':')[-1].split('-')
class PeerGuardianReader(SafePeerReader):

View File

@ -16,14 +16,14 @@ from .common import get_resource
log = logging.getLogger(__name__)
FORMAT_LIST = [
('gzmule', _("Emule IP list (GZip)")),
('spzip', _("SafePeer Text (Zipped)")),
('pgtext', _("PeerGuardian Text (Uncompressed)")),
('p2bgz', _("PeerGuardian P2B (GZip)"))
('gzmule', _('Emule IP list (GZip)')),
('spzip', _('SafePeer Text (Zipped)')),
('pgtext', _('PeerGuardian Text (Uncompressed)')),
('p2bgz', _('PeerGuardian P2B (GZip)'))
]
class WebUI(WebPluginBase):
scripts = [get_resource("blocklist.js")]
scripts = [get_resource('blocklist.js')]
debug_scripts = scripts

View File

@ -9,15 +9,15 @@
from setuptools import find_packages, setup
__plugin_name__ = "Blocklist"
__author__ = "John Garland"
__author_email__ = "johnnybg+deluge@gmail.com"
__version__ = "1.3"
__url__ = "http://deluge-torrent.org"
__license__ = "GPLv3"
__description__ = "Download and import IP blocklists"
__plugin_name__ = 'Blocklist'
__author__ = 'John Garland'
__author_email__ = 'johnnybg+deluge@gmail.com'
__version__ = '1.3'
__url__ = 'http://deluge-torrent.org'
__license__ = 'GPLv3'
__description__ = 'Download and import IP blocklists'
__long_description__ = __description__
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ["data/*"]}
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ['data/*']}
setup(
name=__plugin_name__,
@ -30,7 +30,7 @@ setup(
zip_safe=False,
long_description=__long_description__,
packages=find_packages(),
namespace_packages=["deluge", "deluge.plugins"],
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
entry_points="""
[deluge.plugin.core]

View File

@ -13,5 +13,5 @@ import pkg_resources
def get_resource(filename):
return pkg_resources.resource_filename("deluge.plugins.execute",
os.path.join("data", filename))
return pkg_resources.resource_filename('deluge.plugins.execute',
os.path.join('data', filename))

View File

@ -24,7 +24,7 @@ from deluge.plugins.pluginbase import CorePluginBase
log = logging.getLogger(__name__)
DEFAULT_CONFIG = {
"commands": []
'commands': []
}
EXECUTE_ID = 0
@ -32,9 +32,9 @@ EXECUTE_EVENT = 1
EXECUTE_COMMAND = 2
EVENT_MAP = {
"complete": "TorrentFinishedEvent",
"added": "TorrentAddedEvent",
"removed": "TorrentRemovedEvent"
'complete': 'TorrentFinishedEvent',
'added': 'TorrentAddedEvent',
'removed': 'TorrentRemovedEvent'
}
@ -56,13 +56,13 @@ class ExecuteCommandRemovedEvent(DelugeEvent):
class Core(CorePluginBase):
def enable(self):
self.config = ConfigManager("execute.conf", DEFAULT_CONFIG)
event_manager = component.get("EventManager")
self.config = ConfigManager('execute.conf', DEFAULT_CONFIG)
event_manager = component.get('EventManager')
self.registered_events = {}
self.preremoved_cache = {}
# Go through the commands list and register event handlers
for command in self.config["commands"]:
for command in self.config['commands']:
event = command[EXECUTE_EVENT]
if event in self.registered_events:
continue
@ -73,47 +73,47 @@ class Core(CorePluginBase):
return event_handler
event_handler = create_event_handler(event)
event_manager.register_event_handler(EVENT_MAP[event], event_handler)
if event == "removed":
event_manager.register_event_handler("PreTorrentRemovedEvent", self.on_preremoved)
if event == 'removed':
event_manager.register_event_handler('PreTorrentRemovedEvent', self.on_preremoved)
self.registered_events[event] = event_handler
log.debug("Execute core plugin enabled!")
log.debug('Execute core plugin enabled!')
def on_preremoved(self, torrent_id):
# Get and store the torrent info before it is removed
torrent = component.get("TorrentManager").torrents[torrent_id]
info = torrent.get_status(["name", "download_location"])
self.preremoved_cache[torrent_id] = [utf8_encoded(torrent_id), utf8_encoded(info["name"]),
utf8_encoded(info["download_location"])]
torrent = component.get('TorrentManager').torrents[torrent_id]
info = torrent.get_status(['name', 'download_location'])
self.preremoved_cache[torrent_id] = [utf8_encoded(torrent_id), utf8_encoded(info['name']),
utf8_encoded(info['download_location'])]
def execute_commands(self, torrent_id, event, *arg):
if event == "added" and arg[0]:
if event == 'added' and arg[0]:
# No futher action as from_state (arg[0]) is True
return
elif event == "removed":
elif event == 'removed':
torrent_id, torrent_name, download_location = self.preremoved_cache.pop(torrent_id)
else:
torrent = component.get("TorrentManager").torrents[torrent_id]
info = torrent.get_status(["name", "download_location"])
torrent = component.get('TorrentManager').torrents[torrent_id]
info = torrent.get_status(['name', 'download_location'])
# Grab the torrent name and download location
# getProcessOutputAndValue requires args to be str
torrent_id = utf8_encoded(torrent_id)
torrent_name = utf8_encoded(info["name"])
download_location = utf8_encoded(info["download_location"])
torrent_name = utf8_encoded(info['name'])
download_location = utf8_encoded(info['download_location'])
log.debug("Running commands for %s", event)
log.debug('Running commands for %s', event)
def log_error(result, command):
(stdout, stderr, exit_code) = result
if exit_code:
log.warn("Command '%s' failed with exit code %d", command, exit_code)
if stdout:
log.warn("stdout: %s", stdout)
log.warn('stdout: %s', stdout)
if stderr:
log.warn("stderr: %s", stderr)
log.warn('stderr: %s', stderr)
# Go through and execute all the commands
for command in self.config["commands"]:
for command in self.config['commands']:
if command[EXECUTE_EVENT] == event:
command = os.path.expandvars(command[EXECUTE_COMMAND])
command = os.path.expanduser(command)
@ -121,47 +121,47 @@ class Core(CorePluginBase):
cmd_args = [torrent_id, torrent_name, download_location]
if windows_check():
# Escape ampersand on windows (see #2784)
cmd_args = [cmd_arg.replace("&", "^^^&") for cmd_arg in cmd_args]
cmd_args = [cmd_arg.replace('&', '^^^&') for cmd_arg in cmd_args]
if os.path.isfile(command) and os.access(command, os.X_OK):
log.debug("Running %s with args: %s", command, cmd_args)
log.debug('Running %s with args: %s', command, cmd_args)
d = getProcessOutputAndValue(command, cmd_args, env=os.environ)
d.addCallback(log_error, command)
else:
log.error("Execute script not found or not executable")
log.error('Execute script not found or not executable')
def disable(self):
self.config.save()
event_manager = component.get("EventManager")
event_manager = component.get('EventManager')
for event, handler in self.registered_events.iteritems():
event_manager.deregister_event_handler(event, handler)
log.debug("Execute core plugin disabled!")
log.debug('Execute core plugin disabled!')
# Exported RPC methods #
@export
def add_command(self, event, command):
command_id = hashlib.sha1(str(time.time())).hexdigest()
self.config["commands"].append((command_id, event, command))
self.config['commands'].append((command_id, event, command))
self.config.save()
component.get("EventManager").emit(ExecuteCommandAddedEvent(command_id, event, command))
component.get('EventManager').emit(ExecuteCommandAddedEvent(command_id, event, command))
@export
def get_commands(self):
return self.config["commands"]
return self.config['commands']
@export
def remove_command(self, command_id):
for command in self.config["commands"]:
for command in self.config['commands']:
if command[EXECUTE_ID] == command_id:
self.config["commands"].remove(command)
component.get("EventManager").emit(ExecuteCommandRemovedEvent(command_id))
self.config['commands'].remove(command)
component.get('EventManager').emit(ExecuteCommandRemovedEvent(command_id))
break
self.config.save()
@export
def save_command(self, command_id, event, cmd):
for i, command in enumerate(self.config["commands"]):
for i, command in enumerate(self.config['commands']):
if command[EXECUTE_ID] == command_id:
self.config["commands"][i] = (command_id, event, cmd)
self.config['commands'][i] = (command_id, event, cmd)
break
self.config.save()

View File

@ -27,12 +27,12 @@ EXECUTE_EVENT = 1
EXECUTE_COMMAND = 2
EVENT_MAP = {
"complete": _("Torrent Complete"),
"added": _("Torrent Added"),
"removed": _("Torrent Removed")
'complete': _('Torrent Complete'),
'added': _('Torrent Added'),
'removed': _('Torrent Removed')
}
EVENTS = ["complete", "added", "removed"]
EVENTS = ['complete', 'added', 'removed']
class ExecutePreferences(object):
@ -40,13 +40,13 @@ class ExecutePreferences(object):
self.plugin = plugin
def load(self):
log.debug("Adding Execute Preferences page")
self.glade = gtk.glade.XML(common.get_resource("execute_prefs.glade"))
log.debug('Adding Execute Preferences page')
self.glade = gtk.glade.XML(common.get_resource('execute_prefs.glade'))
self.glade.signal_autoconnect({
"on_add_button_clicked": self.on_add_button_clicked
'on_add_button_clicked': self.on_add_button_clicked
})
events = self.glade.get_widget("event_combobox")
events = self.glade.get_widget('event_combobox')
store = gtk.ListStore(str, str)
for event in EVENTS:
@ -55,31 +55,31 @@ class ExecutePreferences(object):
events.set_model(store)
events.set_active(0)
self.plugin.add_preferences_page(_("Execute"), self.glade.get_widget("execute_box"))
self.plugin.register_hook("on_show_prefs", self.load_commands)
self.plugin.register_hook("on_apply_prefs", self.on_apply_prefs)
self.plugin.add_preferences_page(_('Execute'), self.glade.get_widget('execute_box'))
self.plugin.register_hook('on_show_prefs', self.load_commands)
self.plugin.register_hook('on_apply_prefs', self.on_apply_prefs)
self.load_commands()
client.register_event_handler("ExecuteCommandAddedEvent", self.on_command_added_event)
client.register_event_handler("ExecuteCommandRemovedEvent", self.on_command_removed_event)
client.register_event_handler('ExecuteCommandAddedEvent', self.on_command_added_event)
client.register_event_handler('ExecuteCommandRemovedEvent', self.on_command_removed_event)
def unload(self):
self.plugin.remove_preferences_page(_("Execute"))
self.plugin.deregister_hook("on_apply_prefs", self.on_apply_prefs)
self.plugin.deregister_hook("on_show_prefs", self.load_commands)
self.plugin.remove_preferences_page(_('Execute'))
self.plugin.deregister_hook('on_apply_prefs', self.on_apply_prefs)
self.plugin.deregister_hook('on_show_prefs', self.load_commands)
def add_command(self, command_id, event, command):
log.debug("Adding command `%s`", command_id)
vbox = self.glade.get_widget("commands_vbox")
log.debug('Adding command `%s`', command_id)
vbox = self.glade.get_widget('commands_vbox')
hbox = gtk.HBox(False, 5)
hbox.set_name(command_id + "_" + event)
hbox.set_name(command_id + '_' + event)
label = gtk.Label(EVENT_MAP[event])
entry = gtk.Entry()
entry.set_text(command)
button = gtk.Button()
button.set_name("remove_%s" % command_id)
button.connect("clicked", self.on_remove_button_clicked)
button.set_name('remove_%s' % command_id)
button.connect('clicked', self.on_remove_button_clicked)
img = gtk.Image()
img.set_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_BUTTON)
@ -92,15 +92,15 @@ class ExecutePreferences(object):
vbox.pack_start(hbox)
def remove_command(self, command_id):
vbox = self.glade.get_widget("commands_vbox")
vbox = self.glade.get_widget('commands_vbox')
children = vbox.get_children()
for child in children:
if child.get_name().split("_")[0] == command_id:
if child.get_name().split('_')[0] == command_id:
vbox.remove(child)
break
def clear_commands(self):
vbox = self.glade.get_widget("commands_vbox")
vbox = self.glade.get_widget('commands_vbox')
children = vbox.get_children()
for child in children:
vbox.remove(child)
@ -108,7 +108,7 @@ class ExecutePreferences(object):
def load_commands(self):
def on_get_commands(commands):
self.clear_commands()
log.debug("on_get_commands: %s", commands)
log.debug('on_get_commands: %s', commands)
for command in commands:
command_id, event, command = command
self.add_command(command_id, event, command)
@ -116,38 +116,38 @@ class ExecutePreferences(object):
client.execute.get_commands().addCallback(on_get_commands)
def on_add_button_clicked(self, *args):
command = self.glade.get_widget("command_entry").get_text()
events = self.glade.get_widget("event_combobox")
command = self.glade.get_widget('command_entry').get_text()
events = self.glade.get_widget('event_combobox')
event = events.get_model()[events.get_active()][1]
client.execute.add_command(event, command)
def on_remove_button_clicked(self, widget, *args):
command_id = widget.get_name().replace("remove_", "")
command_id = widget.get_name().replace('remove_', '')
client.execute.remove_command(command_id)
def on_apply_prefs(self):
vbox = self.glade.get_widget("commands_vbox")
vbox = self.glade.get_widget('commands_vbox')
children = vbox.get_children()
for child in children:
command_id, event = child.get_name().split("_")
command_id, event = child.get_name().split('_')
for widget in child.get_children():
if isinstance(widget, gtk.Entry):
command = widget.get_text()
client.execute.save_command(command_id, event, command)
def on_command_added_event(self, command_id, event, command):
log.debug("Adding command %s: %s", event, command)
log.debug('Adding command %s: %s', event, command)
self.add_command(command_id, event, command)
def on_command_removed_event(self, command_id):
log.debug("Removing command %s", command_id)
log.debug('Removing command %s', command_id)
self.remove_command(command_id)
class GtkUI(GtkPluginBase):
def enable(self):
self.plugin = component.get("PluginManager")
self.plugin = component.get('PluginManager')
self.preferences = ExecutePreferences(self.plugin)
self.preferences.load()

View File

@ -18,5 +18,5 @@ log = logging.getLogger(__name__)
class WebUI(WebPluginBase):
scripts = [get_resource("execute.js")]
scripts = [get_resource('execute.js')]
debug_scripts = scripts

View File

@ -9,15 +9,15 @@
from setuptools import find_packages, setup
__plugin_name__ = "Execute"
__author__ = "Damien Churchill"
__author_email__ = "damoxc@gmail.com"
__version__ = "1.2"
__url__ = "http://deluge-torrent.org"
__license__ = "GPLv3"
__description__ = "Plugin to execute a command upon an event"
__plugin_name__ = 'Execute'
__author__ = 'Damien Churchill'
__author_email__ = 'damoxc@gmail.com'
__version__ = '1.2'
__url__ = 'http://deluge-torrent.org'
__license__ = 'GPLv3'
__description__ = 'Plugin to execute a command upon an event'
__long_description__ = __description__
__pkg_data__ = {"deluge.plugins." + __plugin_name__.lower(): ["data/*"]}
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ['data/*']}
setup(
name=__plugin_name__,
@ -30,7 +30,7 @@ setup(
long_description=__long_description__,
packages=find_packages(),
namespace_packages=["deluge", "deluge.plugins"],
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
entry_points="""

View File

@ -13,5 +13,5 @@ import pkg_resources
def get_resource(filename):
return pkg_resources.resource_filename("deluge.plugins.extractor",
os.path.join("data", filename))
return pkg_resources.resource_filename('deluge.plugins.extractor',
os.path.join('data', filename))

View File

@ -27,8 +27,8 @@ from deluge.plugins.pluginbase import CorePluginBase
log = logging.getLogger(__name__)
DEFAULT_PREFS = {
"extract_path": "",
"use_name_folder": True
'extract_path': '',
'use_name_folder': True
}
if windows_check():
@ -40,15 +40,15 @@ if windows_check():
import _winreg
try:
hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, "Software\\7-Zip")
hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, 'Software\\7-Zip')
except WindowsError: # pylint: disable=undefined-variable
pass
else:
win_7z_path = os.path.join(_winreg.QueryValueEx(hkey, "Path")[0], "7z.exe")
win_7z_path = os.path.join(_winreg.QueryValueEx(hkey, 'Path')[0], '7z.exe')
_winreg.CloseKey(hkey)
win_7z_exes.insert(1, win_7z_path)
switch_7z = "x -y"
switch_7z = 'x -y'
# Future suport:
# 7-zip cannot extract tar.* with single command.
# ".tar.gz", ".tgz",
@ -56,15 +56,15 @@ if windows_check():
# ".tar.lzma", ".tlz",
# ".tar.xz", ".txz",
exts_7z = [
".rar", ".zip", ".tar",
".7z", ".xz", ".lzma",
'.rar', '.zip', '.tar',
'.7z', '.xz', '.lzma',
]
for win_7z_exe in win_7z_exes:
if which(win_7z_exe):
EXTRACT_COMMANDS = dict.fromkeys(exts_7z, [win_7z_exe, switch_7z])
break
else:
required_cmds = ["unrar", "unzip", "tar", "unxz", "unlzma", "7zr", "bunzip2"]
required_cmds = ['unrar', 'unzip', 'tar', 'unxz', 'unlzma', '7zr', 'bunzip2']
# Possible future suport:
# gunzip: gz (cmd will delete original archive)
# the following do not extract to dest dir
@ -73,36 +73,36 @@ else:
# ".bz2": ["bzip2", "-d --keep"],
EXTRACT_COMMANDS = {
".rar": ["unrar", "x -o+ -y"],
".tar": ["tar", "-xf"],
".zip": ["unzip", ""],
".tar.gz": ["tar", "-xzf"], ".tgz": ["tar", "-xzf"],
".tar.bz2": ["tar", "-xjf"], ".tbz": ["tar", "-xjf"],
".tar.lzma": ["tar", "--lzma -xf"], ".tlz": ["tar", "--lzma -xf"],
".tar.xz": ["tar", "--xz -xf"], ".txz": ["tar", "--xz -xf"],
".7z": ["7zr", "x"],
'.rar': ['unrar', 'x -o+ -y'],
'.tar': ['tar', '-xf'],
'.zip': ['unzip', ''],
'.tar.gz': ['tar', '-xzf'], '.tgz': ['tar', '-xzf'],
'.tar.bz2': ['tar', '-xjf'], '.tbz': ['tar', '-xjf'],
'.tar.lzma': ['tar', '--lzma -xf'], '.tlz': ['tar', '--lzma -xf'],
'.tar.xz': ['tar', '--xz -xf'], '.txz': ['tar', '--xz -xf'],
'.7z': ['7zr', 'x'],
}
# Test command exists and if not, remove.
for command in required_cmds:
if not which(command):
for k, v in EXTRACT_COMMANDS.items():
if command in v[0]:
log.warning("%s not found, disabling support for %s", command, k)
log.warning('%s not found, disabling support for %s', command, k)
del EXTRACT_COMMANDS[k]
if not EXTRACT_COMMANDS:
raise Exception("No archive extracting programs found, plugin will be disabled")
raise Exception('No archive extracting programs found, plugin will be disabled')
class Core(CorePluginBase):
def enable(self):
self.config = deluge.configmanager.ConfigManager("extractor.conf", DEFAULT_PREFS)
if not self.config["extract_path"]:
self.config["extract_path"] = deluge.configmanager.ConfigManager("core.conf")["download_location"]
component.get("EventManager").register_event_handler("TorrentFinishedEvent", self._on_torrent_finished)
self.config = deluge.configmanager.ConfigManager('extractor.conf', DEFAULT_PREFS)
if not self.config['extract_path']:
self.config['extract_path'] = deluge.configmanager.ConfigManager('core.conf')['download_location']
component.get('EventManager').register_event_handler('TorrentFinishedEvent', self._on_torrent_finished)
def disable(self):
component.get("EventManager").deregister_event_handler("TorrentFinishedEvent", self._on_torrent_finished)
component.get('EventManager').deregister_event_handler('TorrentFinishedEvent', self._on_torrent_finished)
def update(self):
pass
@ -111,57 +111,57 @@ class Core(CorePluginBase):
"""
This is called when a torrent finishes and checks if any files to extract.
"""
tid = component.get("TorrentManager").torrents[torrent_id]
tid_status = tid.get_status(["download_location", "name"])
tid = component.get('TorrentManager').torrents[torrent_id]
tid_status = tid.get_status(['download_location', 'name'])
files = tid.get_files()
for f in files:
file_root, file_ext = os.path.splitext(f["path"])
file_root, file_ext = os.path.splitext(f['path'])
file_ext_sec = os.path.splitext(file_root)[1]
if file_ext_sec and file_ext_sec + file_ext in EXTRACT_COMMANDS:
file_ext = file_ext_sec + file_ext
elif file_ext not in EXTRACT_COMMANDS or file_ext_sec == '.tar':
log.debug("Can't extract file with unknown file type: %s", f["path"])
log.debug("Can't extract file with unknown file type: %s", f['path'])
continue
elif file_ext == ".rar" and "part" in file_ext_sec:
part_num = file_ext_sec.split("part")[1]
elif file_ext == '.rar' and 'part' in file_ext_sec:
part_num = file_ext_sec.split('part')[1]
if part_num.isdigit() and int(part_num) != 1:
log.debug("Skipping remaining multi-part rar files: %s", f["path"])
log.debug('Skipping remaining multi-part rar files: %s', f['path'])
continue
cmd = EXTRACT_COMMANDS[file_ext]
fpath = os.path.join(tid_status["download_location"], os.path.normpath(f["path"]))
dest = os.path.normpath(self.config["extract_path"])
if self.config["use_name_folder"]:
dest = os.path.join(dest, tid_status["name"])
fpath = os.path.join(tid_status['download_location'], os.path.normpath(f['path']))
dest = os.path.normpath(self.config['extract_path'])
if self.config['use_name_folder']:
dest = os.path.join(dest, tid_status['name'])
try:
os.makedirs(dest)
except OSError as ex:
if not (ex.errno == errno.EEXIST and os.path.isdir(dest)):
log.error("Error creating destination folder: %s", ex)
log.error('Error creating destination folder: %s', ex)
break
def on_extract(result, torrent_id, fpath):
# Check command exit code.
if not result[2]:
log.info("Extract successful: %s (%s)", fpath, torrent_id)
log.info('Extract successful: %s (%s)', fpath, torrent_id)
else:
log.error("Extract failed: %s (%s) %s", fpath, torrent_id, result[1])
log.error('Extract failed: %s (%s) %s', fpath, torrent_id, result[1])
# Run the command and add callback.
log.debug("Extracting %s from %s with %s %s to %s", fpath, torrent_id, cmd[0], cmd[1], dest)
log.debug('Extracting %s from %s with %s %s to %s', fpath, torrent_id, cmd[0], cmd[1], dest)
d = getProcessOutputAndValue(cmd[0], cmd[1].split() + [str(fpath)], os.environ, str(dest))
d.addCallback(on_extract, torrent_id, fpath)
@export
def set_config(self, config):
"sets the config dictionary"
'sets the config dictionary'
for key in config.keys():
self.config[key] = config[key]
self.config.save()
@export
def get_config(self):
"returns the config dictionary"
'returns the config dictionary'
return self.config.config

View File

@ -27,47 +27,47 @@ log = logging.getLogger(__name__)
class GtkUI(GtkPluginBase):
def enable(self):
self.glade = gtk.glade.XML(get_resource("extractor_prefs.glade"))
self.glade = gtk.glade.XML(get_resource('extractor_prefs.glade'))
component.get("Preferences").add_page(_("Extractor"), self.glade.get_widget("extractor_prefs_box"))
component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs)
component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs)
component.get('Preferences').add_page(_('Extractor'), self.glade.get_widget('extractor_prefs_box'))
component.get('PluginManager').register_hook('on_apply_prefs', self.on_apply_prefs)
component.get('PluginManager').register_hook('on_show_prefs', self.on_show_prefs)
self.on_show_prefs()
def disable(self):
component.get("Preferences").remove_page(_("Extractor"))
component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs)
component.get("PluginManager").deregister_hook("on_show_prefs", self.on_show_prefs)
component.get('Preferences').remove_page(_('Extractor'))
component.get('PluginManager').deregister_hook('on_apply_prefs', self.on_apply_prefs)
component.get('PluginManager').deregister_hook('on_show_prefs', self.on_show_prefs)
del self.glade
def on_apply_prefs(self):
log.debug("applying prefs for Extractor")
log.debug('applying prefs for Extractor')
if client.is_localhost():
path = self.glade.get_widget("folderchooser_path").get_filename()
path = self.glade.get_widget('folderchooser_path').get_filename()
else:
path = self.glade.get_widget("entry_path").get_text()
path = self.glade.get_widget('entry_path').get_text()
config = {
"extract_path": path,
"use_name_folder": self.glade.get_widget("chk_use_name").get_active()
'extract_path': path,
'use_name_folder': self.glade.get_widget('chk_use_name').get_active()
}
client.extractor.set_config(config)
def on_show_prefs(self):
if client.is_localhost():
self.glade.get_widget("folderchooser_path").show()
self.glade.get_widget("entry_path").hide()
self.glade.get_widget('folderchooser_path').show()
self.glade.get_widget('entry_path').hide()
else:
self.glade.get_widget("folderchooser_path").hide()
self.glade.get_widget("entry_path").show()
self.glade.get_widget('folderchooser_path').hide()
self.glade.get_widget('entry_path').show()
def on_get_config(config):
if client.is_localhost():
self.glade.get_widget("folderchooser_path").set_current_folder(config["extract_path"])
self.glade.get_widget('folderchooser_path').set_current_folder(config['extract_path'])
else:
self.glade.get_widget("entry_path").set_text(config["extract_path"])
self.glade.get_widget('entry_path').set_text(config['extract_path'])
self.glade.get_widget("chk_use_name").set_active(config["use_name_folder"])
self.glade.get_widget('chk_use_name').set_active(config['use_name_folder'])
client.extractor.get_config().addCallback(on_get_config)

View File

@ -22,5 +22,5 @@ log = logging.getLogger(__name__)
class WebUI(WebPluginBase):
scripts = [get_resource("extractor.js")]
scripts = [get_resource('extractor.js')]
debug_scripts = scripts

View File

@ -13,13 +13,13 @@
from setuptools import find_packages, setup
__plugin_name__ = "Extractor"
__author__ = "Andrew Resch"
__author_email__ = "andrewresch@gmail.com"
__version__ = "0.6"
__url__ = "http://deluge-torrent.org"
__license__ = "GPLv3"
__description__ = "Extract files upon torrent completion"
__plugin_name__ = 'Extractor'
__author__ = 'Andrew Resch'
__author_email__ = 'andrewresch@gmail.com'
__version__ = '0.6'
__url__ = 'http://deluge-torrent.org'
__license__ = 'GPLv3'
__description__ = 'Extract files upon torrent completion'
__long_description__ = """
Extract files upon torrent completion
@ -30,7 +30,7 @@ Windows support: .rar, .zip, .tar, .7z, .xz, .lzma
Note: Will not extract with 'Move Completed' enabled
"""
__pkg_data__ = {"deluge.plugins." + __plugin_name__.lower(): ["template/*", "data/*"]}
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ['template/*', 'data/*']}
setup(
name=__plugin_name__,
@ -43,7 +43,7 @@ setup(
long_description=__long_description__ if __long_description__ else __description__,
packages=find_packages(),
namespace_packages=["deluge", "deluge.plugins"],
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
entry_points="""

View File

@ -26,40 +26,40 @@ from deluge.plugins.pluginbase import CorePluginBase
log = logging.getLogger(__name__)
RE_VALID = re.compile(r"[a-z0-9_\-\.]*\Z")
RE_VALID = re.compile(r'[a-z0-9_\-\.]*\Z')
KNOWN_STATES = ['Downloading', 'Seeding', 'Paused', 'Checking', 'Queued', 'Error']
STATE = "state"
TRACKER = "tracker"
KEYWORD = "keyword"
LABEL = "label"
STATE = 'state'
TRACKER = 'tracker'
KEYWORD = 'keyword'
LABEL = 'label'
CONFIG_DEFAULTS = {
"torrent_labels": {}, # torrent_id:label_id
"labels": {}, # label_id:{name:value}
'torrent_labels': {}, # torrent_id:label_id
'labels': {}, # label_id:{name:value}
}
CORE_OPTIONS = ["auto_add_trackers"]
CORE_OPTIONS = ['auto_add_trackers']
OPTIONS_DEFAULTS = {
"apply_max": False,
"max_download_speed": -1,
"max_upload_speed": -1,
"max_connections": -1,
"max_upload_slots": -1,
"prioritize_first_last": False,
"apply_queue": False,
"is_auto_managed": False,
"stop_at_ratio": False,
"stop_ratio": 2.0,
"remove_at_ratio": False,
"apply_move_completed": False,
"move_completed": False,
"move_completed_path": "",
"auto_add": False,
"auto_add_trackers": []
'apply_max': False,
'max_download_speed': -1,
'max_upload_speed': -1,
'max_connections': -1,
'max_upload_slots': -1,
'prioritize_first_last': False,
'apply_queue': False,
'is_auto_managed': False,
'stop_at_ratio': False,
'stop_ratio': 2.0,
'remove_at_ratio': False,
'apply_move_completed': False,
'move_completed': False,
'move_completed_path': '',
'auto_add': False,
'auto_add_trackers': []
}
NO_LABEL = "No Label"
NO_LABEL = 'No Label'
def check_input(cond, message):
@ -73,35 +73,35 @@ class Core(CorePluginBase):
self.torrent_labels = {torrent_id:label_id}
"""
def enable(self):
log.info("*** Start Label plugin ***")
self.plugin = component.get("CorePluginManager")
self.plugin.register_status_field("label", self._status_get_label)
log.info('*** Start Label plugin ***')
self.plugin = component.get('CorePluginManager')
self.plugin.register_status_field('label', self._status_get_label)
# __init__
core = component.get("Core")
self.config = ConfigManager("label.conf", defaults=CONFIG_DEFAULTS)
self.core_cfg = ConfigManager("core.conf")
core = component.get('Core')
self.config = ConfigManager('label.conf', defaults=CONFIG_DEFAULTS)
self.core_cfg = ConfigManager('core.conf')
# reduce typing, assigning some values to self...
self.torrents = core.torrentmanager.torrents
self.labels = self.config["labels"]
self.torrent_labels = self.config["torrent_labels"]
self.labels = self.config['labels']
self.torrent_labels = self.config['torrent_labels']
self.clean_initial_config()
component.get("EventManager").register_event_handler("TorrentAddedEvent", self.post_torrent_add)
component.get("EventManager").register_event_handler("TorrentRemovedEvent", self.post_torrent_remove)
component.get('EventManager').register_event_handler('TorrentAddedEvent', self.post_torrent_add)
component.get('EventManager').register_event_handler('TorrentRemovedEvent', self.post_torrent_remove)
# register tree:
component.get("FilterManager").register_tree_field("label", self.init_filter_dict)
component.get('FilterManager').register_tree_field('label', self.init_filter_dict)
log.debug("Label plugin enabled..")
log.debug('Label plugin enabled..')
def disable(self):
self.plugin.deregister_status_field("label")
component.get("FilterManager").deregister_tree_field("label")
component.get("EventManager").deregister_event_handler("TorrentAddedEvent", self.post_torrent_add)
component.get("EventManager").deregister_event_handler("TorrentRemovedEvent", self.post_torrent_remove)
self.plugin.deregister_status_field('label')
component.get('FilterManager').deregister_tree_field('label')
component.get('EventManager').deregister_event_handler('TorrentAddedEvent', self.post_torrent_add)
component.get('EventManager').deregister_event_handler('TorrentRemovedEvent', self.post_torrent_remove)
def update(self):
pass
@ -115,17 +115,17 @@ class Core(CorePluginBase):
def post_torrent_add(self, torrent_id, from_state):
if from_state:
return
log.debug("post_torrent_add")
log.debug('post_torrent_add')
torrent = self.torrents[torrent_id]
for label_id, options in self.labels.iteritems():
if options["auto_add"]:
if options['auto_add']:
if self._has_auto_match(torrent, options):
self.set_torrent(torrent_id, label_id)
return
def post_torrent_remove(self, torrent_id):
log.debug("post_torrent_remove")
log.debug('post_torrent_remove')
if torrent_id in self.torrent_labels:
del self.torrent_labels[torrent_id]
@ -134,7 +134,7 @@ class Core(CorePluginBase):
"""remove invalid data from config-file"""
for torrent_id, label_id in list(self.torrent_labels.iteritems()):
if (label_id not in self.labels) or (torrent_id not in self.torrents):
log.debug("label: rm %s:%s", torrent_id, label_id)
log.debug('label: rm %s:%s', torrent_id, label_id)
del self.torrent_labels[torrent_id]
def clean_initial_config(self):
@ -168,9 +168,9 @@ class Core(CorePluginBase):
see label_set_options for more options.
"""
label_id = label_id.lower()
check_input(RE_VALID.match(label_id), _("Invalid label, valid characters:[a-z0-9_-]"))
check_input(label_id, _("Empty Label"))
check_input(not (label_id in self.labels), _("Label already exists"))
check_input(RE_VALID.match(label_id), _('Invalid label, valid characters:[a-z0-9_-]'))
check_input(label_id, _('Empty Label'))
check_input(not (label_id in self.labels), _('Label already exists'))
self.labels[label_id] = dict(OPTIONS_DEFAULTS)
self.config.save()
@ -178,7 +178,7 @@ class Core(CorePluginBase):
@export
def remove(self, label_id):
"""remove a label"""
check_input(label_id in self.labels, _("Unknown Label"))
check_input(label_id in self.labels, _('Unknown Label'))
del self.labels[label_id]
self.clean_config()
self.config.save()
@ -187,27 +187,27 @@ class Core(CorePluginBase):
options = self.labels[label_id]
torrent = self.torrents[torrent_id]
if not options["move_completed_path"]:
options["move_completed_path"] = "" # no None.
if not options['move_completed_path']:
options['move_completed_path'] = '' # no None.
if options["apply_max"]:
torrent.set_max_download_speed(options["max_download_speed"])
torrent.set_max_upload_speed(options["max_upload_speed"])
torrent.set_max_connections(options["max_connections"])
torrent.set_max_upload_slots(options["max_upload_slots"])
torrent.set_prioritize_first_last_pieces(options["prioritize_first_last"])
if options['apply_max']:
torrent.set_max_download_speed(options['max_download_speed'])
torrent.set_max_upload_speed(options['max_upload_speed'])
torrent.set_max_connections(options['max_connections'])
torrent.set_max_upload_slots(options['max_upload_slots'])
torrent.set_prioritize_first_last_pieces(options['prioritize_first_last'])
if options["apply_queue"]:
if options['apply_queue']:
torrent.set_auto_managed(options['is_auto_managed'])
torrent.set_stop_at_ratio(options['stop_at_ratio'])
torrent.set_stop_ratio(options['stop_ratio'])
torrent.set_remove_at_ratio(options['remove_at_ratio'])
if options["apply_move_completed"]:
if options['apply_move_completed']:
torrent.set_options(
{
"move_completed": options["move_completed"],
"move_completed_path": options["move_completed_path"]
'move_completed': options['move_completed'],
'move_completed_path': options['move_completed_path']
}
)
@ -215,32 +215,32 @@ class Core(CorePluginBase):
options = self.labels[label_id]
torrent = self.torrents[torrent_id]
if options["apply_max"]:
torrent.set_max_download_speed(self.core_cfg.config["max_download_speed_per_torrent"])
torrent.set_max_upload_speed(self.core_cfg.config["max_upload_speed_per_torrent"])
torrent.set_max_connections(self.core_cfg.config["max_connections_per_torrent"])
torrent.set_max_upload_slots(self.core_cfg.config["max_upload_slots_per_torrent"])
torrent.set_prioritize_first_last_pieces(self.core_cfg.config["prioritize_first_last_pieces"])
if options['apply_max']:
torrent.set_max_download_speed(self.core_cfg.config['max_download_speed_per_torrent'])
torrent.set_max_upload_speed(self.core_cfg.config['max_upload_speed_per_torrent'])
torrent.set_max_connections(self.core_cfg.config['max_connections_per_torrent'])
torrent.set_max_upload_slots(self.core_cfg.config['max_upload_slots_per_torrent'])
torrent.set_prioritize_first_last_pieces(self.core_cfg.config['prioritize_first_last_pieces'])
if options["apply_queue"]:
if options['apply_queue']:
torrent.set_auto_managed(self.core_cfg.config['auto_managed'])
torrent.set_stop_at_ratio(self.core_cfg.config['stop_seed_at_ratio'])
torrent.set_stop_ratio(self.core_cfg.config['stop_seed_ratio'])
torrent.set_remove_at_ratio(self.core_cfg.config['remove_seed_at_ratio'])
if options["apply_move_completed"]:
if options['apply_move_completed']:
torrent.set_options(
{
"move_completed": self.core_cfg.config["move_completed"],
"move_completed_path": self.core_cfg.config["move_completed_path"]
'move_completed': self.core_cfg.config['move_completed'],
'move_completed_path': self.core_cfg.config['move_completed_path']
}
)
def _has_auto_match(self, torrent, label_options):
"""match for auto_add fields"""
for tracker_match in label_options["auto_add_trackers"]:
for tracker_match in label_options['auto_add_trackers']:
for tracker in torrent.trackers:
if tracker_match in tracker["url"]:
if tracker_match in tracker['url']:
return True
return False
@ -258,10 +258,10 @@ class Core(CorePluginBase):
"move_completed_to":string() or None
}
"""
check_input(label_id in self.labels, _("Unknown Label"))
check_input(label_id in self.labels, _('Unknown Label'))
for key in options_dict.keys():
if key not in OPTIONS_DEFAULTS:
raise Exception("label: Invalid options_dict key:%s" % key)
raise Exception('label: Invalid options_dict key:%s' % key)
self.labels[label_id].update(options_dict)
@ -272,7 +272,7 @@ class Core(CorePluginBase):
# auto add
options = self.labels[label_id]
if options["auto_add"]:
if options['auto_add']:
for torrent_id, torrent in self.torrents.iteritems():
if self._has_auto_match(torrent, options):
self.set_torrent(torrent_id, label_id)
@ -293,8 +293,8 @@ class Core(CorePluginBase):
if label_id == NO_LABEL:
label_id = None
check_input((not label_id) or (label_id in self.labels), _("Unknown Label"))
check_input(torrent_id in self.torrents, _("Unknown Torrent"))
check_input((not label_id) or (label_id in self.labels), _('Unknown Label'))
check_input(torrent_id in self.torrents, _('Unknown Torrent'))
if torrent_id in self.torrent_labels:
self._unset_torrent_options(torrent_id, self.torrent_labels[torrent_id])
@ -322,4 +322,4 @@ class Core(CorePluginBase):
self.config.save()
def _status_get_label(self, torrent_id):
return self.torrent_labels.get(torrent_id) or ""
return self.torrent_labels.get(torrent_id) or ''

View File

@ -16,7 +16,7 @@ from . import label_config, sidebar_menu, submenu
log = logging.getLogger(__name__)
NO_LABEL = "No Label"
NO_LABEL = 'No Label'
def cell_data_label(column, cell, model, row, data):
@ -29,8 +29,8 @@ class GtkUI(GtkPluginBase):
self.label_menu.on_show()
def enable(self):
self.plugin = component.get("PluginManager")
self.torrentmenu = component.get("MenuBar").torrentmenu
self.plugin = component.get('PluginManager')
self.torrentmenu = component.get('MenuBar').torrentmenu
self.label_menu = None
self.labelcfg = None
self.sidebar_menu = None
@ -44,7 +44,7 @@ class GtkUI(GtkPluginBase):
self.sidebar_menu.unload()
del self.sidebar_menu
component.get("TorrentView").remove_column(_("Label"))
component.get('TorrentView').remove_column(_('Label'))
def load_interface(self):
# sidebar
@ -54,7 +54,7 @@ class GtkUI(GtkPluginBase):
# self.sidebar.load()
# menu:
log.debug("add items to torrentview-popup menu.")
log.debug('add items to torrentview-popup menu.')
self.label_menu = submenu.LabelMenu()
self.torrentmenu.append(self.label_menu)
self.label_menu.show_all()
@ -70,6 +70,6 @@ class GtkUI(GtkPluginBase):
log.debug('Finished loading Label plugin')
def load_columns(self):
log.debug("add columns")
log.debug('add columns')
component.get("TorrentView").add_text_column(_("Label"), status_field=["label"])
component.get('TorrentView').add_text_column(_('Label'), status_field=['label'])

View File

@ -29,29 +29,29 @@ class LabelConfig(object):
def load(self):
log.debug('Adding Label Preferences page')
self.glade = gtk.glade.XML(self.get_resource("label_pref.glade"))
self.glade = gtk.glade.XML(self.get_resource('label_pref.glade'))
self.plugin.add_preferences_page(_("Label"), self.glade.get_widget("label_prefs_box"))
self.plugin.register_hook("on_show_prefs", self.load_settings)
self.plugin.register_hook("on_apply_prefs", self.on_apply_prefs)
self.plugin.add_preferences_page(_('Label'), self.glade.get_widget('label_prefs_box'))
self.plugin.register_hook('on_show_prefs', self.load_settings)
self.plugin.register_hook('on_apply_prefs', self.on_apply_prefs)
self.load_settings()
def unload(self):
self.plugin.remove_preferences_page(_("Label"))
self.plugin.deregister_hook("on_apply_prefs", self.on_apply_prefs)
self.plugin.deregister_hook("on_show_prefs", self.load_settings)
self.plugin.remove_preferences_page(_('Label'))
self.plugin.deregister_hook('on_apply_prefs', self.on_apply_prefs)
self.plugin.deregister_hook('on_show_prefs', self.load_settings)
def get_resource(self, filename):
return pkg_resources.resource_filename(
"deluge.plugins.label", os.path.join("data", filename)
'deluge.plugins.label', os.path.join('data', filename)
)
def load_settings(self, widget=None, data=None):
client.label.get_config().addCallback(self.cb_global_options)
def cb_global_options(self, options):
log.debug("options=%s", options)
log.debug('options=%s', options)
# for id in self.chk_ids:
# self.glade.get_widget(id).set_active(bool(options[id]))

View File

@ -18,7 +18,7 @@ from deluge.ui.client import client
log = logging.getLogger(__name__)
NO_LABEL = "No Label"
NO_LABEL = 'No Label'
# helpers:
@ -26,7 +26,7 @@ def get_resource(filename):
import pkg_resources
import os
return pkg_resources.resource_filename(
"deluge.plugins.label", os.path.join("data", filename)
'deluge.plugins.label', os.path.join('data', filename)
)
@ -34,7 +34,7 @@ def get_resource(filename):
class LabelSidebarMenu(object):
def __init__(self):
self.treeview = component.get("FilterTreeView")
self.treeview = component.get('FilterTreeView')
self.menu = self.treeview.menu
self.items = []
@ -42,27 +42,27 @@ class LabelSidebarMenu(object):
sep = gtk.SeparatorMenuItem()
self.items.append(sep)
self.menu.prepend(sep)
self._add_item("options", _("Label _Options"), gtk.STOCK_PREFERENCES)
self._add_item("remove", _("_Remove Label"), gtk.STOCK_REMOVE)
self._add_item("add", _("_Add Label"), gtk.STOCK_ADD)
self._add_item('options', _('Label _Options'), gtk.STOCK_PREFERENCES)
self._add_item('remove', _('_Remove Label'), gtk.STOCK_REMOVE)
self._add_item('add', _('_Add Label'), gtk.STOCK_ADD)
self.menu.show_all()
# dialogs:
self.add_dialog = AddDialog()
self.options_dialog = OptionsDialog()
# hooks:
self.menu.connect("show", self.on_show, None)
self.menu.connect('show', self.on_show, None)
def _add_item(self, item_id, label, stock):
"""I hate glade.
id is automatically-added as self.item_<id>
"""
func = getattr(self, "on_%s" % item_id)
func = getattr(self, 'on_%s' % item_id)
item = gtk.ImageMenuItem(stock)
item.get_children()[0].set_label(label)
item.connect("activate", func)
item.connect('activate', func)
self.menu.prepend(item)
setattr(self, "item_%s" % item_id, item)
setattr(self, 'item_%s' % item_id, item)
self.items.append(item)
return item
@ -76,17 +76,17 @@ class LabelSidebarMenu(object):
self.options_dialog.show(self.treeview.value)
def on_show(self, widget=None, data=None):
"No Label:disable options/del"
log.debug("label-sidebar-popup:on-show")
'No Label:disable options/del'
log.debug('label-sidebar-popup:on-show')
cat = self.treeview.cat
label = self.treeview.value
if cat == "label" or (cat == "cat" and label == "label"):
if cat == 'label' or (cat == 'cat' and label == 'label'):
# is a label : show menu-items
for item in self.items:
item.show()
# default items
sensitive = ((label not in (NO_LABEL, None, "", "All")) and (cat != "cat"))
sensitive = ((label not in (NO_LABEL, None, '', 'All')) and (cat != 'cat'))
for item in self.items:
item.set_sensitive(sensitive)
@ -98,11 +98,11 @@ class LabelSidebarMenu(object):
item.hide()
def unload(self):
log.debug("disable01")
log.debug('disable01')
for item in list(self.items):
item.hide()
item.destroy()
log.debug("disable02")
log.debug('disable02')
self.items = []
@ -112,18 +112,18 @@ class AddDialog(object):
pass
def show(self):
self.glade = gtk.glade.XML(get_resource("label_options.glade"))
self.dialog = self.glade.get_widget("dlg_label_add")
self.dialog.set_transient_for(component.get("MainWindow").window)
self.glade = gtk.glade.XML(get_resource('label_options.glade'))
self.dialog = self.glade.get_widget('dlg_label_add')
self.dialog.set_transient_for(component.get('MainWindow').window)
self.glade.signal_autoconnect({
"on_add_ok": self.on_ok,
"on_add_cancel": self.on_cancel,
'on_add_ok': self.on_ok,
'on_add_cancel': self.on_cancel,
})
self.dialog.run()
def on_ok(self, event=None):
value = self.glade.get_widget("txt_add").get_text()
value = self.glade.get_widget('txt_add').get_text()
client.label.add(value)
self.dialog.destroy()
@ -132,19 +132,19 @@ class AddDialog(object):
class OptionsDialog(object):
spin_ids = ["max_download_speed", "max_upload_speed", "stop_ratio"]
spin_int_ids = ["max_upload_slots", "max_connections"]
chk_ids = ["apply_max", "apply_queue", "stop_at_ratio", "apply_queue", "remove_at_ratio",
"apply_move_completed", "move_completed", "is_auto_managed", "auto_add"]
spin_ids = ['max_download_speed', 'max_upload_speed', 'stop_ratio']
spin_int_ids = ['max_upload_slots', 'max_connections']
chk_ids = ['apply_max', 'apply_queue', 'stop_at_ratio', 'apply_queue', 'remove_at_ratio',
'apply_move_completed', 'move_completed', 'is_auto_managed', 'auto_add']
# list of tuples, because order matters when nesting.
sensitive_groups = [
("apply_max", ["max_download_speed", "max_upload_speed", "max_upload_slots", "max_connections"]),
("apply_queue", ["is_auto_managed", "stop_at_ratio"]),
("stop_at_ratio", ["remove_at_ratio", "stop_ratio"]), # nested
("apply_move_completed", ["move_completed"]),
("move_completed", ["move_completed_path"]), # nested
("auto_add", ["auto_add_trackers"])
('apply_max', ['max_download_speed', 'max_upload_speed', 'max_upload_slots', 'max_connections']),
('apply_queue', ['is_auto_managed', 'stop_at_ratio']),
('stop_at_ratio', ['remove_at_ratio', 'stop_ratio']), # nested
('apply_move_completed', ['move_completed']),
('move_completed', ['move_completed_path']), # nested
('auto_add', ['auto_add_trackers'])
]
def __init__(self):
@ -152,20 +152,20 @@ class OptionsDialog(object):
def show(self, label):
self.label = label
self.glade = gtk.glade.XML(get_resource("label_options.glade"))
self.dialog = self.glade.get_widget("dlg_label_options")
self.dialog.set_transient_for(component.get("MainWindow").window)
self.glade = gtk.glade.XML(get_resource('label_options.glade'))
self.dialog = self.glade.get_widget('dlg_label_options')
self.dialog.set_transient_for(component.get('MainWindow').window)
self.glade.signal_autoconnect({
"on_options_ok": self.on_ok,
"on_options_cancel": self.on_cancel,
'on_options_ok': self.on_ok,
'on_options_cancel': self.on_cancel,
})
# Show the label name in the header label
self.glade.get_widget("label_header").set_markup("<b>%s:</b> %s" % (_("Label Options"), self.label))
self.glade.get_widget('label_header').set_markup('<b>%s:</b> %s' % (_('Label Options'), self.label))
for chk_id, group in self.sensitive_groups:
chk = self.glade.get_widget(chk_id)
chk.connect("toggled", self.apply_sensitivity)
chk.connect('toggled', self.apply_sensitivity)
client.label.get_options(self.label).addCallback(self.load_options)
@ -180,20 +180,20 @@ class OptionsDialog(object):
self.glade.get_widget(chk_id).set_active(bool(options[chk_id]))
if client.is_localhost():
self.glade.get_widget("move_completed_path").set_filename(options["move_completed_path"])
self.glade.get_widget("move_completed_path").show()
self.glade.get_widget("move_completed_path_entry").hide()
self.glade.get_widget('move_completed_path').set_filename(options['move_completed_path'])
self.glade.get_widget('move_completed_path').show()
self.glade.get_widget('move_completed_path_entry').hide()
else:
self.glade.get_widget("move_completed_path_entry").set_text(options["move_completed_path"])
self.glade.get_widget("move_completed_path_entry").show()
self.glade.get_widget("move_completed_path").hide()
self.glade.get_widget('move_completed_path_entry').set_text(options['move_completed_path'])
self.glade.get_widget('move_completed_path_entry').show()
self.glade.get_widget('move_completed_path').hide()
self.glade.get_widget("auto_add_trackers").get_buffer().set_text("\n".join(options["auto_add_trackers"]))
self.glade.get_widget('auto_add_trackers').get_buffer().set_text('\n'.join(options['auto_add_trackers']))
self.apply_sensitivity()
def on_ok(self, event=None):
"save options.."
'save options..'
options = {}
for spin_id in self.spin_ids:
@ -204,13 +204,13 @@ class OptionsDialog(object):
options[chk_id] = self.glade.get_widget(chk_id).get_active()
if client.is_localhost():
options["move_completed_path"] = self.glade.get_widget("move_completed_path").get_filename()
options['move_completed_path'] = self.glade.get_widget('move_completed_path').get_filename()
else:
options["move_completed_path"] = self.glade.get_widget("move_completed_path_entry").get_text()
options['move_completed_path'] = self.glade.get_widget('move_completed_path_entry').get_text()
buff = self.glade.get_widget("auto_add_trackers").get_buffer() # sometimes I hate gtk...
tracker_lst = buff.get_text(buff.get_start_iter(), buff.get_end_iter()).strip().split("\n")
options["auto_add_trackers"] = [x for x in tracker_lst if x] # filter out empty lines.
buff = self.glade.get_widget('auto_add_trackers').get_buffer() # sometimes I hate gtk...
tracker_lst = buff.get_text(buff.get_start_iter(), buff.get_end_iter()).strip().split('\n')
options['auto_add_trackers'] = [x for x in tracker_lst if x] # filter out empty lines.
log.debug(options)
client.label.set_options(self.label, options)
@ -219,7 +219,7 @@ class OptionsDialog(object):
def apply_sensitivity(self, event=None):
for chk_id, sensitive_list in self.sensitive_groups:
chk = self.glade.get_widget(chk_id)
sens = chk.get_active() and chk.get_property("sensitive")
sens = chk.get_active() and chk.get_property('sensitive')
for widget_id in sensitive_list:
self.glade.get_widget(widget_id).set_sensitive(sens)

View File

@ -21,26 +21,26 @@ log = logging.getLogger(__name__)
# Deferred Translation
def _(message):
return message
NO_LABEL = _("No Label")
NO_LABEL = _('No Label')
del _
class LabelMenu(gtk.MenuItem):
def __init__(self):
gtk.MenuItem.__init__(self, _("Label"))
gtk.MenuItem.__init__(self, _('Label'))
self.sub_menu = gtk.Menu()
self.set_submenu(self.sub_menu)
self.items = []
# attach..
self.sub_menu.connect("show", self.on_show, None)
self.sub_menu.connect('show', self.on_show, None)
def get_torrent_ids(self):
return component.get("TorrentView").get_selected_torrents()
return component.get('TorrentView').get_selected_torrents()
def on_show(self, widget=None, data=None):
log.debug("label-on-show")
log.debug('label-on-show')
client.label.get_labels().addCallback(self.cb_labels)
def cb_labels(self, labels):
@ -50,12 +50,12 @@ class LabelMenu(gtk.MenuItem):
if label == NO_LABEL:
item = gtk.MenuItem(_(NO_LABEL))
else:
item = gtk.MenuItem(label.replace("_", "__"))
item.connect("activate", self.on_select_label, label)
item = gtk.MenuItem(label.replace('_', '__'))
item.connect('activate', self.on_select_label, label)
self.sub_menu.append(item)
self.show_all()
def on_select_label(self, widget=None, label_id=None):
log.debug("select label:%s,%s", label_id, self.get_torrent_ids())
log.debug('select label:%s,%s', label_id, self.get_torrent_ids())
for torrent_id in self.get_torrent_ids():
client.label.set_torrent(torrent_id, label_id)

View File

@ -19,32 +19,32 @@ sclient.set_core_uri()
print(sclient.get_enabled_plugins())
# enable plugin.
if "label" not in sclient.get_enabled_plugins():
sclient.enable_plugin("label")
if 'label' not in sclient.get_enabled_plugins():
sclient.enable_plugin('label')
# test labels.
print("#init labels")
print('#init labels')
try:
sclient.label_remove("test")
sclient.label_remove('test')
except Exception:
pass
sess_id = sclient.get_session_state()[0]
print("#add")
sclient.label_add("test")
print("#set")
sclient.label_set_torrent(id, "test")
print('#add')
sclient.label_add('test')
print('#set')
sclient.label_set_torrent(id, 'test')
print(sclient.get_torrents_status({"label": "test"}, "name"))
print(sclient.get_torrents_status({'label': 'test'}, 'name'))
print("#set options")
sclient.label_set_options("test", {"max_download_speed": 999}, True)
print(sclient.get_torrent_status(sess_id, ["max_download_speed"]), "999")
sclient.label_set_options("test", {"max_download_speed": 9}, True)
print(sclient.get_torrent_status(sess_id, ["max_download_speed"]), "9")
sclient.label_set_options("test", {"max_download_speed": 888}, False)
print(sclient.get_torrent_status(sess_id, ["max_download_speed"]), "9 (888)")
print('#set options')
sclient.label_set_options('test', {'max_download_speed': 999}, True)
print(sclient.get_torrent_status(sess_id, ['max_download_speed']), '999')
sclient.label_set_options('test', {'max_download_speed': 9}, True)
print(sclient.get_torrent_status(sess_id, ['max_download_speed']), '9')
sclient.label_set_options('test', {'max_download_speed': 888}, False)
print(sclient.get_torrent_status(sess_id, ['max_download_speed']), '9 (888)')
print(sclient.get_torrent_status(sess_id, ['name', 'tracker_host', 'label']))

View File

@ -22,11 +22,11 @@ log = logging.getLogger(__name__)
def get_resource(filename):
return pkg_resources.resource_filename("deluge.plugins.label",
os.path.join("data", filename))
return pkg_resources.resource_filename('deluge.plugins.label',
os.path.join('data', filename))
class WebUI(WebPluginBase):
scripts = [get_resource("label.js")]
scripts = [get_resource('label.js')]
debug_scripts = scripts

View File

@ -9,19 +9,19 @@
from setuptools import find_packages, setup
__plugin_name__ = "Label"
__author__ = "Martijn Voncken"
__author_email__ = "mvoncken@gmail.com"
__version__ = "0.2"
__url__ = "http://deluge-torrent.org"
__license__ = "GPLv3"
__description__ = "Allows labels to be assigned to torrents"
__plugin_name__ = 'Label'
__author__ = 'Martijn Voncken'
__author_email__ = 'mvoncken@gmail.com'
__version__ = '0.2'
__url__ = 'http://deluge-torrent.org'
__license__ = 'GPLv3'
__description__ = 'Allows labels to be assigned to torrents'
__long_description__ = """
Allows labels to be assigned to torrents
Also offers filters on state, tracker and keywords
"""
__pkg_data__ = {"deluge.plugins." + __plugin_name__.lower(): ["template/*", "data/*"]}
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ['template/*', 'data/*']}
setup(
name=__plugin_name__,
@ -34,7 +34,7 @@ setup(
long_description=__long_description__,
packages=find_packages(),
namespace_packages=["deluge", "deluge.plugins"],
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
entry_points="""

View File

@ -30,17 +30,17 @@ except ImportError:
def get_resource(filename):
import os
import pkg_resources
return pkg_resources.resource_filename("deluge.plugins.notifications", os.path.join("data", filename))
return pkg_resources.resource_filename('deluge.plugins.notifications', os.path.join('data', filename))
class CustomNotifications(object):
def __init__(self, plugin_name=None):
self.custom_notifications = {
"email": {},
"popup": {},
"blink": {},
"sound": {}
'email': {},
'popup': {},
'blink': {},
'sound': {}
}
def enable(self):
@ -55,9 +55,9 @@ class CustomNotifications(object):
def _handle_custom_providers(self, kind, eventtype, *args, **kwargs):
log.debug("Calling CORE's custom %s providers for %s: %s %s",
kind, eventtype, args, kwargs)
if eventtype in self.config["subscriptions"][kind]:
if eventtype in self.config['subscriptions'][kind]:
wrapper, handler = self.custom_notifications[kind][eventtype]
log.debug("Found handler for kind %s: %s", kind, handler)
log.debug('Found handler for kind %s: %s', kind, handler)
custom_notif_func = getattr(self,
'handle_custom_%s_notification' % kind)
d = defer.maybeDeferred(handler, *args, **kwargs)
@ -68,7 +68,7 @@ class CustomNotifications(object):
def _register_custom_provider(self, kind, eventtype, handler):
if not self._handled_eventtype(eventtype, handler):
return defer.succeed("Event not handled")
return defer.succeed('Event not handled')
if eventtype not in self.custom_notifications:
def wrapper(*args, **kwargs):
return self._handle_custom_providers(kind, eventtype, *args, **kwargs)
@ -76,7 +76,7 @@ class CustomNotifications(object):
else:
wrapper, handler = self.custom_notifications[kind][eventtype]
try:
component.get("EventManager").register_event_handler(
component.get('EventManager').register_event_handler(
eventtype, wrapper
)
except KeyError:
@ -87,7 +87,7 @@ class CustomNotifications(object):
try:
wrapper, handler = self.custom_notifications[kind][eventtype]
try:
component.get("EventManager").deregister_event_handler(
component.get('EventManager').deregister_event_handler(
eventtype, wrapper
)
except KeyError:
@ -104,15 +104,15 @@ class CustomNotifications(object):
if known_events[eventtype].__module__.startswith('deluge.event'):
if handler.__self__ is self:
return True
log.error("You cannot register custom notification providers "
"for built-in event types.")
log.error('You cannot register custom notification providers '
'for built-in event types.')
return False
return True
def _on_notify_sucess(self, result, kind):
log.debug("Notification success using %s: %s", kind, result)
log.debug('Notification success using %s: %s', kind, result)
return result
def _on_notify_failure(self, failure, kind):
log.debug("Notification failure using %s: %s", kind, failure)
log.debug('Notification failure using %s: %s', kind, failure)
return failure

View File

@ -29,17 +29,17 @@ from .common import CustomNotifications
log = logging.getLogger(__name__)
DEFAULT_PREFS = {
"smtp_enabled": False,
"smtp_host": "",
"smtp_port": 25,
"smtp_user": "",
"smtp_pass": "",
"smtp_from": "",
"smtp_tls": False, # SSL or TLS
"smtp_recipients": [],
'smtp_enabled': False,
'smtp_host': '',
'smtp_port': 25,
'smtp_user': '',
'smtp_pass': '',
'smtp_from': '',
'smtp_tls': False, # SSL or TLS
'smtp_recipients': [],
# Subscriptions
"subscriptions": {
"email": []
'subscriptions': {
'email': []
}
}
@ -73,9 +73,9 @@ class CoreNotifications(CustomNotifications):
def handle_custom_email_notification(self, result, eventtype):
if not self.config['smtp_enabled']:
return defer.succeed("SMTP notification not enabled.")
return defer.succeed('SMTP notification not enabled.')
subject, message = result
log.debug("Spawning new thread to send email with subject: %s: %s",
log.debug('Spawning new thread to send email with subject: %s: %s',
subject, message)
# Spawn thread because we don't want Deluge to lock up while we send the
# email.
@ -90,11 +90,11 @@ class CoreNotifications(CustomNotifications):
continue
classdoc = known_events[evt].__doc__.strip()
handled_events.append((evt, classdoc))
log.debug("Handled Notification Events: %s", handled_events)
log.debug('Handled Notification Events: %s', handled_events)
return handled_events
def _notify_email(self, subject='', message=''):
log.debug("Email prepared")
log.debug('Email prepared')
to_addrs = self.config['smtp_recipients']
to_addrs_str = ', '.join(self.config['smtp_recipients'])
headers_dict = {
@ -115,9 +115,9 @@ Date: %(date)s
try:
# Python 2.6
server = smtplib.SMTP(self.config["smtp_host"], self.config["smtp_port"], timeout=60)
server = smtplib.SMTP(self.config['smtp_host'], self.config['smtp_port'], timeout=60)
except Exception as ex:
err_msg = _("There was an error sending the notification email: %s") % ex
err_msg = _('There was an error sending the notification email: %s') % ex
log.error(err_msg)
return ex
@ -126,7 +126,7 @@ Date: %(date)s
if security_enabled:
server.ehlo()
if 'starttls' not in server.esmtp_features:
log.warning("TLS/SSL enabled but server does not support it")
log.warning('TLS/SSL enabled but server does not support it')
else:
server.starttls()
server.ehlo()
@ -136,12 +136,12 @@ Date: %(date)s
server.login(self.config['smtp_user'], self.config['smtp_pass'])
except smtplib.SMTPHeloError as ex:
err_msg = _("The server didn't reply properly to the helo "
"greeting: %s") % ex
'greeting: %s') % ex
log.error(err_msg)
return ex
except smtplib.SMTPAuthenticationError as ex:
err_msg = _("The server didn't accept the username/password "
"combination: %s") % ex
'combination: %s') % ex
log.error(err_msg)
return ex
@ -149,8 +149,8 @@ Date: %(date)s
try:
server.sendmail(self.config['smtp_from'], to_addrs, message)
except smtplib.SMTPException as ex:
err_msg = _("There was an error sending the notification email:"
" %s") % ex
err_msg = _('There was an error sending the notification email:'
' %s') % ex
log.error(err_msg)
return ex
finally:
@ -164,20 +164,20 @@ Date: %(date)s
pass
else:
server.quit()
return _("Notification email sent.")
return _('Notification email sent.')
def _on_torrent_finished_event(self, torrent_id):
log.debug("Handler for TorrentFinishedEvent called for CORE")
torrent = component.get("TorrentManager")[torrent_id]
log.debug('Handler for TorrentFinishedEvent called for CORE')
torrent = component.get('TorrentManager')[torrent_id]
torrent_status = torrent.get_status({})
# Email
subject = _("Finished Torrent \"%(name)s\"") % torrent_status
message = _(
"This email is to inform you that Deluge has finished "
'This email is to inform you that Deluge has finished '
"downloading \"%(name)s\", which includes %(num_files)i files."
"\nTo stop receiving these alerts, simply turn off email "
'\nTo stop receiving these alerts, simply turn off email '
"notification in Deluge's preferences.\n\n"
"Thank you,\nDeluge."
'Thank you,\nDeluge.'
) % torrent_status
return subject, message
@ -197,23 +197,23 @@ class Core(CorePluginBase, CoreNotifications):
def enable(self):
CoreNotifications.enable(self)
self.config = deluge.configmanager.ConfigManager(
"notifications-core.conf", DEFAULT_PREFS)
log.debug("ENABLING CORE NOTIFICATIONS")
'notifications-core.conf', DEFAULT_PREFS)
log.debug('ENABLING CORE NOTIFICATIONS')
def disable(self):
log.debug("DISABLING CORE NOTIFICATIONS")
log.debug('DISABLING CORE NOTIFICATIONS')
CoreNotifications.disable(self)
@export
def set_config(self, config):
"sets the config dictionary"
'sets the config dictionary'
for key in config.keys():
self.config[key] = config[key]
self.config.save()
@export
def get_config(self):
"returns the config dictionary"
'returns the config dictionary'
return self.config.config
@export

View File

@ -48,20 +48,20 @@ except ImportError:
DEFAULT_PREFS = {
# BLINK
"blink_enabled": False,
'blink_enabled': False,
# FLASH
"flash_enabled": False,
'flash_enabled': False,
# POPUP
"popup_enabled": False,
'popup_enabled': False,
# SOUND
"sound_enabled": False,
"sound_path": "",
"custom_sounds": {},
'sound_enabled': False,
'sound_path': '',
'custom_sounds': {},
# Subscriptions
"subscriptions": {
"popup": [],
"blink": [],
"sound": [],
'subscriptions': {
'popup': [],
'blink': [],
'sound': [],
},
}
@ -79,19 +79,19 @@ class GtkUiNotifications(CustomNotifications):
def enable(self):
CustomNotifications.enable(self)
self.register_custom_blink_notification(
"TorrentFinishedEvent", self._on_torrent_finished_event_blink
'TorrentFinishedEvent', self._on_torrent_finished_event_blink
)
self.register_custom_sound_notification(
"TorrentFinishedEvent", self._on_torrent_finished_event_sound
'TorrentFinishedEvent', self._on_torrent_finished_event_sound
)
self.register_custom_popup_notification(
"TorrentFinishedEvent", self._on_torrent_finished_event_popup
'TorrentFinishedEvent', self._on_torrent_finished_event_popup
)
def disable(self):
self.deregister_custom_blink_notification("TorrentFinishedEvent")
self.deregister_custom_sound_notification("TorrentFinishedEvent")
self.deregister_custom_popup_notification("TorrentFinishedEvent")
self.deregister_custom_blink_notification('TorrentFinishedEvent')
self.deregister_custom_sound_notification('TorrentFinishedEvent')
self.deregister_custom_popup_notification('TorrentFinishedEvent')
CustomNotifications.disable(self)
def register_custom_popup_notification(self, eventtype, handler):
@ -146,7 +146,7 @@ class GtkUiNotifications(CustomNotifications):
if result:
return defer.maybeDeferred(self.__blink)
return defer.succeed("Won't blink. The returned value from the custom "
"handler was: %s" % result)
'handler was: %s' % result)
def handle_custom_sound_notification(self, result, eventtype):
if isinstance(result, basestring):
@ -155,33 +155,33 @@ class GtkUiNotifications(CustomNotifications):
self.__play_sound, self.config['custom_sounds'][eventtype])
return defer.maybeDeferred(self.__play_sound, result)
return defer.succeed("Won't play sound. The returned value from the "
"custom handler was: %s" % result)
'custom handler was: %s' % result)
def __blink(self):
self.systray.blink(True)
return defer.succeed(_("Notification Blink shown"))
return defer.succeed(_('Notification Blink shown'))
def __popup(self, title='', message=''):
if not self.config['popup_enabled']:
return defer.succeed(_("Popup notification is not enabled."))
return defer.succeed(_('Popup notification is not enabled.'))
if not POPUP_AVAILABLE:
return defer.fail(_("pynotify is not installed"))
return defer.fail(_('pynotify is not installed'))
if pynotify.init("Deluge"):
icon = gtk.gdk.pixbuf_new_from_file_at_size(deluge.common.get_pixmap("deluge.svg"), 48, 48)
if pynotify.init('Deluge'):
icon = gtk.gdk.pixbuf_new_from_file_at_size(deluge.common.get_pixmap('deluge.svg'), 48, 48)
self.note = pynotify.Notification(title, message)
self.note.set_icon_from_pixbuf(icon)
if not self.note.show():
err_msg = _("pynotify failed to show notification")
err_msg = _('pynotify failed to show notification')
log.warning(err_msg)
return defer.fail(err_msg)
return defer.succeed(_("Notification popup shown"))
return defer.succeed(_('Notification popup shown'))
def __play_sound(self, sound_path=''):
if not self.config['sound_enabled']:
return defer.succeed(_("Sound notification not enabled"))
return defer.succeed(_('Sound notification not enabled'))
if not SOUND_AVAILABLE:
err_msg = _("pygame is not installed")
err_msg = _('pygame is not installed')
log.warning(err_msg)
return defer.fail(err_msg)
@ -193,11 +193,11 @@ class GtkUiNotifications(CustomNotifications):
alert_sound.load(sound_path)
alert_sound.play()
except pygame.error as ex:
err_msg = _("Sound notification failed %s") % ex
err_msg = _('Sound notification failed %s') % ex
log.warning(err_msg)
return defer.fail(err_msg)
else:
msg = _("Sound notification Success")
msg = _('Sound notification Success')
log.info(msg)
return defer.succeed(msg)
@ -209,21 +209,21 @@ class GtkUiNotifications(CustomNotifications):
return ''
def _on_torrent_finished_event_popup(self, torrent_id):
d = client.core.get_torrent_status(torrent_id, ["name", "file_progress"])
d = client.core.get_torrent_status(torrent_id, ['name', 'file_progress'])
d.addCallback(self._on_torrent_finished_event_got_torrent_status)
d.addErrback(self._on_torrent_finished_event_torrent_status_failure)
return d
def _on_torrent_finished_event_torrent_status_failure(self, failure):
log.debug("Failed to get torrent status to be able to show the popup")
log.debug('Failed to get torrent status to be able to show the popup')
def _on_torrent_finished_event_got_torrent_status(self, torrent_status):
log.debug("Handler for TorrentFinishedEvent GTKUI called. "
"Got Torrent Status")
title = _("Finished Torrent")
torrent_status["num_files"] = torrent_status["file_progress"].count(1.0)
log.debug('Handler for TorrentFinishedEvent GTKUI called. '
'Got Torrent Status')
title = _('Finished Torrent')
torrent_status['num_files'] = torrent_status['file_progress'].count(1.0)
message = _("The torrent \"%(name)s\" including %(num_files)i file(s) "
"has finished downloading.") % torrent_status
'has finished downloading.') % torrent_status
return title, message
@ -234,11 +234,11 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
def enable(self):
self.config = deluge.configmanager.ConfigManager(
"notifications-gtk.conf", DEFAULT_PREFS
'notifications-gtk.conf', DEFAULT_PREFS
)
self.glade = gtk.glade.XML(get_resource("config.glade"))
self.glade.get_widget("smtp_port").set_value(25)
self.prefs = self.glade.get_widget("prefs_box")
self.glade = gtk.glade.XML(get_resource('config.glade'))
self.glade.get_widget('smtp_port').set_value(25)
self.prefs = self.glade.get_widget('prefs_box')
self.prefs.show_all()
self.build_recipients_model_populate_treeview()
@ -261,25 +261,25 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
'on_sound_path_update_preview': self.on_sound_path_update_preview
})
prefs = component.get("Preferences")
prefs = component.get('Preferences')
parent = self.prefs.get_parent()
if parent:
parent.remove(self.prefs)
index = prefs.notebook.append_page(self.prefs)
prefs.liststore.append([index, _("Notifications")])
prefs.liststore.append([index, _('Notifications')])
component.get("PluginManager").register_hook("on_apply_prefs",
component.get('PluginManager').register_hook('on_apply_prefs',
self.on_apply_prefs)
component.get("PluginManager").register_hook("on_show_prefs",
component.get('PluginManager').register_hook('on_show_prefs',
self.on_show_prefs)
if not POPUP_AVAILABLE:
self.glade.get_widget("popup_enabled").set_property('sensitive',
self.glade.get_widget('popup_enabled').set_property('sensitive',
False)
if not SOUND_AVAILABLE:
# for widget_name in ('sound_enabled', 'sound_path', 'sounds_page', 'sounds_page_label'):
# self.glade.get_widget(widget_name).set_property('sensitive', False)
self.glade.get_widget("sound_enabled").set_property('sensitive',
self.glade.get_widget('sound_enabled').set_property('sensitive',
False)
self.glade.get_widget('sound_path').set_property('sensitive', False)
self.glade.get_widget('sounds_page').set_property('sensitive',
@ -287,7 +287,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
self.glade.get_widget('sounds_page_label').set_property('sensitive',
False)
self.systray = component.get("SystemTray")
self.systray = component.get('SystemTray')
if not hasattr(self.systray, 'tray'):
# Tray is not beeing used
self.glade.get_widget('blink_enabled').set_property('sensitive',
@ -297,25 +297,25 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
def disable(self):
GtkUiNotifications.disable(self)
component.get("Preferences").remove_page(_("Notifications"))
component.get("PluginManager").deregister_hook("on_apply_prefs",
component.get('Preferences').remove_page(_('Notifications'))
component.get('PluginManager').deregister_hook('on_apply_prefs',
self.on_apply_prefs)
component.get("PluginManager").deregister_hook("on_show_prefs",
component.get('PluginManager').deregister_hook('on_show_prefs',
self.on_show_prefs)
def build_recipients_model_populate_treeview(self):
# SMTP Recipients treeview/model
self.recipients_treeview = self.glade.get_widget("smtp_recipients")
self.recipients_treeview = self.glade.get_widget('smtp_recipients')
treeview_selection = self.recipients_treeview.get_selection()
treeview_selection.connect(
"changed", self.on_recipients_treeview_selection_changed
'changed', self.on_recipients_treeview_selection_changed
)
self.recipients_model = gtk.ListStore(str, bool)
renderer = gtk.CellRendererText()
renderer.connect("edited", self.on_cell_edited, self.recipients_model)
renderer.set_data("recipient", RECIPIENT_FIELD)
column = gtk.TreeViewColumn("Recipients", renderer,
renderer.connect('edited', self.on_cell_edited, self.recipients_model)
renderer.set_data('recipient', RECIPIENT_FIELD)
column = gtk.TreeViewColumn('Recipients', renderer,
text=RECIPIENT_FIELD,
editable=RECIPIENT_EDIT)
column.set_expand(True)
@ -327,32 +327,32 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
self.sounds_treeview = self.glade.get_widget('sounds_treeview')
sounds_selection = self.sounds_treeview.get_selection()
sounds_selection.connect(
"changed", self.on_sounds_treeview_selection_changed
'changed', self.on_sounds_treeview_selection_changed
)
self.sounds_treeview.set_tooltip_column(SND_EVENT_DOC)
self.sounds_model = gtk.ListStore(str, str, str, str)
renderer = gtk.CellRendererText()
renderer.set_data("event", SND_EVENT)
column = gtk.TreeViewColumn("Event", renderer, text=SND_EVENT)
renderer.set_data('event', SND_EVENT)
column = gtk.TreeViewColumn('Event', renderer, text=SND_EVENT)
column.set_expand(True)
self.sounds_treeview.append_column(column)
renderer = gtk.CellRendererText()
renderer.set_data("event_doc", SND_EVENT_DOC)
column = gtk.TreeViewColumn("Doc", renderer, text=SND_EVENT_DOC)
renderer.set_data('event_doc', SND_EVENT_DOC)
column = gtk.TreeViewColumn('Doc', renderer, text=SND_EVENT_DOC)
column.set_property('visible', False)
self.sounds_treeview.append_column(column)
renderer = gtk.CellRendererText()
renderer.set_data("sound_name", SND_NAME)
column = gtk.TreeViewColumn("Name", renderer, text=SND_NAME)
renderer.set_data('sound_name', SND_NAME)
column = gtk.TreeViewColumn('Name', renderer, text=SND_NAME)
self.sounds_treeview.append_column(column)
renderer = gtk.CellRendererText()
renderer.set_data("sound_path", SND_PATH)
column = gtk.TreeViewColumn("Path", renderer, text=SND_PATH)
renderer.set_data('sound_path', SND_PATH)
column = gtk.TreeViewColumn('Path', renderer, text=SND_PATH)
column.set_property('visible', False)
self.sounds_treeview.append_column(column)
@ -360,51 +360,51 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
def build_notifications_model_populate_treeview(self):
# Notification Subscriptions treeview/model
self.subscriptions_treeview = self.glade.get_widget("subscriptions_treeview")
self.subscriptions_treeview = self.glade.get_widget('subscriptions_treeview')
subscriptions_selection = self.subscriptions_treeview.get_selection()
subscriptions_selection.connect(
"changed", self.on_subscriptions_treeview_selection_changed
'changed', self.on_subscriptions_treeview_selection_changed
)
self.subscriptions_treeview.set_tooltip_column(SUB_EVENT_DOC)
self.subscriptions_model = gtk.ListStore(str, str, bool, bool, bool, bool)
renderer = gtk.CellRendererText()
renderer.set_data("event", SUB_EVENT)
column = gtk.TreeViewColumn("Event", renderer, text=SUB_EVENT)
renderer.set_data('event', SUB_EVENT)
column = gtk.TreeViewColumn('Event', renderer, text=SUB_EVENT)
column.set_expand(True)
self.subscriptions_treeview.append_column(column)
renderer = gtk.CellRendererText()
renderer.set_data("event_doc", SUB_EVENT)
column = gtk.TreeViewColumn("Doc", renderer, text=SUB_EVENT_DOC)
renderer.set_data('event_doc', SUB_EVENT)
column = gtk.TreeViewColumn('Doc', renderer, text=SUB_EVENT_DOC)
column.set_property('visible', False)
self.subscriptions_treeview.append_column(column)
renderer = gtk.CellRendererToggle()
renderer.set_property('activatable', True)
renderer.connect('toggled', self._on_email_col_toggled)
column = gtk.TreeViewColumn("Email", renderer, active=SUB_NOT_EMAIL)
column = gtk.TreeViewColumn('Email', renderer, active=SUB_NOT_EMAIL)
column.set_clickable(True)
self.subscriptions_treeview.append_column(column)
renderer = gtk.CellRendererToggle()
renderer.set_property("activatable", True)
renderer.connect("toggled", self._on_popup_col_toggled)
column = gtk.TreeViewColumn("Popup", renderer, active=SUB_NOT_POPUP)
renderer.set_property('activatable', True)
renderer.connect('toggled', self._on_popup_col_toggled)
column = gtk.TreeViewColumn('Popup', renderer, active=SUB_NOT_POPUP)
column.set_clickable(True)
self.subscriptions_treeview.append_column(column)
renderer = gtk.CellRendererToggle()
renderer.set_property("activatable", True)
renderer.connect("toggled", self._on_blink_col_toggled)
column = gtk.TreeViewColumn("Blink", renderer, active=SUB_NOT_BLINK)
renderer.set_property('activatable', True)
renderer.connect('toggled', self._on_blink_col_toggled)
column = gtk.TreeViewColumn('Blink', renderer, active=SUB_NOT_BLINK)
column.set_clickable(True)
self.subscriptions_treeview.append_column(column)
renderer = gtk.CellRendererToggle()
renderer.set_property('activatable', True)
renderer.connect('toggled', self._on_sound_col_toggled)
column = gtk.TreeViewColumn("Sound", renderer, active=SUB_NOT_SOUND)
column = gtk.TreeViewColumn('Sound', renderer, active=SUB_NOT_SOUND)
column.set_clickable(True)
self.subscriptions_treeview.append_column(column)
self.subscriptions_treeview.set_model(self.subscriptions_model)
@ -444,13 +444,13 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
SUB_EVENT, event_name,
SUB_EVENT_DOC, event_doc,
SUB_NOT_EMAIL, event_name in email_subscriptions,
SUB_NOT_POPUP, event_name in subscriptions_dict["popup"],
SUB_NOT_POPUP, event_name in subscriptions_dict['popup'],
SUB_NOT_BLINK, event_name in subscriptions_dict['blink'],
SUB_NOT_SOUND, event_name in subscriptions_dict['sound']
)
def on_apply_prefs(self):
log.debug("applying prefs for Notifications")
log.debug('applying prefs for Notifications')
current_popup_subscriptions = []
current_blink_subscriptions = []
@ -467,8 +467,8 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
current_sound_subscriptions.append(event)
old_sound_file = self.config['sound_path']
new_sound_file = self.glade.get_widget("sound_path").get_filename()
log.debug("Old Default sound file: %s New one: %s",
new_sound_file = self.glade.get_widget('sound_path').get_filename()
log.debug('Old Default sound file: %s New one: %s',
old_sound_file, new_sound_file)
custom_sounds = {}
for event_name, event_doc, filename, filepath in self.sounds_model:
@ -478,30 +478,30 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
custom_sounds[event_name] = filepath
self.config.config.update({
"popup_enabled": self.glade.get_widget("popup_enabled").get_active(),
"blink_enabled": self.glade.get_widget("blink_enabled").get_active(),
"sound_enabled": self.glade.get_widget("sound_enabled").get_active(),
"sound_path": new_sound_file,
"subscriptions": {
"popup": current_popup_subscriptions,
"blink": current_blink_subscriptions,
"sound": current_sound_subscriptions
'popup_enabled': self.glade.get_widget('popup_enabled').get_active(),
'blink_enabled': self.glade.get_widget('blink_enabled').get_active(),
'sound_enabled': self.glade.get_widget('sound_enabled').get_active(),
'sound_path': new_sound_file,
'subscriptions': {
'popup': current_popup_subscriptions,
'blink': current_blink_subscriptions,
'sound': current_sound_subscriptions
},
"custom_sounds": custom_sounds
'custom_sounds': custom_sounds
})
self.config.save()
core_config = {
"smtp_enabled": self.glade.get_widget("smtp_enabled").get_active(),
"smtp_host": self.glade.get_widget("smtp_host").get_text(),
"smtp_port": self.glade.get_widget("smtp_port").get_value(),
"smtp_user": self.glade.get_widget("smtp_user").get_text(),
"smtp_pass": self.glade.get_widget("smtp_pass").get_text(),
"smtp_from": self.glade.get_widget("smtp_from").get_text(),
"smtp_tls": self.glade.get_widget("smtp_tls").get_active(),
"smtp_recipients": [dest[0] for dest in self.recipients_model if
dest[0] != "USER@HOST"],
"subscriptions": {"email": current_email_subscriptions}
'smtp_enabled': self.glade.get_widget('smtp_enabled').get_active(),
'smtp_host': self.glade.get_widget('smtp_host').get_text(),
'smtp_port': self.glade.get_widget('smtp_port').get_value(),
'smtp_user': self.glade.get_widget('smtp_user').get_text(),
'smtp_pass': self.glade.get_widget('smtp_pass').get_text(),
'smtp_from': self.glade.get_widget('smtp_from').get_text(),
'smtp_tls': self.glade.get_widget('smtp_tls').get_active(),
'smtp_recipients': [dest[0] for dest in self.recipients_model if
dest[0] != 'USER@HOST'],
'subscriptions': {'email': current_email_subscriptions}
}
client.notifications.set_config(core_config)
@ -511,37 +511,37 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
client.notifications.get_config().addCallback(self.cb_get_config)
def cb_get_config(self, core_config):
"callback for on show_prefs"
self.glade.get_widget("smtp_host").set_text(core_config["smtp_host"])
self.glade.get_widget("smtp_port").set_value(core_config["smtp_port"])
self.glade.get_widget("smtp_user").set_text(core_config["smtp_user"])
self.glade.get_widget("smtp_pass").set_text(core_config["smtp_pass"])
self.glade.get_widget("smtp_from").set_text(core_config["smtp_from"])
self.glade.get_widget("smtp_tls").set_active(core_config["smtp_tls"])
'callback for on show_prefs'
self.glade.get_widget('smtp_host').set_text(core_config['smtp_host'])
self.glade.get_widget('smtp_port').set_value(core_config['smtp_port'])
self.glade.get_widget('smtp_user').set_text(core_config['smtp_user'])
self.glade.get_widget('smtp_pass').set_text(core_config['smtp_pass'])
self.glade.get_widget('smtp_from').set_text(core_config['smtp_from'])
self.glade.get_widget('smtp_tls').set_active(core_config['smtp_tls'])
self.recipients_model.clear()
for recipient in core_config['smtp_recipients']:
self.recipients_model.set(self.recipients_model.append(),
RECIPIENT_FIELD, recipient,
RECIPIENT_EDIT, False)
self.glade.get_widget("smtp_enabled").set_active(
self.glade.get_widget('smtp_enabled').set_active(
core_config['smtp_enabled']
)
self.glade.get_widget("sound_enabled").set_active(
self.glade.get_widget('sound_enabled').set_active(
self.config['sound_enabled']
)
self.glade.get_widget("popup_enabled").set_active(
self.glade.get_widget('popup_enabled').set_active(
self.config['popup_enabled']
)
self.glade.get_widget("blink_enabled").set_active(
self.glade.get_widget('blink_enabled').set_active(
self.config['blink_enabled']
)
if self.config['sound_path']:
sound_path = self.config['sound_path']
else:
sound_path = deluge.common.get_default_download_dir()
self.glade.get_widget("sound_path").set_filename(sound_path)
self.glade.get_widget('sound_path').set_filename(sound_path)
# Force toggle
self.on_enabled_toggled(self.glade.get_widget("smtp_enabled"))
self.on_enabled_toggled(self.glade.get_widget('smtp_enabled'))
self.on_sound_enabled_toggled(self.glade.get_widget('sound_enabled'))
client.notifications.get_handled_events().addCallback(
@ -557,7 +557,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
def on_add_button_clicked(self, widget, treeview):
model = treeview.get_model()
model.set(model.append(),
RECIPIENT_FIELD, "USER@HOST",
RECIPIENT_FIELD, 'USER@HOST',
RECIPIENT_EDIT, True)
def on_delete_button_clicked(self, widget, treeview):
@ -573,53 +573,53 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
def on_recipients_treeview_selection_changed(self, selection):
model, selected_connection_iter = selection.get_selected()
if selected_connection_iter:
self.glade.get_widget("delete_button").set_property('sensitive',
self.glade.get_widget('delete_button').set_property('sensitive',
True)
else:
self.glade.get_widget("delete_button").set_property('sensitive',
self.glade.get_widget('delete_button').set_property('sensitive',
False)
def on_subscriptions_treeview_selection_changed(self, selection):
model, selected_connection_iter = selection.get_selected()
if selected_connection_iter:
self.glade.get_widget("delete_button").set_property('sensitive',
self.glade.get_widget('delete_button').set_property('sensitive',
True)
else:
self.glade.get_widget("delete_button").set_property('sensitive',
self.glade.get_widget('delete_button').set_property('sensitive',
False)
def on_sounds_treeview_selection_changed(self, selection):
model, selected_iter = selection.get_selected()
if selected_iter:
self.glade.get_widget("sounds_edit_button").set_property("sensitive", True)
self.glade.get_widget('sounds_edit_button').set_property('sensitive', True)
path = model.get(selected_iter, SND_PATH)[0]
log.debug("Sound selection changed: %s", path)
log.debug('Sound selection changed: %s', path)
if path != self.config['sound_path']:
self.glade.get_widget("sounds_revert_button").set_property("sensitive", True)
self.glade.get_widget('sounds_revert_button').set_property('sensitive', True)
else:
self.glade.get_widget("sounds_revert_button").set_property("sensitive", False)
self.glade.get_widget('sounds_revert_button').set_property('sensitive', False)
else:
self.glade.get_widget("sounds_edit_button").set_property("sensitive", False)
self.glade.get_widget("sounds_revert_button").set_property("sensitive", False)
self.glade.get_widget('sounds_edit_button').set_property('sensitive', False)
self.glade.get_widget('sounds_revert_button').set_property('sensitive', False)
def on_sounds_revert_button_clicked(self, widget):
log.debug("on_sounds_revert_button_clicked")
log.debug('on_sounds_revert_button_clicked')
selection = self.sounds_treeview.get_selection()
model, selected_iter = selection.get_selected()
if selected_iter:
log.debug("on_sounds_revert_button_clicked: got iter")
log.debug('on_sounds_revert_button_clicked: got iter')
model.set(selected_iter,
SND_PATH, self.config['sound_path'],
SND_NAME, basename(self.config['sound_path']))
def on_sounds_edit_button_clicked(self, widget):
log.debug("on_sounds_edit_button_clicked")
log.debug('on_sounds_edit_button_clicked')
selection = self.sounds_treeview.get_selection()
model, selected_iter = selection.get_selected()
if selected_iter:
path = model.get(selected_iter, SND_PATH)[0]
dialog = gtk.FileChooserDialog(
title=_("Choose Sound File"),
title=_('Choose Sound File'),
buttons=(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
@ -638,7 +638,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
d = defer.maybeDeferred(dialog.run)
d.addCallback(update_model)
log.debug("dialog should have been shown")
log.debug('dialog should have been shown')
def on_enabled_toggled(self, widget):
for widget_name in ('smtp_host', 'smtp_port', 'smtp_user', 'smtp_pass',

View File

@ -37,16 +37,16 @@ class TestEmailNotifications(component.Component):
self.events_classes = []
def enable(self):
log.debug("\n\nEnabling %s", self.__class__.__name__)
log.debug('\n\nEnabling %s', self.__class__.__name__)
for event in self.events:
if self.__imp == 'core':
# component.get("CorePlugin.Notifications").register_custom_email_notification(
component.get("Notifications").register_custom_email_notification(
component.get('Notifications').register_custom_email_notification(
event.__class__.__name__,
self.custom_email_message_provider
)
elif self.__imp == 'gtk':
notifications_component = component.get("Notifications")
notifications_component = component.get('Notifications')
notifications_component.register_custom_popup_notification(
event.__class__.__name__,
self.custom_popup_message_provider
@ -63,32 +63,32 @@ class TestEmailNotifications(component.Component):
self.lc.start(60, False)
def disable(self):
log.debug("\n\nDisabling %s", self.__class__.__name__)
log.debug('\n\nDisabling %s', self.__class__.__name__)
self.lc.stop()
def update(self):
if self.__imp == 'core':
log.debug("\n\nUpdating %s", self.__class__.__name__)
log.debug('\n\nUpdating %s', self.__class__.__name__)
self.events.append(self.events.pop(0)) # Re-Queue
self.n += 1
component.get("EventManager").emit(self.events[0])
component.get('EventManager').emit(self.events[0])
def custom_email_message_provider(self, *evt_args, **evt_kwargs):
log.debug("Running custom email message provider: %s %s", evt_args, evt_kwargs)
subject = "%s Email Subject: %s" % (self.events[0].__class__.__name__, self.n)
message = "%s Email Message: %s" % (self.events[0].__class__.__name__, self.n)
log.debug('Running custom email message provider: %s %s', evt_args, evt_kwargs)
subject = '%s Email Subject: %s' % (self.events[0].__class__.__name__, self.n)
message = '%s Email Message: %s' % (self.events[0].__class__.__name__, self.n)
return subject, message
def custom_popup_message_provider(self, *evt_args, **evt_kwargs):
log.debug("Running custom popup message provider: %s %s", evt_args, evt_kwargs)
title = "%s Popup Title: %s" % (self.events[0].__class__.__name__, self.n)
message = "%s Popup Message: %s" % (self.events[0].__class__.__name__, self.n)
log.debug('Running custom popup message provider: %s %s', evt_args, evt_kwargs)
title = '%s Popup Title: %s' % (self.events[0].__class__.__name__, self.n)
message = '%s Popup Message: %s' % (self.events[0].__class__.__name__, self.n)
return title, message
def custom_blink_message_provider(self, *evt_args, **evt_kwargs):
log.debug("Running custom blink message provider: %s %s", evt_args, evt_kwargs)
log.debug('Running custom blink message provider: %s %s', evt_args, evt_kwargs)
return True
def custom_sound_message_provider(self, *evt_args, **evt_kwargs):
log.debug("Running custom sound message provider: %s %s", evt_args, evt_kwargs)
log.debug('Running custom sound message provider: %s %s', evt_args, evt_kwargs)
return ''

View File

@ -23,11 +23,11 @@ log = logging.getLogger(__name__)
class WebUI(WebPluginBase):
scripts = [get_resource("notifications.js")]
scripts = [get_resource('notifications.js')]
debug_scripts = scripts
def enable(self):
log.debug("Enabling Web UI notifications")
log.debug('Enabling Web UI notifications')
def disable(self):
log.debug("Disabling Web UI notifications")
log.debug('Disabling Web UI notifications')

View File

@ -14,13 +14,13 @@
from setuptools import find_packages, setup
__plugin_name__ = "Notifications"
__author__ = "Pedro Algarvio"
__author_email__ = "pedro@algarvio.me"
__version__ = "0.2"
__url__ = "http://dev.deluge-torrent.org/"
__license__ = "GPLv3"
__description__ = "Plugin which provides notifications to Deluge."
__plugin_name__ = 'Notifications'
__author__ = 'Pedro Algarvio'
__author_email__ = 'pedro@algarvio.me'
__version__ = '0.2'
__url__ = 'http://dev.deluge-torrent.org/'
__license__ = 'GPLv3'
__description__ = 'Plugin which provides notifications to Deluge.'
__long_description__ = """
Plugin which provides notifications to Deluge
@ -29,7 +29,7 @@ Email, Popup, Blink and Sound notifications
The plugin also allows other plugins to make
use of itself for their own custom notifications
"""
__pkg_data__ = {"deluge.plugins." + __plugin_name__.lower(): ["template/*", "data/*"]}
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ['template/*', 'data/*']}
setup(
name=__plugin_name__,
@ -42,7 +42,7 @@ setup(
long_description=__long_description__ if __long_description__ else __description__,
packages=find_packages(exclude=['**/test.py']),
namespace_packages=["deluge", "deluge.plugins"],
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
entry_points="""

View File

@ -15,4 +15,4 @@
def get_resource(filename):
import os
import pkg_resources
return pkg_resources.resource_filename("deluge.plugins.scheduler", os.path.join("data", filename))
return pkg_resources.resource_filename('deluge.plugins.scheduler', os.path.join('data', filename))

View File

@ -25,26 +25,26 @@ from deluge.plugins.pluginbase import CorePluginBase
log = logging.getLogger(__name__)
DEFAULT_PREFS = {
"low_down": -1.0,
"low_up": -1.0,
"low_active": -1,
"low_active_down": -1,
"low_active_up": -1,
"button_state": [[0] * 7 for dummy in xrange(24)]
'low_down': -1.0,
'low_up': -1.0,
'low_active': -1,
'low_active_down': -1,
'low_active_up': -1,
'button_state': [[0] * 7 for dummy in xrange(24)]
}
STATES = {
0: "Green",
1: "Yellow",
2: "Red"
0: 'Green',
1: 'Yellow',
2: 'Red'
}
CONTROLLED_SETTINGS = [
"max_download_speed",
"max_upload_speed",
"max_active_limit",
"max_active_downloading",
"max_active_seeding"
'max_download_speed',
'max_upload_speed',
'max_active_limit',
'max_active_downloading',
'max_active_seeding'
]
@ -62,14 +62,14 @@ class SchedulerEvent(DelugeEvent):
class Core(CorePluginBase):
def enable(self):
# Create the defaults with the core config
core_config = component.get("Core").config
DEFAULT_PREFS["low_down"] = core_config["max_download_speed"]
DEFAULT_PREFS["low_up"] = core_config["max_upload_speed"]
DEFAULT_PREFS["low_active"] = core_config["max_active_limit"]
DEFAULT_PREFS["low_active_down"] = core_config["max_active_downloading"]
DEFAULT_PREFS["low_active_up"] = core_config["max_active_seeding"]
core_config = component.get('Core').config
DEFAULT_PREFS['low_down'] = core_config['max_download_speed']
DEFAULT_PREFS['low_up'] = core_config['max_upload_speed']
DEFAULT_PREFS['low_active'] = core_config['max_active_limit']
DEFAULT_PREFS['low_active_down'] = core_config['max_active_downloading']
DEFAULT_PREFS['low_active_up'] = core_config['max_active_seeding']
self.config = deluge.configmanager.ConfigManager("scheduler.conf", DEFAULT_PREFS)
self.config = deluge.configmanager.ConfigManager('scheduler.conf', DEFAULT_PREFS)
self.state = self.get_state()
@ -82,12 +82,12 @@ class Core(CorePluginBase):
self.timer = reactor.callLater(secs_to_next_hour, self.do_schedule)
# Register for config changes so state isn't overridden
component.get("EventManager").register_event_handler("ConfigValueChangedEvent", self.on_config_value_changed)
component.get('EventManager').register_event_handler('ConfigValueChangedEvent', self.on_config_value_changed)
def disable(self):
if self.timer.active():
self.timer.cancel()
component.get("EventManager").deregister_event_handler("ConfigValueChangedEvent", self.on_config_value_changed)
component.get('EventManager').deregister_event_handler('ConfigValueChangedEvent', self.on_config_value_changed)
self.__apply_set_functions()
def update(self):
@ -101,11 +101,11 @@ class Core(CorePluginBase):
"""
Have the core apply it's bandwidth settings as specified in core.conf.
"""
core_config = deluge.configmanager.ConfigManager("core.conf")
core_config = deluge.configmanager.ConfigManager('core.conf')
for setting in CONTROLLED_SETTINGS:
component.get("PreferencesManager").do_config_set_func(setting, core_config[setting])
component.get('PreferencesManager').do_config_set_func(setting, core_config[setting])
# Resume the session if necessary
component.get("Core").resume_session()
component.get('Core').resume_session()
def do_schedule(self, timer=True):
"""
@ -114,30 +114,30 @@ class Core(CorePluginBase):
state = self.get_state()
if state == "Green":
if state == 'Green':
# This is Green (Normal) so we just make sure we've applied the
# global defaults
self.__apply_set_functions()
elif state == "Yellow":
elif state == 'Yellow':
# This is Yellow (Slow), so use the settings provided from the user
settings = {
"active_limit": self.config["low_active"],
"active_downloads": self.config["low_active_down"],
"active_seeds": self.config["low_active_up"],
"download_rate_limit": int(self.config["low_down"] * 1024),
"upload_rate_limit": int(self.config["low_up"] * 1024)
'active_limit': self.config['low_active'],
'active_downloads': self.config['low_active_down'],
'active_seeds': self.config['low_active_up'],
'download_rate_limit': int(self.config['low_down'] * 1024),
'upload_rate_limit': int(self.config['low_up'] * 1024)
}
component.get("Core").apply_session_settings(settings)
component.get('Core').apply_session_settings(settings)
# Resume the session if necessary
component.get("Core").resume_session()
elif state == "Red":
component.get('Core').resume_session()
elif state == 'Red':
# This is Red (Stop), so pause the libtorrent session
component.get("Core").pause_session()
component.get('Core').pause_session()
if state != self.state:
# The state has changed since last update so we need to emit an event
self.state = state
component.get("EventManager").emit(SchedulerEvent(self.state))
component.get('EventManager').emit(SchedulerEvent(self.state))
if timer:
# Call this again in 1 hour
@ -145,7 +145,7 @@ class Core(CorePluginBase):
@export()
def set_config(self, config):
"sets the config dictionary"
'sets the config dictionary'
for key in config.keys():
self.config[key] = config[key]
self.config.save()
@ -153,11 +153,11 @@ class Core(CorePluginBase):
@export()
def get_config(self):
"returns the config dictionary"
'returns the config dictionary'
return self.config.config
@export()
def get_state(self):
now = time.localtime(time.time())
level = self.config["button_state"][now[3]][now[6]]
level = self.config['button_state'][now[3]][now[6]]
return STATES[level]

View File

@ -25,7 +25,7 @@ from .common import get_resource
log = logging.getLogger(__name__)
DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
DAYS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
class SchedulerSelectWidget(gtk.DrawingArea):
@ -34,11 +34,11 @@ class SchedulerSelectWidget(gtk.DrawingArea):
self.set_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK |
gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.LEAVE_NOTIFY_MASK)
self.connect("expose_event", self.expose)
self.connect("button_press_event", self.mouse_down)
self.connect("button_release_event", self.mouse_up)
self.connect("motion_notify_event", self.mouse_hover)
self.connect("leave_notify_event", self.mouse_leave)
self.connect('expose_event', self.expose)
self.connect('button_press_event', self.mouse_down)
self.connect('button_release_event', self.mouse_up)
self.connect('motion_notify_event', self.mouse_hover)
self.connect('leave_notify_event', self.mouse_leave)
self.colors = [[115 / 255, 210 / 255, 22 / 255],
[237 / 255, 212 / 255, 0 / 255],
@ -124,8 +124,8 @@ class SchedulerSelectWidget(gtk.DrawingArea):
self.hover_point = self.get_point(event)
self.hover_label.set_text(self.hover_days[self.hover_point[1]] +
" " + str(self.hover_point[0]) +
":00 - " + str(self.hover_point[0]) + ":59")
' ' + str(self.hover_point[0]) +
':00 - ' + str(self.hover_point[0]) + ':59')
if self.mouse_press:
points = [[self.hover_point[0], self.start_point[0]], [self.hover_point[1], self.start_point[1]]]
@ -138,7 +138,7 @@ class SchedulerSelectWidget(gtk.DrawingArea):
# clear hover text on mouse leave
def mouse_leave(self, widget, event):
self.hover_label.set_text("")
self.hover_label.set_text('')
self.hover_point = [-1, -1]
@ -146,63 +146,63 @@ class GtkUI(GtkPluginBase):
def enable(self):
self.create_prefs_page()
component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs)
component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs)
self.statusbar = component.get("StatusBar")
component.get('PluginManager').register_hook('on_apply_prefs', self.on_apply_prefs)
component.get('PluginManager').register_hook('on_show_prefs', self.on_show_prefs)
self.statusbar = component.get('StatusBar')
self.status_item = self.statusbar.add_item(
image=get_resource("green.png"),
text="",
image=get_resource('green.png'),
text='',
callback=self.on_status_item_clicked,
tooltip="Scheduler")
tooltip='Scheduler')
def on_state_deferred(state):
self.state = state
self.on_scheduler_event(state)
client.scheduler.get_state().addCallback(on_state_deferred)
client.register_event_handler("SchedulerEvent", self.on_scheduler_event)
client.register_event_handler('SchedulerEvent', self.on_scheduler_event)
def disable(self):
component.get("Preferences").remove_page(_("Scheduler"))
component.get('Preferences').remove_page(_('Scheduler'))
# Reset statusbar dict.
self.statusbar.config_value_changed_dict["max_download_speed"] = self.statusbar._on_max_download_speed
self.statusbar.config_value_changed_dict["max_upload_speed"] = self.statusbar._on_max_upload_speed
self.statusbar.config_value_changed_dict['max_download_speed'] = self.statusbar._on_max_download_speed
self.statusbar.config_value_changed_dict['max_upload_speed'] = self.statusbar._on_max_upload_speed
# Remove statusbar item.
self.statusbar.remove_item(self.status_item)
del self.status_item
component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs)
component.get("PluginManager").deregister_hook("on_show_prefs", self.on_show_prefs)
component.get('PluginManager').deregister_hook('on_apply_prefs', self.on_apply_prefs)
component.get('PluginManager').deregister_hook('on_show_prefs', self.on_show_prefs)
def on_apply_prefs(self):
log.debug("applying prefs for Scheduler")
log.debug('applying prefs for Scheduler')
config = {}
config["low_down"] = self.spin_download.get_value()
config["low_up"] = self.spin_upload.get_value()
config["low_active"] = self.spin_active.get_value_as_int()
config["low_active_down"] = self.spin_active_down.get_value_as_int()
config["low_active_up"] = self.spin_active_up.get_value_as_int()
config["button_state"] = self.scheduler_select.button_state
config['low_down'] = self.spin_download.get_value()
config['low_up'] = self.spin_upload.get_value()
config['low_active'] = self.spin_active.get_value_as_int()
config['low_active_down'] = self.spin_active_down.get_value_as_int()
config['low_active_up'] = self.spin_active_up.get_value_as_int()
config['button_state'] = self.scheduler_select.button_state
client.scheduler.set_config(config)
def on_show_prefs(self):
def on_get_config(config):
log.debug("config: %s", config)
self.scheduler_select.set_button_state(config["button_state"])
self.spin_download.set_value(config["low_down"])
self.spin_upload.set_value(config["low_up"])
self.spin_active.set_value(config["low_active"])
self.spin_active_down.set_value(config["low_active_down"])
self.spin_active_up.set_value(config["low_active_up"])
log.debug('config: %s', config)
self.scheduler_select.set_button_state(config['button_state'])
self.spin_download.set_value(config['low_down'])
self.spin_upload.set_value(config['low_up'])
self.spin_active.set_value(config['low_active'])
self.spin_active_down.set_value(config['low_active_down'])
self.spin_active_up.set_value(config['low_active_up'])
client.scheduler.get_config().addCallback(on_get_config)
def on_scheduler_event(self, state):
self.state = state
self.status_item.set_image_from_file(get_resource(self.state.lower() + ".png"))
if self.state == "Yellow":
self.status_item.set_image_from_file(get_resource(self.state.lower() + '.png'))
if self.state == 'Yellow':
# Prevent func calls in Statusbar if the config changes.
self.statusbar.config_value_changed_dict.pop("max_download_speed", None)
self.statusbar.config_value_changed_dict.pop("max_upload_speed", None)
self.statusbar.config_value_changed_dict.pop('max_download_speed', None)
self.statusbar.config_value_changed_dict.pop('max_upload_speed', None)
try:
self.statusbar._on_max_download_speed(self.spin_download.get_value())
self.statusbar._on_max_upload_speed(self.spin_upload.get_value())
@ -210,20 +210,20 @@ class GtkUI(GtkPluginBase):
# Skip error due to Plugin being enabled before statusbar items created on startup.
pass
else:
self.statusbar.config_value_changed_dict["max_download_speed"] = self.statusbar._on_max_download_speed
self.statusbar.config_value_changed_dict["max_upload_speed"] = self.statusbar._on_max_upload_speed
self.statusbar.config_value_changed_dict['max_download_speed'] = self.statusbar._on_max_download_speed
self.statusbar.config_value_changed_dict['max_upload_speed'] = self.statusbar._on_max_upload_speed
def update_config_values(config):
try:
self.statusbar._on_max_download_speed(config["max_download_speed"])
self.statusbar._on_max_upload_speed(config["max_upload_speed"])
self.statusbar._on_max_download_speed(config['max_download_speed'])
self.statusbar._on_max_upload_speed(config['max_upload_speed'])
except AttributeError:
# Skip error due to Plugin being enabled before statusbar items created on startup.
pass
client.core.get_config_values(["max_download_speed", "max_upload_speed"]).addCallback(update_config_values)
client.core.get_config_values(['max_download_speed', 'max_upload_speed']).addCallback(update_config_values)
def on_status_item_clicked(self, widget, event):
component.get("Preferences").show("Scheduler")
component.get('Preferences').show('Scheduler')
# Configuration dialog
def create_prefs_page(self):
@ -240,7 +240,7 @@ class GtkUI(GtkPluginBase):
hbox.pack_start(self.scheduler_select, True, True)
frame = gtk.Frame()
label = gtk.Label()
label.set_markup("<b>Schedule</b>")
label.set_markup('<b>Schedule</b>')
frame.set_label_widget(label)
frame.set_shadow_type(gtk.SHADOW_NONE)
frame.add(hbox)
@ -250,7 +250,7 @@ class GtkUI(GtkPluginBase):
table = gtk.Table(3, 4)
label = gtk.Label(_("Download Limit:"))
label = gtk.Label(_('Download Limit:'))
label.set_alignment(0.0, 0.6)
table.attach(label, 0, 1, 0, 1, gtk.FILL)
self.spin_download = gtk.SpinButton()
@ -259,7 +259,7 @@ class GtkUI(GtkPluginBase):
self.spin_download.set_increments(1, 10)
table.attach(self.spin_download, 1, 2, 0, 1, gtk.FILL)
label = gtk.Label(_("Upload Limit:"))
label = gtk.Label(_('Upload Limit:'))
label.set_alignment(0.0, 0.6)
table.attach(label, 0, 1, 1, 2, gtk.FILL)
self.spin_upload = gtk.SpinButton()
@ -268,7 +268,7 @@ class GtkUI(GtkPluginBase):
self.spin_upload.set_increments(1, 10)
table.attach(self.spin_upload, 1, 2, 1, 2, gtk.FILL)
label = gtk.Label(_("Active Torrents:"))
label = gtk.Label(_('Active Torrents:'))
label.set_alignment(0.0, 0.6)
table.attach(label, 2, 3, 0, 1, gtk.FILL)
self.spin_active = gtk.SpinButton()
@ -277,7 +277,7 @@ class GtkUI(GtkPluginBase):
self.spin_active.set_increments(1, 10)
table.attach(self.spin_active, 3, 4, 0, 1, gtk.FILL)
label = gtk.Label(_("Active Downloading:"))
label = gtk.Label(_('Active Downloading:'))
label.set_alignment(0.0, 0.6)
table.attach(label, 2, 3, 1, 2, gtk.FILL)
self.spin_active_down = gtk.SpinButton()
@ -286,7 +286,7 @@ class GtkUI(GtkPluginBase):
self.spin_active_down.set_increments(1, 10)
table.attach(self.spin_active_down, 3, 4, 1, 2, gtk.FILL)
label = gtk.Label(_("Active Seeding:"))
label = gtk.Label(_('Active Seeding:'))
label.set_alignment(0.0, 0.6)
table.attach(label, 2, 3, 2, 3, gtk.FILL)
self.spin_active_up = gtk.SpinButton()
@ -296,16 +296,16 @@ class GtkUI(GtkPluginBase):
table.attach(self.spin_active_up, 3, 4, 2, 3, gtk.FILL)
eventbox = gtk.EventBox()
eventbox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#EDD400"))
eventbox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#EDD400'))
eventbox.add(table)
frame = gtk.Frame()
label = gtk.Label()
label.set_markup(_("<b>Slow Settings</b>"))
label.set_markup(_('<b>Slow Settings</b>'))
frame.set_label_widget(label)
frame.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#CDB400"))
frame.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#CDB400'))
frame.set_border_width(2)
frame.add(eventbox)
vbox.pack_start(frame, False, False)
vbox.show_all()
component.get("Preferences").add_page(_("Scheduler"), vbox)
component.get('Preferences').add_page(_('Scheduler'), vbox)

View File

@ -23,5 +23,5 @@ log = logging.getLogger(__name__)
class WebUI(WebPluginBase):
scripts = [get_resource("scheduler.js")]
scripts = [get_resource('scheduler.js')]
debug_scripts = scripts

View File

@ -13,15 +13,15 @@
from setuptools import find_packages, setup
__plugin_name__ = "Scheduler"
__author__ = "Andrew Resch"
__author_email__ = "andrewresch@gmail.com"
__version__ = "0.2"
__url__ = "http://deluge-torrent.org"
__license__ = "GPLv3"
__description__ = "Schedule limits on a per-hour per-day basis."
__plugin_name__ = 'Scheduler'
__author__ = 'Andrew Resch'
__author_email__ = 'andrewresch@gmail.com'
__version__ = '0.2'
__url__ = 'http://deluge-torrent.org'
__license__ = 'GPLv3'
__description__ = 'Schedule limits on a per-hour per-day basis.'
__long_description__ = """"""
__pkg_data__ = {"deluge.plugins." + __plugin_name__.lower(): ["template/*", "data/*"]}
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ['template/*', 'data/*']}
setup(
name=__plugin_name__,
@ -34,7 +34,7 @@ setup(
long_description=__long_description__ if __long_description__ else __description__,
packages=find_packages(),
namespace_packages=["deluge", "deluge.plugins"],
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
entry_points="""

View File

@ -13,4 +13,4 @@ import pkg_resources
def get_resource(filename):
return pkg_resources.resource_filename("deluge.plugins.stats", os.path.join("data", filename))
return pkg_resources.resource_filename('deluge.plugins.stats', os.path.join('data', filename))

View File

@ -23,17 +23,17 @@ from deluge.core.rpcserver import export
from deluge.plugins.pluginbase import CorePluginBase
DEFAULT_PREFS = {
"test": "NiNiNi",
"update_interval": 1, # 2 seconds.
"length": 150, # 2 seconds * 150 --> 5 minutes.
'test': 'NiNiNi',
'update_interval': 1, # 2 seconds.
'length': 150, # 2 seconds * 150 --> 5 minutes.
}
DEFAULT_TOTALS = {
"total_upload": 0,
"total_download": 0,
"total_payload_upload": 0,
"total_payload_download": 0,
"stats": {}
'total_upload': 0,
'total_download': 0,
'total_payload_upload': 0,
'total_payload_download': 0,
'stats': {}
}
log = logging.getLogger(__name__)
@ -57,8 +57,8 @@ class Core(CorePluginBase):
totals = {} # class var to catch only updating this once per session in enable.
def enable(self):
log.debug("Stats plugin enabled")
self.core = component.get("Core")
log.debug('Stats plugin enabled')
self.core = component.get('Core')
self.stats = {}
self.count = {}
self.intervals = [1, 5, 30, 300]
@ -70,12 +70,12 @@ class Core(CorePluginBase):
self.last_update[i] = t
self.count[i] = 0
self.config = configmanager.ConfigManager("stats.conf", DEFAULT_PREFS)
self.saved_stats = configmanager.ConfigManager("stats.totals", DEFAULT_TOTALS)
self.config = configmanager.ConfigManager('stats.conf', DEFAULT_PREFS)
self.saved_stats = configmanager.ConfigManager('stats.totals', DEFAULT_TOTALS)
if self.totals == {}:
self.totals.update(self.saved_stats.config)
self.length = self.config["length"]
self.length = self.config['length']
# self.stats = get_key(self.saved_stats, "stats") or {}
self.stats_keys = []
@ -92,7 +92,7 @@ class Core(CorePluginBase):
self.update_stats()
self.update_timer = LoopingCall(self.update_stats)
self.update_timer.start(self.config["update_interval"])
self.update_timer.start(self.config['update_interval'])
self.save_timer = LoopingCall(self.save_stats)
self.save_timer.start(60)
@ -124,10 +124,10 @@ class Core(CorePluginBase):
stats.update(self.core.get_session_status([key]))
except AttributeError:
pass
stats["num_connections"] = stats["num_peers"]
stats.update(self.core.get_config_values(["max_download",
"max_upload",
"max_num_connections"]))
stats['num_connections'] = stats['num_peers']
stats.update(self.core.get_config_values(['max_download',
'max_upload',
'max_num_connections']))
# status = self.core.session.status()
# for stat in dir(status):
# if not stat.startswith('_') and stat not in stats:
@ -166,16 +166,16 @@ class Core(CorePluginBase):
update_interval(300, 30, 10)
except Exception as ex:
log.error("Stats update error %s", ex)
log.error('Stats update error %s', ex)
return True
def save_stats(self):
try:
self.saved_stats["stats"] = self.stats
self.saved_stats['stats'] = self.stats
self.saved_stats.config.update(self.get_totals())
self.saved_stats.save()
except Exception as ex:
log.error("Stats save error %s", ex)
log.error('Stats save error %s', ex)
return True
# export:
@ -189,9 +189,9 @@ class Core(CorePluginBase):
if key in self.stats[interval]:
stats_dict[key] = self.stats[interval][key]
stats_dict["_last_update"] = self.last_update[interval]
stats_dict["_length"] = self.config["length"]
stats_dict["_update_interval"] = interval
stats_dict['_last_update'] = self.last_update[interval]
stats_dict['_length'] = self.config['length']
stats_dict['_update_interval'] = interval
return stats_dict
@export
@ -206,25 +206,25 @@ class Core(CorePluginBase):
def get_session_totals(self):
status = self.core.session.status()
return {
"total_upload": status.total_upload,
"total_download": status.total_download,
"total_payload_upload": status.total_payload_upload,
"total_payload_download": status.total_payload_download
'total_upload': status.total_upload,
'total_download': status.total_download,
'total_payload_upload': status.total_payload_upload,
'total_payload_download': status.total_payload_download
}
@export
def set_config(self, config):
"sets the config dictionary"
'sets the config dictionary'
for key in config.keys():
self.config[key] = config[key]
self.config.save()
@export
def get_config(self):
"returns the config dictionary"
'returns the config dictionary'
return self.config.config
@export
def get_intervals(self):
"Returns the available resolutions"
'Returns the available resolutions'
return self.intervals

View File

@ -88,12 +88,12 @@ class Graph(object):
}
def set_stats(self, stats):
self.last_update = stats["_last_update"]
del stats["_last_update"]
self.length = stats["_length"]
del stats["_length"]
self.interval = stats["_update_interval"]
del stats["_update_interval"]
self.last_update = stats['_last_update']
del stats['_last_update']
self.length = stats['_length']
del stats['_length']
self.interval = stats['_update_interval']
del stats['_update_interval']
self.stats = stats
return

View File

@ -36,17 +36,17 @@ DEFAULT_CONF = {
'version': 1,
'colors': {
'bandwidth_graph': {
'upload_rate': str(gtk.gdk.Color("blue")),
'download_rate': str(gtk.gdk.Color("green")),
'upload_rate': str(gtk.gdk.Color('blue')),
'download_rate': str(gtk.gdk.Color('green')),
},
'connections_graph': {
'dht_nodes': str(gtk.gdk.Color("orange")),
'dht_cache_nodes': str(gtk.gdk.Color("blue")),
'dht_torrents': str(gtk.gdk.Color("green")),
'num_connections': str(gtk.gdk.Color("darkred")),
'dht_nodes': str(gtk.gdk.Color('orange')),
'dht_cache_nodes': str(gtk.gdk.Color('blue')),
'dht_torrents': str(gtk.gdk.Color('green')),
'num_connections': str(gtk.gdk.Color('darkred')),
},
'seeds_graph': {
'num_peers': str(gtk.gdk.Color("blue")),
'num_peers': str(gtk.gdk.Color('blue')),
}}}
@ -54,13 +54,13 @@ def neat_time(column, cell, model, data):
"""Render seconds as seconds or minutes with label"""
seconds = model.get_value(data, 0)
if seconds > 60:
text = "%d %s" % (seconds // 60, _("minutes"))
text = '%d %s' % (seconds // 60, _('minutes'))
elif seconds == 60:
text = _("1 minute")
text = _('1 minute')
elif seconds == 1:
text = _("1 second")
text = _('1 second')
else:
text = "%d %s" % (seconds, _("seconds"))
text = '%d %s' % (seconds, _('seconds'))
cell.set_property('text', text)
return
@ -114,7 +114,7 @@ class GraphsTab(Tab):
cell = gtk.CellRendererText()
self.intervals_combo.pack_start(cell, True)
self.intervals_combo.set_cell_data_func(cell, neat_time)
self.intervals_combo.connect("changed", self._on_selected_interval_changed)
self.intervals_combo.connect('changed', self._on_selected_interval_changed)
self.update_intervals()
def graph_expose(self, widget, event):
@ -145,7 +145,7 @@ class GraphsTab(Tab):
client.stats.get_intervals().addCallback(self._on_intervals_changed)
def select_bandwidth_graph(self):
log.debug("Selecting bandwidth graph")
log.debug('Selecting bandwidth graph')
self.graph_widget = self.bandwidth_graph
self.graph = Graph()
colors = self.colors['bandwidth_graph']
@ -157,7 +157,7 @@ class GraphsTab(Tab):
formatter_scale=size_formatter_scale)
def select_connections_graph(self):
log.debug("Selecting connections graph")
log.debug('Selecting connections graph')
self.graph_widget = self.connections_graph
g = Graph()
self.graph = g
@ -169,7 +169,7 @@ class GraphsTab(Tab):
g.set_left_axis(formatter=int_str, min=10)
def select_seeds_graph(self):
log.debug("Selecting connections graph")
log.debug('Selecting connections graph')
self.graph_widget = self.seeds_graph
self.graph = Graph()
colors = self.colors['seeds_graph']
@ -219,32 +219,32 @@ class GraphsTab(Tab):
class GtkUI(GtkPluginBase):
def enable(self):
log.debug("Stats plugin enable called")
self.config = deluge.configmanager.ConfigManager("stats.gtkui.conf", DEFAULT_CONF)
self.glade = XML(common.get_resource("config.glade"))
component.get("Preferences").add_page("Stats", self.glade.get_widget("prefs_box"))
component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs)
component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs)
log.debug('Stats plugin enable called')
self.config = deluge.configmanager.ConfigManager('stats.gtkui.conf', DEFAULT_CONF)
self.glade = XML(common.get_resource('config.glade'))
component.get('Preferences').add_page('Stats', self.glade.get_widget('prefs_box'))
component.get('PluginManager').register_hook('on_apply_prefs', self.on_apply_prefs)
component.get('PluginManager').register_hook('on_show_prefs', self.on_show_prefs)
self.on_show_prefs()
self.graphs_tab = GraphsTab(XML(common.get_resource("tabs.glade")), self.config['colors'])
self.graphs_tab = GraphsTab(XML(common.get_resource('tabs.glade')), self.config['colors'])
self.torrent_details = component.get('TorrentDetails')
self.torrent_details.add_tab(self.graphs_tab)
def disable(self):
component.get("Preferences").remove_page("Stats")
component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs)
component.get("PluginManager").deregister_hook("on_show_prefs", self.on_show_prefs)
component.get('Preferences').remove_page('Stats')
component.get('PluginManager').deregister_hook('on_apply_prefs', self.on_apply_prefs)
component.get('PluginManager').deregister_hook('on_show_prefs', self.on_show_prefs)
self.torrent_details.remove_tab(self.graphs_tab.get_name())
def on_apply_prefs(self):
log.debug("applying prefs for Stats")
log.debug('applying prefs for Stats')
gtkconf = {}
for graph, colors in self.config['colors'].items():
gtkconf[graph] = {}
for value, color in colors.items():
try:
color_btn = self.glade.get_widget("%s_%s_color" % (graph, value))
color_btn = self.glade.get_widget('%s_%s_color' % (graph, value))
gtkconf[graph][value] = str(color_btn.get_color())
except Exception:
gtkconf[graph][value] = DEFAULT_CONF['colors'][graph][value]
@ -258,12 +258,12 @@ class GtkUI(GtkPluginBase):
for graph, colors in self.config['colors'].items():
for value, color in colors.items():
try:
color_btn = self.glade.get_widget("%s_%s_color" % (graph, value))
color_btn = self.glade.get_widget('%s_%s_color' % (graph, value))
color_btn.set_color(gtk.gdk.Color(color))
except Exception:
log.debug("Unable to set %s %s %s", graph, value, color)
log.debug('Unable to set %s %s %s', graph, value, color)
client.stats.get_config().addCallback(self.cb_get_config)
def cb_get_config(self, config):
"callback for on show_prefs"
'callback for on show_prefs'
pass

View File

@ -21,9 +21,9 @@ def print_totals(totals):
for name, value in totals.iteritems():
print(name, fsize(value))
print("overhead:")
print("up:", fsize(totals["total_upload"] - totals["total_payload_upload"]))
print("down:", fsize(totals["total_download"] - totals["total_payload_download"]))
print('overhead:')
print('up:', fsize(totals['total_upload'] - totals['total_payload_upload']))
print('down:', fsize(totals['total_download'] - totals['total_payload_download']))
class StatsTestCase(BaseTestCase):
@ -32,7 +32,7 @@ class StatsTestCase(BaseTestCase):
defer.setDebugging(True)
tests_common.set_tmp_config_dir()
client.start_standalone()
client.core.enable_plugin("Stats")
client.core.enable_plugin('Stats')
return component.start()
def tear_down(self):
@ -42,8 +42,8 @@ class StatsTestCase(BaseTestCase):
@defer.inlineCallbacks
def test_client_totals(self):
plugins = yield client.core.get_available_plugins()
if "Stats" not in plugins:
raise unittest.SkipTest("WebUi plugin not available for testing")
if 'Stats' not in plugins:
raise unittest.SkipTest('WebUi plugin not available for testing')
totals = yield client.stats.get_totals()
self.assertEquals(totals['total_upload'], 0)
@ -55,8 +55,8 @@ class StatsTestCase(BaseTestCase):
@defer.inlineCallbacks
def test_session_totals(self):
plugins = yield client.core.get_available_plugins()
if "Stats" not in plugins:
raise unittest.SkipTest("WebUi plugin not available for testing")
if 'Stats' not in plugins:
raise unittest.SkipTest('WebUi plugin not available for testing')
totals = yield client.stats.get_session_totals()
self.assertEquals(totals['total_upload'], 0)
@ -82,7 +82,7 @@ class StatsTestCase(BaseTestCase):
from deluge.ui.gtkui.torrentview import TorrentView
from deluge.plugins.Stats.deluge.plugins.stats import graph, gtkui
ConfigManager("gtkui.conf", defaults=DEFAULT_PREFS)
ConfigManager('gtkui.conf', defaults=DEFAULT_PREFS)
self.plugins = PluginManager()
MainWindow()
@ -97,7 +97,7 @@ class StatsTestCase(BaseTestCase):
def write(self, data):
self.data.append(data)
stats_gtkui = gtkui.GtkUI("test_stats")
stats_gtkui = gtkui.GtkUI('test_stats')
stats_gtkui.enable()
yield stats_gtkui.graphs_tab.update()
@ -109,6 +109,6 @@ class StatsTestCase(BaseTestCase):
surface = g.draw(900, 150)
file_like = FakeFile()
surface.write_to_png(file_like)
data = "".join(file_like.data)
with open("file_like.png", "wb") as _file:
data = ''.join(file_like.data)
with open('file_like.png', 'wb') as _file:
_file.write(data)

View File

@ -22,13 +22,13 @@ log = logging.getLogger(__name__)
class WebUI(WebPluginBase):
scripts = [get_resource("stats.js")]
scripts = [get_resource('stats.js')]
# The enable and disable methods are not scrictly required on the WebUI
# plugins. They are only here if you need to register images/stylesheets
# with the webserver.
def enable(self):
log.debug("Stats Web plugin enabled!")
log.debug('Stats Web plugin enabled!')
def disable(self):
log.debug("Stats Web plugin disabled!")
log.debug('Stats Web plugin disabled!')

View File

@ -14,18 +14,18 @@
from setuptools import find_packages, setup
__plugin_name__ = "Stats"
__author__ = "Ian Martin"
__author_email__ = "ianmartin@cantab.net"
__version__ = "0.3.2"
__url__ = "http://deluge-torrent.org"
__license__ = "GPLv3"
__description__ = "Display stats graphs"
__plugin_name__ = 'Stats'
__author__ = 'Ian Martin'
__author_email__ = 'ianmartin@cantab.net'
__version__ = '0.3.2'
__url__ = 'http://deluge-torrent.org'
__license__ = 'GPLv3'
__description__ = 'Display stats graphs'
__long_description__ = """
Records lots of extra stats
and produces time series
graphs"""
__pkg_data__ = {"deluge.plugins." + __plugin_name__.lower(): ["template/*", "data/*"]}
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ['template/*', 'data/*']}
setup(
name=__plugin_name__,
@ -38,7 +38,7 @@ setup(
long_description=__long_description__,
packages=find_packages(),
namespace_packages=["deluge", "deluge.plugins"],
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
entry_points="""

View File

@ -16,5 +16,5 @@
def get_resource(filename):
import os.path
import pkg_resources
return pkg_resources.resource_filename("deluge.plugins.toggle",
os.path.join("data", filename))
return pkg_resources.resource_filename('deluge.plugins.toggle',
os.path.join('data', filename))

View File

@ -26,7 +26,7 @@ DEFAULT_PREFS = {
class Core(CorePluginBase):
def enable(self):
self.core = component.get("Core")
self.core = component.get('Core')
def disable(self):
pass

View File

@ -24,25 +24,25 @@ log = logging.getLogger(__name__)
class GtkUI(GtkPluginBase):
def enable(self):
self.core = client.toggle
self.plugin = component.get("PluginManager")
self.plugin = component.get('PluginManager')
self.separator = self.plugin.add_toolbar_separator()
self.button = self.plugin.add_toolbar_button(self._on_button_clicked, label="Pause Session",
stock="gtk-media-pause", tooltip="Pause the session")
self.button = self.plugin.add_toolbar_button(self._on_button_clicked, label='Pause Session',
stock='gtk-media-pause', tooltip='Pause the session')
def disable(self):
component.get("PluginManager").remove_toolbar_button(self.button)
component.get("PluginManager").remove_toolbar_button(self.separator)
component.get('PluginManager').remove_toolbar_button(self.button)
component.get('PluginManager').remove_toolbar_button(self.separator)
def update(self):
def _on_get_status(paused):
if paused:
self.button.set_label("Resume Session")
self.button.set_tooltip_text("Resume the session")
self.button.set_stock_id("gtk-media-play")
self.button.set_label('Resume Session')
self.button.set_tooltip_text('Resume the session')
self.button.set_stock_id('gtk-media-play')
else:
self.button.set_label("Pause Session")
self.button.set_tooltip_text("Pause the session")
self.button.set_stock_id("gtk-media-pause")
self.button.set_label('Pause Session')
self.button.set_tooltip_text('Pause the session')
self.button.set_stock_id('gtk-media-pause')
self.core.get_status().addCallback(_on_get_status)
def _on_button_clicked(self, widget):

View File

@ -23,7 +23,7 @@ log = logging.getLogger(__name__)
class WebUI(WebPluginBase):
scripts = [get_resource("toggle.js")]
scripts = [get_resource('toggle.js')]
def enable(self):
pass

View File

@ -14,15 +14,15 @@
from setuptools import find_packages, setup
__plugin_name__ = "Toggle"
__author__ = "John Garland"
__author_email__ = "johnnybg+deluge@gmail.com"
__version__ = "0.3"
__url__ = "http://deluge-torrent.org"
__license__ = "GPLv3"
__description__ = "Toggles the session"
__plugin_name__ = 'Toggle'
__author__ = 'John Garland'
__author_email__ = 'johnnybg+deluge@gmail.com'
__version__ = '0.3'
__url__ = 'http://deluge-torrent.org'
__license__ = 'GPLv3'
__description__ = 'Toggles the session'
__long_description__ = """"""
__pkg_data__ = {"deluge.plugins." + __plugin_name__.lower(): ["template/*", "data/*"]}
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ['template/*', 'data/*']}
setup(
name=__plugin_name__,
@ -35,7 +35,7 @@ setup(
long_description=__long_description__ if __long_description__ else __description__,
packages=find_packages(),
namespace_packages=["deluge", "deluge.plugins"],
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
entry_points="""

View File

@ -15,5 +15,5 @@
def get_resource(filename):
import os.path
import pkg_resources
return pkg_resources.resource_filename("deluge.plugins.webui",
os.path.join("data", filename))
return pkg_resources.resource_filename('deluge.plugins.webui',
os.path.join('data', filename))

View File

@ -24,9 +24,9 @@ from deluge.plugins.pluginbase import CorePluginBase
log = logging.getLogger(__name__)
DEFAULT_PREFS = {
"enabled": False,
"ssl": False,
"port": 8112
'enabled': False,
'ssl': False,
'port': 8112
}
@ -34,7 +34,7 @@ class Core(CorePluginBase):
server = None
def enable(self):
self.config = configmanager.ConfigManager("web_plugin.conf", DEFAULT_PREFS)
self.config = configmanager.ConfigManager('web_plugin.conf', DEFAULT_PREFS)
if self.config['enabled']:
self.start_server()
@ -63,16 +63,16 @@ class Core(CorePluginBase):
return False
try:
self.server = component.get("DelugeWeb")
self.server = component.get('DelugeWeb')
except KeyError:
self.server = server.DelugeWeb(daemon=False)
self.server.port = self.config["port"]
self.server.https = self.config["ssl"]
self.server.port = self.config['port']
self.server.https = self.config['ssl']
try:
self.server.start()
except CannotListenError as ex:
log.warn("Failed to start WebUI server: %s", ex)
log.warn('Failed to start WebUI server: %s', ex)
raise
return True
@ -86,14 +86,14 @@ class Core(CorePluginBase):
@export
def set_config(self, config):
"sets the config dictionary"
'sets the config dictionary'
action = None
if "enabled" in config:
if config["enabled"] != self.config["enabled"]:
action = config["enabled"] and 'start' or 'stop'
if 'enabled' in config:
if config['enabled'] != self.config['enabled']:
action = config['enabled'] and 'start' or 'stop'
if "ssl" in config:
if 'ssl' in config:
if not action:
action = 'restart'
@ -110,5 +110,5 @@ class Core(CorePluginBase):
@export
def get_config(self):
"returns the config dictionary"
'returns the config dictionary'
return self.config.config

View File

@ -27,27 +27,27 @@ log = logging.getLogger(__name__)
class GtkUI(GtkPluginBase):
def enable(self):
self.glade = gtk.glade.XML(get_resource("config.glade"))
self.glade = gtk.glade.XML(get_resource('config.glade'))
component.get("Preferences").add_page(_("WebUi"), self.glade.get_widget("prefs_box"))
component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs)
component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs)
component.get('Preferences').add_page(_('WebUi'), self.glade.get_widget('prefs_box'))
component.get('PluginManager').register_hook('on_apply_prefs', self.on_apply_prefs)
component.get('PluginManager').register_hook('on_show_prefs', self.on_show_prefs)
client.webui.get_config().addCallback(self.cb_get_config)
client.webui.got_deluge_web().addCallback(self.cb_chk_deluge_web)
def disable(self):
component.get("Preferences").remove_page(_("WebUi"))
component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs)
component.get("PluginManager").deregister_hook("on_show_prefs", self.on_show_prefs)
component.get('Preferences').remove_page(_('WebUi'))
component.get('PluginManager').deregister_hook('on_apply_prefs', self.on_apply_prefs)
component.get('PluginManager').deregister_hook('on_show_prefs', self.on_show_prefs)
def on_apply_prefs(self):
if not self.have_web:
return
log.debug("applying prefs for WebUi")
log.debug('applying prefs for WebUi')
config = {
"enabled": self.glade.get_widget("enabled_checkbutton").get_active(),
"ssl": self.glade.get_widget("ssl_checkbutton").get_active(),
"port": self.glade.get_widget("port_spinbutton").get_value_as_int()
'enabled': self.glade.get_widget('enabled_checkbutton').get_active(),
'ssl': self.glade.get_widget('ssl_checkbutton').get_active(),
'port': self.glade.get_widget('port_spinbutton').get_value_as_int()
}
client.webui.set_config(config)
@ -55,26 +55,26 @@ class GtkUI(GtkPluginBase):
client.webui.get_config().addCallback(self.cb_get_config)
def cb_get_config(self, config):
"callback for on show_prefs"
self.glade.get_widget("enabled_checkbutton").set_active(config["enabled"])
self.glade.get_widget("ssl_checkbutton").set_active(config["ssl"])
self.glade.get_widget("port_spinbutton").set_value(config["port"])
'callback for on show_prefs'
self.glade.get_widget('enabled_checkbutton').set_active(config['enabled'])
self.glade.get_widget('ssl_checkbutton').set_active(config['ssl'])
self.glade.get_widget('port_spinbutton').set_value(config['port'])
def cb_chk_deluge_web(self, have_web):
self.have_web = have_web
if have_web:
return
self.glade.get_widget("settings_vbox").set_sensitive(False)
self.glade.get_widget('settings_vbox').set_sensitive(False)
vbox = self.glade.get_widget("prefs_box")
vbox = self.glade.get_widget('prefs_box')
hbox = gtk.HBox()
icon = gtk.image_new_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_SMALL_TOOLBAR)
icon.set_padding(5, 5)
hbox.pack_start(icon, False, False)
label = gtk.Label(_("The Deluge web interface is not installed, "
"please install the\ninterface and try again"))
label = gtk.Label(_('The Deluge web interface is not installed, '
'please install the\ninterface and try again'))
label.set_alignment(0, 0.5)
label.set_padding(5, 5)
hbox.pack_start(label)

View File

@ -34,14 +34,14 @@ class WebUIPluginTestCase(BaseTestCase):
return component.shutdown().addCallback(on_shutdown)
def test_enable_webui(self):
if "WebUi" not in self.core.get_available_plugins():
raise unittest.SkipTest("WebUi plugin not available for testing")
if 'WebUi' not in self.core.get_available_plugins():
raise unittest.SkipTest('WebUi plugin not available for testing')
d = self.core.enable_plugin("WebUi")
d = self.core.enable_plugin('WebUi')
def result_cb(result):
if "WebUi" not in self.core.get_enabled_plugins():
self.fail("Failed to enable WebUi plugin")
if 'WebUi' not in self.core.get_enabled_plugins():
self.fail('Failed to enable WebUi plugin')
self.assertTrue(result)
d.addBoth(result_cb)

View File

@ -13,15 +13,15 @@
from setuptools import find_packages, setup
__plugin_name__ = "WebUi"
__author__ = "Damien Churchill"
__author_email__ = "damoxc@gmail.com"
__version__ = "0.1"
__url__ = "http://deluge-torrent.org"
__license__ = "GPLv3"
__description__ = "Allows starting the web interface within the daemon."
__plugin_name__ = 'WebUi'
__author__ = 'Damien Churchill'
__author_email__ = 'damoxc@gmail.com'
__version__ = '0.1'
__url__ = 'http://deluge-torrent.org'
__license__ = 'GPLv3'
__description__ = 'Allows starting the web interface within the daemon.'
__long_description__ = """"""
__pkg_data__ = {"deluge.plugins." + __plugin_name__.lower(): ["template/*", "data/*"]}
__pkg_data__ = {'deluge.plugins.' + __plugin_name__.lower(): ['template/*', 'data/*']}
setup(
name=__plugin_name__,
@ -34,7 +34,7 @@ setup(
long_description=__long_description__ if __long_description__ else __description__,
packages=find_packages(),
namespace_packages=["deluge", "deluge.plugins"],
namespace_packages=['deluge', 'deluge.plugins'],
package_data=__pkg_data__,
entry_points="""

View File

@ -22,22 +22,22 @@ class PluginBase(component.Component):
super(PluginBase, self).__init__(name, self.update_interval)
def enable(self):
raise NotImplementedError("Need to define an enable method!")
raise NotImplementedError('Need to define an enable method!')
def disable(self):
raise NotImplementedError("Need to define a disable method!")
raise NotImplementedError('Need to define a disable method!')
class CorePluginBase(PluginBase):
def __init__(self, plugin_name):
super(CorePluginBase, self).__init__("CorePlugin." + plugin_name)
super(CorePluginBase, self).__init__('CorePlugin.' + plugin_name)
# Register RPC methods
component.get("RPCServer").register_object(self, plugin_name.lower())
log.debug("CorePlugin initialized..")
component.get('RPCServer').register_object(self, plugin_name.lower())
log.debug('CorePlugin initialized..')
def __del__(self):
component.get("RPCServer").deregister_object(self)
component.get('RPCServer').deregister_object(self)
def enable(self):
super(CorePluginBase, self).enable()
@ -49,8 +49,8 @@ class CorePluginBase(PluginBase):
class GtkPluginBase(PluginBase):
def __init__(self, plugin_name):
super(GtkPluginBase, self).__init__("GtkPlugin." + plugin_name)
log.debug("GtkPlugin initialized..")
super(GtkPluginBase, self).__init__('GtkPlugin.' + plugin_name)
log.debug('GtkPlugin initialized..')
def enable(self):
super(GtkPluginBase, self).enable()
@ -68,11 +68,11 @@ class WebPluginBase(PluginBase):
debug_stylesheets = []
def __init__(self, plugin_name):
super(WebPluginBase, self).__init__("WebPlugin." + plugin_name)
super(WebPluginBase, self).__init__('WebPlugin.' + plugin_name)
# Register JSON rpc methods
component.get("JSON").register_object(self, plugin_name.lower())
log.debug("WebPlugin initialized..")
component.get('JSON').register_object(self, plugin_name.lower())
log.debug('WebPlugin initialized..')
def enable(self):
pass

View File

@ -62,7 +62,7 @@ import struct
import sys
from threading import Lock
__version__ = ("Python", 1, 0, 4)
__version__ = ('Python', 1, 0, 4)
__all__ = ['dumps', 'loads']
py3 = sys.version_info[0] >= 3
@ -244,7 +244,7 @@ def make_fixed_length_string_decoders():
def f(x, f):
s = x[f + 1:f + 1 + slen]
if _decode_utf8:
s = s.decode("utf8")
s = s.decode('utf8')
return (s, f + 1 + slen)
return f
for i in range(STR_FIXED_COUNT):
@ -324,7 +324,7 @@ def encode_int(x, r):
else:
s = str(x)
if py3:
s = bytes(s, "ascii")
s = bytes(s, 'ascii')
if len(s) >= MAX_INT_LENGTH:
raise ValueError('overflow')
@ -353,12 +353,12 @@ def encode_string(x, r):
else:
s = str(len(x))
if py3:
s = bytes(s, "ascii")
s = bytes(s, 'ascii')
r.extend((s, b':', x))
def encode_unicode(x, r):
encode_string(x.encode("utf8"), r)
encode_string(x.encode('utf8'), r)
def encode_list(x, r):
@ -447,7 +447,7 @@ def test():
assert 1e-10 < abs(loads(dumps(1.1)) - 1.1) < 1e-6
assert 1e-10 < abs(loads(dumps(1.1, 32)) - 1.1) < 1e-6
assert abs(loads(dumps(1.1, 64)) - 1.1) < 1e-12
assert loads(dumps("Hello World!!"), decode_utf8=True)
assert loads(dumps('Hello World!!'), decode_utf8=True)
try:
import psyco
psyco.bind(dumps)

View File

@ -16,15 +16,15 @@ from datetime import datetime
import deluge.common
parser = ArgumentParser()
parser.add_argument("-n", "--name", metavar="<plugin name>", required=True, help="Plugin name")
parser.add_argument("-m", "--module-name", metavar="<module name>", help="Module name")
parser.add_argument("-p", "--basepath", metavar="<path>", required=True, help="Base path")
parser.add_argument("-a", "--author-name", metavar="<author name>", required=True,
help="Author name,for the GPL header")
parser.add_argument("-e", "--author-email", metavar="<author email>", required=True,
help="Author email,for the GPL header")
parser.add_argument("-u", "--url", metavar="<URL>", help="Homepage URL")
parser.add_argument("-c", "--config", metavar="<Config dir>", dest="configdir", help="Location of deluge configuration")
parser.add_argument('-n', '--name', metavar='<plugin name>', required=True, help='Plugin name')
parser.add_argument('-m', '--module-name', metavar='<module name>', help='Module name')
parser.add_argument('-p', '--basepath', metavar='<path>', required=True, help='Base path')
parser.add_argument('-a', '--author-name', metavar='<author name>', required=True,
help='Author name,for the GPL header')
parser.add_argument('-e', '--author-email', metavar='<author email>', required=True,
help='Author email,for the GPL header')
parser.add_argument('-u', '--url', metavar='<URL>', help='Homepage URL')
parser.add_argument('-c', '--config', metavar='<Config dir>', dest='configdir', help='Location of deluge configuration')
options = parser.parse_args()
@ -32,10 +32,10 @@ options = parser.parse_args()
def create_plugin():
if not options.url:
options.url = ""
options.url = ''
if not os.path.exists(options.basepath):
print("basepath does not exist")
print('basepath does not exist')
return
if not options.configdir:
@ -44,65 +44,65 @@ def create_plugin():
options.configdir = os.path.realpath(options.configdir)
real_name = options.name
name = real_name.replace(" ", "_")
name = real_name.replace(' ', '_')
safe_name = name.lower()
if options.module_name:
safe_name = options.module_name.lower()
plugin_base = os.path.realpath(os.path.join(options.basepath, name))
deluge_namespace = os.path.join(plugin_base, "deluge")
plugins_namespace = os.path.join(deluge_namespace, "plugins")
deluge_namespace = os.path.join(plugin_base, 'deluge')
plugins_namespace = os.path.join(deluge_namespace, 'plugins')
src = os.path.join(plugins_namespace, safe_name)
data_dir = os.path.join(src, "data")
data_dir = os.path.join(src, 'data')
python_path = sys.executable
if os.path.exists(plugin_base):
print("the directory %s already exists, delete it first" % plugin_base)
print('the directory %s already exists, delete it first' % plugin_base)
return
def write_file(path, filename, template, include_gpl=True):
plugin_args = {
"author_name": options.author_name,
"author_email": options.author_email,
"name": name,
"safe_name": safe_name,
"filename": filename,
"plugin_base": plugin_base,
"python_path": python_path,
"url": options.url,
"configdir": options.configdir,
"current_year": datetime.utcnow().year
'author_name': options.author_name,
'author_email': options.author_email,
'name': name,
'safe_name': safe_name,
'filename': filename,
'plugin_base': plugin_base,
'python_path': python_path,
'url': options.url,
'configdir': options.configdir,
'current_year': datetime.utcnow().year
}
filename = os.path.join(path, filename)
with open(filename, "w") as _file:
if filename.endswith(".py") and include_gpl:
with open(filename, 'w') as _file:
if filename.endswith('.py') and include_gpl:
_file.write(GPL % plugin_args)
_file.write(template % plugin_args)
print("creating folders..")
print('creating folders..')
os.mkdir(plugin_base)
os.mkdir(deluge_namespace)
os.mkdir(plugins_namespace)
os.mkdir(src)
os.mkdir(data_dir)
print("creating files..")
write_file(plugin_base, "setup.py", SETUP)
write_file(deluge_namespace, "__init__.py", NAMESPACE_INIT, False)
write_file(plugins_namespace, "__init__.py", NAMESPACE_INIT, False)
write_file(src, "__init__.py", INIT)
write_file(src, "gtkui.py", GTKUI)
write_file(src, "webui.py", WEBUI)
write_file(src, "core.py", CORE)
write_file(src, "common.py", COMMON)
write_file(data_dir, "config.glade", GLADE)
write_file(data_dir, "%s.js" % safe_name, DEFAULT_JS)
print('creating files..')
write_file(plugin_base, 'setup.py', SETUP)
write_file(deluge_namespace, '__init__.py', NAMESPACE_INIT, False)
write_file(plugins_namespace, '__init__.py', NAMESPACE_INIT, False)
write_file(src, '__init__.py', INIT)
write_file(src, 'gtkui.py', GTKUI)
write_file(src, 'webui.py', WEBUI)
write_file(src, 'core.py', CORE)
write_file(src, 'common.py', COMMON)
write_file(data_dir, 'config.glade', GLADE)
write_file(data_dir, '%s.js' % safe_name, DEFAULT_JS)
# add an input parameter for this?
print("building dev-link..")
write_file(plugin_base, "create_dev_link.sh", CREATE_DEV_LINK)
dev_link_path = os.path.join(plugin_base, "create_dev_link.sh")
os.system("chmod +x %s" % dev_link_path) # lazy..
print('building dev-link..')
write_file(plugin_base, 'create_dev_link.sh', CREATE_DEV_LINK)
dev_link_path = os.path.join(plugin_base, 'create_dev_link.sh')
os.system('chmod +x %s' % dev_link_path) # lazy..
os.system(dev_link_path)

View File

@ -28,21 +28,21 @@ def is_float_digit(string):
# set up command-line options
parser = OptionParser()
parser.add_option("--port", help="port for deluge backend host (default: 58846)", default="58846", dest="port")
parser.add_option("--host", help="hostname of deluge backend to connect to (default: localhost)",
default="localhost", dest="host")
parser.add_option("--max_active_limit", dest="max_active_limit",
help="sets the absolute maximum number of active torrents on the deluge backend")
parser.add_option("--max_active_downloading", dest="max_active_downloading",
help="sets the maximum number of active downloading torrents on the deluge backend")
parser.add_option("--max_active_seeding", dest="max_active_seeding",
help="sets the maximum number of active seeding torrents on the deluge backend")
parser.add_option("--max_download_speed", help="sets the maximum global download speed on the deluge backend",
dest="max_download_speed")
parser.add_option("--max_upload_speed", help="sets the maximum global upload speed on the deluge backend",
dest="max_upload_speed")
parser.add_option("--debug", help="outputs debug information to the console", default=False, action="store_true",
dest="debug")
parser.add_option('--port', help='port for deluge backend host (default: 58846)', default='58846', dest='port')
parser.add_option('--host', help='hostname of deluge backend to connect to (default: localhost)',
default='localhost', dest='host')
parser.add_option('--max_active_limit', dest='max_active_limit',
help='sets the absolute maximum number of active torrents on the deluge backend')
parser.add_option('--max_active_downloading', dest='max_active_downloading',
help='sets the maximum number of active downloading torrents on the deluge backend')
parser.add_option('--max_active_seeding', dest='max_active_seeding',
help='sets the maximum number of active seeding torrents on the deluge backend')
parser.add_option('--max_download_speed', help='sets the maximum global download speed on the deluge backend',
dest='max_download_speed')
parser.add_option('--max_upload_speed', help='sets the maximum global upload speed on the deluge backend',
dest='max_upload_speed')
parser.add_option('--debug', help='outputs debug information to the console', default=False, action='store_true',
dest='debug')
# grab command-line options
(options, args) = parser.parse_args()
@ -57,21 +57,21 @@ if options.max_active_limit:
if options.max_active_limit.isdigit() and int(options.max_active_limit) >= 0:
settings['max_active_limit'] = int(options.max_active_limit)
else:
sys.stderr.write("ERROR: Invalid max_active_limit parameter!\n")
sys.stderr.write('ERROR: Invalid max_active_limit parameter!\n')
sys.exit(-1)
if options.max_active_downloading:
if options.max_active_downloading.isdigit() and int(options.max_active_downloading) >= 0:
settings['max_active_downloading'] = int(options.max_active_downloading)
else:
sys.stderr.write("ERROR: Invalid max_active_downloading parameter!\n")
sys.stderr.write('ERROR: Invalid max_active_downloading parameter!\n')
sys.exit(-1)
if options.max_active_seeding:
if options.max_active_seeding.isdigit() and int(options.max_active_seeding) >= 0:
settings['max_active_seeding'] = int(options.max_active_seeding)
else:
sys.stderr.write("ERROR: Invalid max_active_seeding parameter!\n")
sys.stderr.write('ERROR: Invalid max_active_seeding parameter!\n')
sys.exit(-1)
if options.max_download_speed:
@ -79,7 +79,7 @@ if options.max_download_speed:
float(options.max_download_speed) >= 0.0 or float(options.max_download_speed) == -1.0):
settings['max_download_speed'] = float(options.max_download_speed)
else:
sys.stderr.write("ERROR: Invalid max_download_speed parameter!\n")
sys.stderr.write('ERROR: Invalid max_download_speed parameter!\n')
sys.exit(-1)
if options.max_upload_speed:
@ -87,14 +87,14 @@ if options.max_upload_speed:
float(options.max_upload_speed) >= 0.0 or float(options.max_upload_speed) == -1.0):
settings['max_upload_speed'] = float(options.max_upload_speed)
else:
sys.stderr.write("ERROR: Invalid max_upload_speed parameter!\n")
sys.stderr.write('ERROR: Invalid max_upload_speed parameter!\n')
sys.exit(-1)
# If there is something to do ...
if settings:
# create connection to daemon
from deluge.ui.client import sclient as client
client.set_core_uri("http://" + options.host + ":" + options.port)
client.set_core_uri('http://' + options.host + ':' + options.port)
# commit configurations changes
client.set_config(settings)

View File

@ -10,4 +10,4 @@ else:
try:
resource.setrlimit(resource.RLIMIT_NOFILE, (65536, 65536))
except (ValueError, resource.error) as ex:
print("Failed to raise file descriptor limit:", ex)
print('Failed to raise file descriptor limit:', ex)

View File

@ -16,13 +16,13 @@ class BaseTestCase(unittest.TestCase):
def setUp(self): # NOQA
if len(component._ComponentRegistry.components) != 0:
warnings.warn("The component._ComponentRegistry.components is not empty on test setup.\n"
warnings.warn('The component._ComponentRegistry.components is not empty on test setup.\n'
"This is probably caused by another test that didn't clean up after finishing!: %s" %
component._ComponentRegistry.components)
d = maybeDeferred(self.set_up)
def on_setup_error(error):
warnings.warn("Error caught in test setup!\n%s" % error.getTraceback())
warnings.warn('Error caught in test setup!\n%s' % error.getTraceback())
self.fail()
return d.addErrback(on_setup_error)
@ -31,7 +31,7 @@ class BaseTestCase(unittest.TestCase):
d = maybeDeferred(self.tear_down)
def on_teardown_failed(error):
warnings.warn("Error caught in test teardown!\n%s" % error.getTraceback())
warnings.warn('Error caught in test teardown!\n%s' % error.getTraceback())
self.fail()
def on_teardown_complete(result):

View File

@ -26,11 +26,11 @@ from deluge.error import DelugeError
from deluge.ui.util import lang
# This sets log level to critical, so use log.critical() to debug while running unit tests
deluge.log.setup_logger("none")
deluge.log.setup_logger('none')
def disable_new_release_check():
deluge.core.preferencesmanager.DEFAULT_PREFS["new_release_check"] = False
deluge.core.preferencesmanager.DEFAULT_PREFS['new_release_check'] = False
def set_tmp_config_dir():
@ -39,24 +39,24 @@ def set_tmp_config_dir():
return config_directory
def setup_test_logger(level="info", prefix="deluge"):
deluge.log.setup_logger(level, filename="%s.log" % prefix, twisted_observer=False)
def setup_test_logger(level='info', prefix='deluge'):
deluge.log.setup_logger(level, filename='%s.log' % prefix, twisted_observer=False)
def get_test_data_file(filename):
return os.path.join(os.path.join(os.path.dirname(__file__), "data"), filename)
return os.path.join(os.path.join(os.path.dirname(__file__), 'data'), filename)
def todo_test(caller):
# If we are using the delugereporter we can set todo mark on the test
# Without the delugereporter the todo would print a stack trace, so in
# that case we rely only on skipTest
if os.environ.get("DELUGE_REPORTER", None):
getattr(caller, caller._testMethodName).__func__.todo = "To be fixed"
if os.environ.get('DELUGE_REPORTER', None):
getattr(caller, caller._testMethodName).__func__.todo = 'To be fixed'
filename = os.path.basename(traceback.extract_stack(None, 2)[0][0])
funcname = traceback.extract_stack(None, 2)[0][2]
raise unittest.SkipTest("TODO: %s:%s" % (filename, funcname))
raise unittest.SkipTest('TODO: %s:%s' % (filename, funcname))
def add_watchdog(deferred, timeout=0.05, message=None):
@ -85,9 +85,9 @@ class ReactorOverride(object):
"""
def __getattr__(self, attr):
if attr == "run":
if attr == 'run':
return self._run
if attr == "stop":
if attr == 'stop':
return self._stop
return getattr(reactor, attr)
@ -115,8 +115,8 @@ class ProcessOutputHandler(protocol.ProcessProtocol):
"""
self.callbacks = callbacks
self.script = script
self.log_output = ""
self.stderr_out = ""
self.log_output = ''
self.stderr_out = ''
self.logfile = logfile
self.print_stderr = print_stderr
self.quit_d = None
@ -163,24 +163,24 @@ class ProcessOutputHandler(protocol.ProcessProtocol):
else:
self.quit_d.errback(status)
def check_callbacks(self, data, cb_type="stdout"):
def check_callbacks(self, data, cb_type='stdout'):
ret = False
for c in self.callbacks:
if cb_type not in c["types"] or c["deferred"].called:
if cb_type not in c['types'] or c['deferred'].called:
continue
for trigger in c["triggers"]:
if trigger["expr"] in data:
for trigger in c['triggers']:
if trigger['expr'] in data:
ret = True
if "cb" in trigger:
trigger["cb"](self, c["deferred"], data, self.log_output)
elif "value" not in trigger:
if 'cb' in trigger:
trigger['cb'](self, c['deferred'], data, self.log_output)
elif 'value' not in trigger:
raise Exception("Trigger must specify either 'cb' or 'value'")
else:
val = trigger["value"](self, data, self.log_output)
if trigger.get("type", "callback") == "errback":
c["deferred"].errback(val)
val = trigger['value'](self, data, self.log_output)
if trigger.get('type', 'callback') == 'errback':
c['deferred'].errback(val)
else:
c["deferred"].callback(val)
c['deferred'].callback(val)
return ret
def outReceived(self, data): # NOQA
@ -195,16 +195,16 @@ class ProcessOutputHandler(protocol.ProcessProtocol):
"""Process output from stderr"""
self.log_output += data
self.stderr_out += data
self.check_callbacks(data, cb_type="stderr")
self.check_callbacks(data, cb_type='stderr')
if not self.print_stderr:
return
data = "\n%s" % data.strip()
prefixed = data.replace("\n", "\nSTDERR: ")
print("\n%s" % prefixed)
data = '\n%s' % data.strip()
prefixed = data.replace('\n', '\nSTDERR: ')
print('\n%s' % prefixed)
def start_core(listen_port=58846, logfile=None, timeout=10, timeout_msg=None,
custom_script="", print_stderr=True, extra_callbacks=None):
custom_script='', print_stderr=True, extra_callbacks=None):
"""Start the deluge core as a daemon.
Args:
@ -240,18 +240,18 @@ except:
sys.stderr.write("Exception raised:\\n %%s" %% traceback.format_exc())
""" % (config_directory, listen_port, custom_script)
callbacks = []
default_core_cb = {"deferred": Deferred(), "types": "stdout"}
default_core_cb = {'deferred': Deferred(), 'types': 'stdout'}
if timeout:
default_core_cb["timeout"] = timeout
default_core_cb['timeout'] = timeout
# Specify the triggers for daemon log output
default_core_cb["triggers"] = [
{"expr": "Finished loading ", "value": lambda reader, data, data_all: reader},
{"expr": "Couldn't listen on localhost:%d" % (listen_port), "type": "errback", # Error from libtorrent
"value": lambda reader, data, data_all: CannotListenError("localhost", listen_port,
"Could not start deluge test client!\n%s" % data)},
{"expr": "Traceback", "type": "errback",
"value": lambda reader, data, data_all: DelugeError("Traceback found when starting daemon:\n%s" % data)}
default_core_cb['triggers'] = [
{'expr': 'Finished loading ', 'value': lambda reader, data, data_all: reader},
{'expr': "Couldn't listen on localhost:%d" % (listen_port), 'type': 'errback', # Error from libtorrent
'value': lambda reader, data, data_all: CannotListenError('localhost', listen_port,
'Could not start deluge test client!\n%s' % data)},
{'expr': 'Traceback', 'type': 'errback',
'value': lambda reader, data, data_all: DelugeError('Traceback found when starting daemon:\n%s' % data)}
]
callbacks.append(default_core_cb)
@ -259,7 +259,7 @@ except:
callbacks.extend(extra_callbacks)
process_protocol = start_process(daemon_script, callbacks, logfile, print_stderr)
return default_core_cb["deferred"], process_protocol
return default_core_cb['deferred'], process_protocol
def start_process(script, callbacks, logfile=None, print_stderr=True):
@ -291,8 +291,8 @@ def start_process(script, callbacks, logfile=None, print_stderr=True):
# Add timeouts to deferreds
for c in callbacks:
if "timeout" in c:
w = add_watchdog(c["deferred"], timeout=c["timeout"], message=c.get("timeout_msg", None))
if 'timeout' in c:
w = add_watchdog(c['deferred'], timeout=c['timeout'], message=c.get('timeout_msg', None))
process_protocol.watchdogs.append(w)
reactor.spawnProcess(process_protocol, sys.executable, args=[sys.executable], path=cwd)

View File

@ -29,9 +29,9 @@ class ReactorOverride(object):
"""
def __getattr__(self, attr):
if attr == "run":
if attr == 'run':
return self._run
if attr == "stop":
if attr == 'stop':
return self._stop
return getattr(reactor, attr)
@ -59,14 +59,14 @@ class WebServerTestBase(BaseTestCase, DaemonBase):
self.webserver_listen_port = 8999
config_defaults = deluge.ui.web.server.CONFIG_DEFAULTS.copy()
config_defaults["port"] = self.webserver_listen_port
self.config = configmanager.ConfigManager("web.conf", config_defaults)
config_defaults['port'] = self.webserver_listen_port
self.config = configmanager.ConfigManager('web.conf', config_defaults)
self.deluge_web = DelugeWeb(daemon=False)
host = list(self.deluge_web.web_api.host_list["hosts"][0])
host = list(self.deluge_web.web_api.host_list['hosts'][0])
host[2] = self.listen_port
self.deluge_web.web_api.host_list["hosts"][0] = tuple(host)
self.deluge_web.web_api.host_list['hosts'][0] = tuple(host)
self.host_id = host[0]
self.deluge_web.start()
@ -86,11 +86,11 @@ class WebServerMockBase(object):
def check_request(request, method=None, level=None):
pass
self.patch(auth, "check_request", check_request)
self.patch(auth, 'check_request', check_request)
def mock_compress_body(self):
def compress(contents, request):
return contents
# Patch compress to avoid having to decompress output with zlib
self.patch(deluge.ui.web.json_api, "compress", compress)
self.patch(deluge.ui.web.json_api, 'compress', compress)

View File

@ -21,21 +21,21 @@ class DaemonBase(object):
def terminate_core(self, *args):
if args[0] is not None:
if hasattr(args[0], "getTraceback"):
print("terminate_core: Errback Exception: %s" % args[0].getTraceback())
if hasattr(args[0], 'getTraceback'):
print('terminate_core: Errback Exception: %s' % args[0].getTraceback())
if not self.core.killed:
d = self.core.kill()
return d
@defer.inlineCallbacks
def start_core(self, arg, custom_script="", logfile="", print_stderr=True, timeout=5,
def start_core(self, arg, custom_script='', logfile='', print_stderr=True, timeout=5,
port_range=10, extra_callbacks=None):
if logfile == "":
logfile = "daemon_%s.log" % self.id()
if logfile == '':
logfile = 'daemon_%s.log' % self.id()
# We are running py.test
if hasattr(pytest, "config"):
if hasattr(pytest, 'config'):
# Put log file in the py.test --basetemp argument
basetemp = pytest.config.option.basetemp
if basetemp:
@ -46,7 +46,7 @@ class DaemonBase(object):
for dummy in range(port_range):
try:
d, self.core = common.start_core(listen_port=self.listen_port, logfile=logfile,
timeout=timeout, timeout_msg="Timeout!",
timeout=timeout, timeout_msg='Timeout!',
custom_script=custom_script,
print_stderr=print_stderr,
extra_callbacks=extra_callbacks)

View File

@ -15,8 +15,8 @@ class AlertManagerTestCase(BaseTestCase):
def set_up(self):
self.core = Core()
self.am = component.get("AlertManager")
return component.start(["AlertManager"])
self.am = component.get('AlertManager')
return component.start(['AlertManager'])
def tear_down(self):
return component.shutdown()
@ -25,13 +25,13 @@ class AlertManagerTestCase(BaseTestCase):
def handler(alert):
return
self.am.register_handler("dummy_alert", handler)
self.assertEquals(self.am.handlers["dummy_alert"], [handler])
self.am.register_handler('dummy_alert', handler)
self.assertEquals(self.am.handlers['dummy_alert'], [handler])
def test_deregister_handler(self):
def handler(alert):
return
self.am.register_handler("dummy_alert", handler)
self.am.register_handler('dummy_alert', handler)
self.am.deregister_handler(handler)
self.assertEquals(self.am.handlers["dummy_alert"], [])
self.assertEquals(self.am.handlers['dummy_alert'], [])

View File

@ -20,7 +20,7 @@ from .daemon_base import DaemonBase
class NoVersionSendingDaemonSSLProxy(DaemonSSLProxy):
def authenticate(self, username, password):
self.login_deferred = defer.Deferred()
d = self.call("daemon.login", username, password)
d = self.call('daemon.login', username, password)
d.addCallback(self.__on_login, username)
d.addErrback(self.__on_login_fail)
return self.login_deferred
@ -34,7 +34,7 @@ class NoVersionSendingDaemonSSLProxy(DaemonSSLProxy):
class NoVersionSendingClient(Client):
def connect(self, host="127.0.0.1", port=58846, username="", password="",
def connect(self, host='127.0.0.1', port=58846, username='', password='',
skip_authentication=False):
self._daemon_proxy = NoVersionSendingDaemonSSLProxy()
self._daemon_proxy.set_disconnect_callback(self.__on_disconnect)
@ -85,7 +85,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
return d
def test_connect_no_credentials(self):
d = client.connect("localhost", self.listen_port, username="", password="")
d = client.connect('localhost', self.listen_port, username='', password='')
def on_connect(result):
self.assertEqual(client.get_auth_level(), AUTH_LEVEL_ADMIN)
@ -97,7 +97,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
def test_connect_localclient(self):
username, password = deluge.ui.common.get_localhost_auth()
d = client.connect("localhost", self.listen_port, username=username, password=password)
d = client.connect('localhost', self.listen_port, username=username, password=password)
def on_connect(result):
self.assertEqual(client.get_auth_level(), AUTH_LEVEL_ADMIN)
@ -109,14 +109,14 @@ class ClientTestCase(BaseTestCase, DaemonBase):
def test_connect_bad_password(self):
username, password = deluge.ui.common.get_localhost_auth()
d = client.connect("localhost", self.listen_port, username=username, password=password + "1")
d = client.connect('localhost', self.listen_port, username=username, password=password + '1')
def on_failure(failure):
self.assertEqual(
failure.trap(error.BadLoginError),
error.BadLoginError
)
self.assertEquals(failure.value.message, "Password does not match")
self.assertEquals(failure.value.message, 'Password does not match')
self.addCleanup(client.disconnect)
d.addCallbacks(self.fail, on_failure)
@ -124,14 +124,14 @@ class ClientTestCase(BaseTestCase, DaemonBase):
def test_connect_invalid_user(self):
username, password = deluge.ui.common.get_localhost_auth()
d = client.connect("localhost", self.listen_port, username="invalid-user")
d = client.connect('localhost', self.listen_port, username='invalid-user')
def on_failure(failure):
self.assertEqual(
failure.trap(error.BadLoginError),
error.BadLoginError
)
self.assertEquals(failure.value.message, "Username does not exist")
self.assertEquals(failure.value.message, 'Username does not exist')
self.addCleanup(client.disconnect)
d.addCallbacks(self.fail, on_failure)
@ -139,7 +139,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
def test_connect_without_password(self):
username, password = deluge.ui.common.get_localhost_auth()
d = client.connect("localhost", self.listen_port, username=username)
d = client.connect('localhost', self.listen_port, username=username)
def on_failure(failure):
self.assertEqual(
@ -155,16 +155,16 @@ class ClientTestCase(BaseTestCase, DaemonBase):
@defer.inlineCallbacks
def test_connect_with_password(self):
username, password = deluge.ui.common.get_localhost_auth()
yield client.connect("localhost", self.listen_port, username=username, password=password)
yield client.core.create_account("testuser", "testpw", "DEFAULT")
yield client.connect('localhost', self.listen_port, username=username, password=password)
yield client.core.create_account('testuser', 'testpw', 'DEFAULT')
yield client.disconnect()
ret = yield client.connect("localhost", self.listen_port, username="testuser", password="testpw")
ret = yield client.connect('localhost', self.listen_port, username='testuser', password='testpw')
self.assertEquals(ret, deluge.common.AUTH_LEVEL_NORMAL)
yield
@defer.inlineCallbacks
def test_invalid_rpc_method_call(self):
yield client.connect("localhost", self.listen_port, username="", password="")
yield client.connect('localhost', self.listen_port, username='', password='')
d = client.core.invalid_method()
def on_failure(failure):
@ -177,7 +177,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
username, password = deluge.ui.common.get_localhost_auth()
no_version_sending_client = NoVersionSendingClient()
d = no_version_sending_client.connect(
"localhost", self.listen_port, username=username, password=password
'localhost', self.listen_port, username=username, password=password
)
def on_failure(failure):

View File

@ -15,95 +15,95 @@ class CommonTestCase(unittest.TestCase):
pass
def test_fsize(self):
self.assertEquals(fsize(0), "0 B")
self.assertEquals(fsize(100), "100 B")
self.assertEquals(fsize(1023), "1023 B")
self.assertEquals(fsize(1024), "1.0 KiB")
self.assertEquals(fsize(1048575), "1024.0 KiB")
self.assertEquals(fsize(1048576), "1.0 MiB")
self.assertEquals(fsize(1073741823), "1024.0 MiB")
self.assertEquals(fsize(1073741824), "1.0 GiB")
self.assertEquals(fsize(112245), "109.6 KiB")
self.assertEquals(fsize(110723441824), "103.1 GiB")
self.assertEquals(fsize(1099511627775), "1024.0 GiB")
self.assertEquals(fsize(1099511627777), "1.0 TiB")
self.assertEquals(fsize(766148267453245), "696.8 TiB")
self.assertEquals(fsize(0), '0 B')
self.assertEquals(fsize(100), '100 B')
self.assertEquals(fsize(1023), '1023 B')
self.assertEquals(fsize(1024), '1.0 KiB')
self.assertEquals(fsize(1048575), '1024.0 KiB')
self.assertEquals(fsize(1048576), '1.0 MiB')
self.assertEquals(fsize(1073741823), '1024.0 MiB')
self.assertEquals(fsize(1073741824), '1.0 GiB')
self.assertEquals(fsize(112245), '109.6 KiB')
self.assertEquals(fsize(110723441824), '103.1 GiB')
self.assertEquals(fsize(1099511627775), '1024.0 GiB')
self.assertEquals(fsize(1099511627777), '1.0 TiB')
self.assertEquals(fsize(766148267453245), '696.8 TiB')
def test_fpcnt(self):
self.failUnless(fpcnt(0.9311) == "93.11%")
self.failUnless(fpcnt(0.9311) == '93.11%')
def test_fspeed(self):
self.failUnless(fspeed(43134) == "42.1 KiB/s")
self.failUnless(fspeed(43134) == '42.1 KiB/s')
def test_fpeer(self):
self.failUnless(fpeer(10, 20) == "10 (20)")
self.failUnless(fpeer(10, -1) == "10")
self.failUnless(fpeer(10, 20) == '10 (20)')
self.failUnless(fpeer(10, -1) == '10')
def test_ftime(self):
self.failUnless(ftime(0) == "")
self.failUnless(ftime(5) == "5s")
self.failUnless(ftime(100) == "1m 40s")
self.failUnless(ftime(3789) == "1h 3m")
self.failUnless(ftime(23011) == "6h 23m")
self.failUnless(ftime(391187) == "4d 12h")
self.failUnless(ftime(604800) == "1w 0d")
self.failUnless(ftime(13893086) == "22w 6d")
self.failUnless(ftime(59740269) == "1y 46w")
self.failUnless(ftime(0) == '')
self.failUnless(ftime(5) == '5s')
self.failUnless(ftime(100) == '1m 40s')
self.failUnless(ftime(3789) == '1h 3m')
self.failUnless(ftime(23011) == '6h 23m')
self.failUnless(ftime(391187) == '4d 12h')
self.failUnless(ftime(604800) == '1w 0d')
self.failUnless(ftime(13893086) == '22w 6d')
self.failUnless(ftime(59740269) == '1y 46w')
def test_fdate(self):
self.failUnless(fdate(-1) == "")
self.failUnless(fdate(-1) == '')
def test_is_url(self):
self.failUnless(is_url("http://deluge-torrent.org"))
self.failIf(is_url("file://test.torrent"))
self.failUnless(is_url('http://deluge-torrent.org'))
self.failIf(is_url('file://test.torrent'))
def test_is_magnet(self):
self.failUnless(is_magnet("magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN"))
self.failUnless(is_magnet('magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN'))
def test_is_infohash(self):
self.failUnless(is_infohash("2dc5d0e71a66fe69649a640d39cb00a259704973"))
self.failUnless(is_infohash('2dc5d0e71a66fe69649a640d39cb00a259704973'))
def test_get_path_size(self):
self.failUnless(get_path_size(os.devnull) == 0)
self.failUnless(get_path_size("non-existant.file") == -1)
self.failUnless(get_path_size('non-existant.file') == -1)
def test_is_ip(self):
self.failUnless(is_ip("127.0.0.1"))
self.failIf(is_ip("127..0.0"))
self.failUnless(is_ip('127.0.0.1'))
self.failIf(is_ip('127..0.0'))
def test_version_split(self):
self.failUnless(VersionSplit("1.2.2") == VersionSplit("1.2.2"))
self.failUnless(VersionSplit("1.2.1") < VersionSplit("1.2.2"))
self.failUnless(VersionSplit("1.1.9") < VersionSplit("1.2.2"))
self.failUnless(VersionSplit("1.2.2") > VersionSplit("1.2.1"))
self.failUnless(VersionSplit("1.2.2") < VersionSplit("1.2.2-dev"))
self.failUnless(VersionSplit("1.2.2-dev") < VersionSplit("1.3.0-rc2"))
self.failUnless(VersionSplit("1.2.2") > VersionSplit("1.2.2-rc2"))
self.failUnless(VersionSplit("1.2.2-rc2-dev") > VersionSplit("1.2.2-rc2"))
self.failUnless(VersionSplit("1.2.2-rc3") > VersionSplit("1.2.2-rc2"))
self.failUnless(VersionSplit("0.14.9") == VersionSplit("0.14.9"))
self.failUnless(VersionSplit("0.14.9") > VersionSplit("0.14.5"))
self.failUnless(VersionSplit("0.14.10") >= VersionSplit("0.14.9"))
self.failUnless(VersionSplit("1.4.0") > VersionSplit("1.3.900.dev123"))
self.failUnless(VersionSplit("1.3.2rc2.dev1") < VersionSplit("1.3.2-rc2"))
self.failUnless(VersionSplit("1.3.900.dev888") > VersionSplit("1.3.900.dev123"))
self.failUnless(VersionSplit("1.4.0") > VersionSplit("1.4.0.dev123"))
self.failUnless(VersionSplit("1.4.0.dev1") < VersionSplit("1.4.0"))
self.failUnless(VersionSplit("1.4.0a1") < VersionSplit("1.4.0"))
self.failUnless(VersionSplit('1.2.2') == VersionSplit('1.2.2'))
self.failUnless(VersionSplit('1.2.1') < VersionSplit('1.2.2'))
self.failUnless(VersionSplit('1.1.9') < VersionSplit('1.2.2'))
self.failUnless(VersionSplit('1.2.2') > VersionSplit('1.2.1'))
self.failUnless(VersionSplit('1.2.2') < VersionSplit('1.2.2-dev'))
self.failUnless(VersionSplit('1.2.2-dev') < VersionSplit('1.3.0-rc2'))
self.failUnless(VersionSplit('1.2.2') > VersionSplit('1.2.2-rc2'))
self.failUnless(VersionSplit('1.2.2-rc2-dev') > VersionSplit('1.2.2-rc2'))
self.failUnless(VersionSplit('1.2.2-rc3') > VersionSplit('1.2.2-rc2'))
self.failUnless(VersionSplit('0.14.9') == VersionSplit('0.14.9'))
self.failUnless(VersionSplit('0.14.9') > VersionSplit('0.14.5'))
self.failUnless(VersionSplit('0.14.10') >= VersionSplit('0.14.9'))
self.failUnless(VersionSplit('1.4.0') > VersionSplit('1.3.900.dev123'))
self.failUnless(VersionSplit('1.3.2rc2.dev1') < VersionSplit('1.3.2-rc2'))
self.failUnless(VersionSplit('1.3.900.dev888') > VersionSplit('1.3.900.dev123'))
self.failUnless(VersionSplit('1.4.0') > VersionSplit('1.4.0.dev123'))
self.failUnless(VersionSplit('1.4.0.dev1') < VersionSplit('1.4.0'))
self.failUnless(VersionSplit('1.4.0a1') < VersionSplit('1.4.0'))
def test_parse_human_size(self):
from deluge.common import parse_human_size
sizes = [("1", 1),
("10 bytes", 10),
("2048 bytes", 2048),
("1MiB", 2**(10 * 2)),
("1 MiB", 2**(10 * 2)),
("1 GiB", 2**(10 * 3)),
("1 GiB", 2**(10 * 3)),
("1M", 10**6),
("1MB", 10**6),
("1 GB", 10**9),
("1 TB", 10**12)]
sizes = [('1', 1),
('10 bytes', 10),
('2048 bytes', 2048),
('1MiB', 2**(10 * 2)),
('1 MiB', 2**(10 * 2)),
('1 GiB', 2**(10 * 3)),
('1 GiB', 2**(10 * 3)),
('1M', 10**6),
('1MB', 10**6),
('1 GB', 10**9),
('1 TB', 10**12)]
for human_size, byte_size in sizes:
parsed = parse_human_size(human_size)

View File

@ -69,41 +69,41 @@ class ComponentTestClass(BaseTestCase):
def test_start_component(self):
def on_start(result, c):
self.assertEquals(c._component_state, "Started")
self.assertEquals(c._component_state, 'Started')
self.assertEquals(c.start_count, 1)
c = ComponentTester("test_start_c1")
d = component.start(["test_start_c1"])
c = ComponentTester('test_start_c1')
d = component.start(['test_start_c1'])
d.addCallback(on_start, c)
return d
def test_start_stop_depends(self):
def on_stop(result, c1, c2):
self.assertEquals(c1._component_state, "Stopped")
self.assertEquals(c2._component_state, "Stopped")
self.assertEquals(c1._component_state, 'Stopped')
self.assertEquals(c2._component_state, 'Stopped')
self.assertEquals(c1.stop_count, 1)
self.assertEquals(c2.stop_count, 1)
def on_start(result, c1, c2):
self.assertEquals(c1._component_state, "Started")
self.assertEquals(c2._component_state, "Started")
self.assertEquals(c1._component_state, 'Started')
self.assertEquals(c2._component_state, 'Started')
self.assertEquals(c1.start_count, 1)
self.assertEquals(c2.start_count, 1)
return component.stop(["test_start_depends_c1"]).addCallback(on_stop, c1, c2)
return component.stop(['test_start_depends_c1']).addCallback(on_stop, c1, c2)
c1 = ComponentTester("test_start_depends_c1")
c2 = ComponentTester("test_start_depends_c2", depend=["test_start_depends_c1"])
c1 = ComponentTester('test_start_depends_c1')
c2 = ComponentTester('test_start_depends_c2', depend=['test_start_depends_c1'])
d = component.start(["test_start_depends_c2"])
d = component.start(['test_start_depends_c2'])
d.addCallback(on_start, c1, c2)
return d
def start_with_depends(self):
c1 = ComponentTesterDelayStart("test_start_all_c1")
c2 = ComponentTester("test_start_all_c2", depend=["test_start_all_c4"])
c3 = ComponentTesterDelayStart("test_start_all_c3", depend=["test_start_all_c5", "test_start_all_c1"])
c4 = ComponentTester("test_start_all_c4", depend=["test_start_all_c3"])
c5 = ComponentTester("test_start_all_c5")
c1 = ComponentTesterDelayStart('test_start_all_c1')
c2 = ComponentTester('test_start_all_c2', depend=['test_start_all_c4'])
c3 = ComponentTesterDelayStart('test_start_all_c3', depend=['test_start_all_c5', 'test_start_all_c1'])
c4 = ComponentTester('test_start_all_c4', depend=['test_start_all_c3'])
c5 = ComponentTester('test_start_all_c5')
d = component.start()
return (d, c1, c2, c3, c4, c5)
@ -115,7 +115,7 @@ class ComponentTestClass(BaseTestCase):
def test_start_all(self):
def on_start(*args):
for c in args[1:]:
self.assertEquals(c._component_state, "Started")
self.assertEquals(c._component_state, 'Started')
self.assertEquals(c.start_count, 1)
ret = self.start_with_depends()
@ -124,36 +124,36 @@ class ComponentTestClass(BaseTestCase):
return ret[0]
def test_register_exception(self):
ComponentTester("test_register_exception_c1")
ComponentTester('test_register_exception_c1')
self.assertRaises(
component.ComponentAlreadyRegistered,
ComponentTester,
"test_register_exception_c1")
'test_register_exception_c1')
def test_stop_component(self):
def on_stop(result, c):
self.assertEquals(c._component_state, "Stopped")
self.assertEquals(c._component_state, 'Stopped')
self.assertFalse(c._component_timer.running)
self.assertEquals(c.stop_count, 1)
def on_start(result, c):
self.assertEquals(c._component_state, "Started")
return component.stop(["test_stop_component_c1"]).addCallback(on_stop, c)
self.assertEquals(c._component_state, 'Started')
return component.stop(['test_stop_component_c1']).addCallback(on_stop, c)
c = ComponentTesterUpdate("test_stop_component_c1")
d = component.start(["test_stop_component_c1"])
c = ComponentTesterUpdate('test_stop_component_c1')
d = component.start(['test_stop_component_c1'])
d.addCallback(on_start, c)
return d
def test_stop_all(self):
def on_stop(result, *args):
for c in args:
self.assertEquals(c._component_state, "Stopped")
self.assertEquals(c._component_state, 'Stopped')
self.assertEquals(c.stop_count, 1)
def on_start(result, *args):
for c in args:
self.assertEquals(c._component_state, "Started")
self.assertEquals(c._component_state, 'Started')
return component.stop().addCallback(on_stop, *args)
ret = self.start_with_depends()
@ -168,50 +168,50 @@ class ComponentTestClass(BaseTestCase):
self.assertNotEqual(c1.counter, counter)
return component.stop()
c1 = ComponentTesterUpdate("test_update_c1")
c1 = ComponentTesterUpdate('test_update_c1')
cnt = int(c1.counter)
d = component.start(["test_update_c1"])
d = component.start(['test_update_c1'])
d.addCallback(on_start, c1, cnt)
return d
def test_pause(self):
def on_pause(result, c1, counter):
self.assertEqual(c1._component_state, "Paused")
self.assertEqual(c1._component_state, 'Paused')
self.assertNotEqual(c1.counter, counter)
self.assertFalse(c1._component_timer.running)
def on_start(result, c1, counter):
self.assertTrue(c1._component_timer)
self.assertNotEqual(c1.counter, counter)
d = component.pause(["test_pause_c1"])
d = component.pause(['test_pause_c1'])
d.addCallback(on_pause, c1, counter)
return d
c1 = ComponentTesterUpdate("test_pause_c1")
c1 = ComponentTesterUpdate('test_pause_c1')
cnt = int(c1.counter)
d = component.start(["test_pause_c1"])
d = component.start(['test_pause_c1'])
d.addCallback(on_start, c1, cnt)
return d
@defer.inlineCallbacks
def test_component_start_error(self):
ComponentTesterUpdate("test_pause_c1")
yield component.start(["test_pause_c1"])
yield component.pause(["test_pause_c1"])
test_comp = component.get("test_pause_c1")
ComponentTesterUpdate('test_pause_c1')
yield component.start(['test_pause_c1'])
yield component.pause(['test_pause_c1'])
test_comp = component.get('test_pause_c1')
try:
result = self.failureResultOf(test_comp._component_start())
except AttributeError:
raise SkipTest("This test requires trial failureResultOf() in Twisted version >= 13")
raise SkipTest('This test requires trial failureResultOf() in Twisted version >= 13')
self.assertEqual(result.check(component.ComponentException), component.ComponentException)
@defer.inlineCallbacks
def test_start_paused_error(self):
ComponentTesterUpdate("test_pause_c1")
yield component.start(["test_pause_c1"])
yield component.pause(["test_pause_c1"])
ComponentTesterUpdate('test_pause_c1')
yield component.start(['test_pause_c1'])
yield component.pause(['test_pause_c1'])
# Deferreds that fail in component have to error handler which results in
# twisted doing a log.err call which causes the test to fail.
@ -223,12 +223,12 @@ class ComponentTestClass(BaseTestCase):
[(defer.FAILURE,
component.ComponentException("Trying to start a component ('%s') not in "
"stopped state. Current state: '%s'" %
("test_pause_c1", "Paused"), ""))])
('test_pause_c1', 'Paused'), ''))])
def test_shutdown(self):
def on_shutdown(result, c1):
self.assertTrue(c1.shutdowned)
self.assertEquals(c1._component_state, "Stopped")
self.assertEquals(c1._component_state, 'Stopped')
self.assertEquals(c1.stop_count, 1)
def on_start(result, c1):
@ -236,7 +236,7 @@ class ComponentTestClass(BaseTestCase):
d.addCallback(on_shutdown, c1)
return d
c1 = ComponentTesterShutdown("test_shutdown_c1")
d = component.start(["test_shutdown_c1"])
c1 = ComponentTesterShutdown('test_shutdown_c1')
d = component.start(['test_shutdown_c1'])
d.addCallback(on_start, c1)
return d

View File

@ -10,7 +10,7 @@ from deluge.config import Config
from .common import set_tmp_config_dir
DEFAULTS = {"string": "foobar", "int": 1, "float": 0.435, "bool": True, "unicode": u"foobar"}
DEFAULTS = {'string': 'foobar', 'int': 1, 'float': 0.435, 'bool': True, 'unicode': u'foobar'}
class ConfigTestCase(unittest.TestCase):
@ -18,102 +18,102 @@ class ConfigTestCase(unittest.TestCase):
self.config_dir = set_tmp_config_dir()
def test_init(self):
config = Config("test.conf", defaults=DEFAULTS, config_dir=self.config_dir)
config = Config('test.conf', defaults=DEFAULTS, config_dir=self.config_dir)
self.assertEquals(DEFAULTS, config.config)
config = Config("test.conf", config_dir=self.config_dir)
config = Config('test.conf', config_dir=self.config_dir)
self.assertEquals({}, config.config)
def test_set_get_item(self):
config = Config("test.conf", config_dir=self.config_dir)
config["foo"] = 1
self.assertEquals(config["foo"], 1)
self.assertRaises(ValueError, config.set_item, "foo", "bar")
config = Config('test.conf', config_dir=self.config_dir)
config['foo'] = 1
self.assertEquals(config['foo'], 1)
self.assertRaises(ValueError, config.set_item, 'foo', 'bar')
config["foo"] = 2
self.assertEquals(config.get_item("foo"), 2)
config['foo'] = 2
self.assertEquals(config.get_item('foo'), 2)
config["foo"] = "3"
self.assertEquals(config.get_item("foo"), 3)
config['foo'] = '3'
self.assertEquals(config.get_item('foo'), 3)
config["unicode"] = u"ВИДЕОФИЛЬМЫ"
self.assertEquals(config["unicode"], u"ВИДЕОФИЛЬМЫ")
config['unicode'] = u'ВИДЕОФИЛЬМЫ'
self.assertEquals(config['unicode'], u'ВИДЕОФИЛЬМЫ')
config["unicode"] = "foostring"
self.assertTrue(isinstance(config.get_item("unicode"), unicode))
config['unicode'] = 'foostring'
self.assertTrue(isinstance(config.get_item('unicode'), unicode))
config._save_timer.cancel()
def test_set_get_item_none(self):
config = Config("test.conf", config_dir=self.config_dir)
config = Config('test.conf', config_dir=self.config_dir)
config["foo"] = None
self.assertIsNone(config["foo"])
self.assertIsInstance(config["foo"], type(None))
config['foo'] = None
self.assertIsNone(config['foo'])
self.assertIsInstance(config['foo'], type(None))
config["foo"] = 1
self.assertEquals(config.get("foo"), 1)
config['foo'] = 1
self.assertEquals(config.get('foo'), 1)
config["foo"] = None
self.assertIsNone(config["foo"])
config['foo'] = None
self.assertIsNone(config['foo'])
config["bar"] = None
self.assertIsNone(config["bar"])
config['bar'] = None
self.assertIsNone(config['bar'])
config["bar"] = None
self.assertIsNone(config["bar"])
config['bar'] = None
self.assertIsNone(config['bar'])
config._save_timer.cancel()
def test_get(self):
config = Config("test.conf", config_dir=self.config_dir)
config["foo"] = 1
self.assertEquals(config.get("foo"), 1)
self.assertEquals(config.get("foobar"), None)
self.assertEquals(config.get("foobar", 2), 2)
config["foobar"] = 5
self.assertEquals(config.get("foobar", 2), 5)
config = Config('test.conf', config_dir=self.config_dir)
config['foo'] = 1
self.assertEquals(config.get('foo'), 1)
self.assertEquals(config.get('foobar'), None)
self.assertEquals(config.get('foobar', 2), 2)
config['foobar'] = 5
self.assertEquals(config.get('foobar', 2), 5)
def test_load(self):
def check_config():
config = Config("test.conf", config_dir=self.config_dir)
config = Config('test.conf', config_dir=self.config_dir)
self.assertEquals(config["string"], "foobar")
self.assertEquals(config["float"], 0.435)
self.assertEquals(config['string'], 'foobar')
self.assertEquals(config['float'], 0.435)
# Test loading an old config from 1.1.x
import pickle
with open(os.path.join(self.config_dir, "test.conf"), "wb") as _file:
with open(os.path.join(self.config_dir, 'test.conf'), 'wb') as _file:
pickle.dump(DEFAULTS, _file)
check_config()
# Test opening a previous 1.2 config file of just a json object
import json
with open(os.path.join(self.config_dir, "test.conf"), "wb") as _file:
with open(os.path.join(self.config_dir, 'test.conf'), 'wb') as _file:
json.dump(DEFAULTS, _file, indent=2)
check_config()
# Test opening a previous 1.2 config file of having the format versions
# as ints
with open(os.path.join(self.config_dir, "test.conf"), "wb") as _file:
_file.write(str(1) + "\n")
_file.write(str(1) + "\n")
with open(os.path.join(self.config_dir, 'test.conf'), 'wb') as _file:
_file.write(str(1) + '\n')
_file.write(str(1) + '\n')
json.dump(DEFAULTS, _file, indent=2)
check_config()
# Test the 1.2 config format
version = {"format": 1, "file": 1}
with open(os.path.join(self.config_dir, "test.conf"), "wb") as _file:
version = {'format': 1, 'file': 1}
with open(os.path.join(self.config_dir, 'test.conf'), 'wb') as _file:
json.dump(version, _file, indent=2)
json.dump(DEFAULTS, _file, indent=2)
check_config()
def test_save(self):
config = Config("test.conf", defaults=DEFAULTS, config_dir=self.config_dir)
config = Config('test.conf', defaults=DEFAULTS, config_dir=self.config_dir)
# We do this twice because the first time we need to save the file to disk
# and the second time we do a compare and we should not write
ret = config.save()
@ -121,23 +121,23 @@ class ConfigTestCase(unittest.TestCase):
ret = config.save()
self.assertTrue(ret)
config["string"] = "baz"
config["int"] = 2
config['string'] = 'baz'
config['int'] = 2
ret = config.save()
self.assertTrue(ret)
del config
config = Config("test.conf", defaults=DEFAULTS, config_dir=self.config_dir)
self.assertEquals(config["string"], "baz")
self.assertEquals(config["int"], 2)
config = Config('test.conf', defaults=DEFAULTS, config_dir=self.config_dir)
self.assertEquals(config['string'], 'baz')
self.assertEquals(config['int'], 2)
def test_save_timer(self):
self.clock = task.Clock()
deluge.config.callLater = self.clock.callLater
config = Config("test.conf", defaults=DEFAULTS, config_dir=self.config_dir)
config["string"] = "baz"
config["int"] = 2
config = Config('test.conf', defaults=DEFAULTS, config_dir=self.config_dir)
config['string'] = 'baz'
config['int'] = 2
self.assertTrue(config._save_timer.active())
# Timeout set for 5 seconds in config, so lets move clock by 5 seconds
@ -146,9 +146,9 @@ class ConfigTestCase(unittest.TestCase):
def check_config(config):
self.assertTrue(not config._save_timer.active())
del config
config = Config("test.conf", defaults=DEFAULTS, config_dir=self.config_dir)
self.assertEquals(config["string"], "baz")
self.assertEquals(config["int"], 2)
config = Config('test.conf', defaults=DEFAULTS, config_dir=self.config_dir)
self.assertEquals(config['string'], 'baz')
self.assertEquals(config['int'], 2)
check_config(config)

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