Fix files to pass new Flake8 checkers

Some new flake8 checkers were added so fix these new warnings and
any issues uncovered.

Use add-trailing-comma to fix missing trailing commas. It does not
format it as well as I would like however it was fast to change and
helps with git changes in future.

Removed pylint from tox due to large number of warnings.
This commit is contained in:
Calum Lind 2018-06-01 15:35:19 +01:00
parent bae1647e99
commit d642fa3989
166 changed files with 3294 additions and 1907 deletions

View file

@ -19,7 +19,7 @@ class RpcApi(object):
def scan_for_methods(obj):
methods = {
'__doc__': 'Methods available in %s' % obj.__name__.lower()
'__doc__': 'Methods available in %s' % obj.__name__.lower(),
}
for d in dir(obj):
if not hasattr(getattr(obj, d), '_rpcserver_export'):

View file

@ -31,9 +31,9 @@ def decode_int(x, f):
f += 1
newf = x.index(END_DELIM, f)
n = int(x[f:newf])
if x[f:f+1] == b'-' and x[f+1:f+2] == b'0':
if x[f:f + 1] == b'-' and x[f + 1:f + 2] == b'0':
raise ValueError
elif x[f:f+1] == b'0' and newf != f + 1:
elif x[f:f + 1] == b'0' and newf != f + 1:
raise ValueError
return (n, newf + 1)
@ -41,7 +41,7 @@ def decode_int(x, f):
def decode_string(x, f):
colon = x.index(BYTE_SEP, f)
n = int(x[f:colon])
if x[f:f+1] == b'0' and colon != f + 1:
if x[f:f + 1] == b'0' and colon != f + 1:
raise ValueError
colon += 1
return (x[colon:colon + n], colon + n)
@ -49,17 +49,17 @@ def decode_string(x, f):
def decode_list(x, f):
r, f = [], f + 1
while x[f:f+1] != END_DELIM:
v, f = decode_func[x[f:f+1]](x, f)
while x[f:f + 1] != END_DELIM:
v, f = decode_func[x[f:f + 1]](x, f)
r.append(v)
return (r, f + 1)
def decode_dict(x, f):
r, f = {}, f + 1
while x[f:f+1] != END_DELIM:
while x[f:f + 1] != END_DELIM:
k, f = decode_string(x, f)
r[k], f = decode_func[x[f:f+1]](x, f)
r[k], f = decode_func[x[f:f + 1]](x, f)
return (r, f + 1)

View file

@ -63,7 +63,7 @@ TORRENT_STATE = [
'Paused',
'Error',
'Queued',
'Moving'
'Moving',
]
# The output formatting for json.dump
@ -103,7 +103,8 @@ def get_default_config_dir(filename=None):
import _winreg as winreg # For Python 2.
hkey = winreg.OpenKey(
winreg.HKEY_CURRENT_USER,
'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders')
'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders',
)
app_data_reg = winreg.QueryValueEx(hkey, 'AppData')
app_data_path = app_data_reg[0]
winreg.CloseKey(hkey)
@ -273,7 +274,7 @@ def resource_filename(module, path):
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]))
pkg_resources._manager, os.path.join(*(module.split('.') + [path])),
)
@ -554,18 +555,20 @@ def tokenize(text):
return tokenized_input
size_units = (dict(prefix='b', divider=1, singular='byte', plural='bytes'),
dict(prefix='KiB', divider=1024**1),
dict(prefix='MiB', divider=1024**2),
dict(prefix='GiB', divider=1024**3),
dict(prefix='TiB', divider=1024**4),
dict(prefix='PiB', divider=1024**5),
dict(prefix='KB', divider=1000**1),
dict(prefix='MB', divider=1000**2),
dict(prefix='GB', divider=1000**3),
dict(prefix='TB', divider=1000**4),
dict(prefix='PB', divider=1000**5),
dict(prefix='m', divider=1000**2))
size_units = [
{'prefix': 'b', 'divider': 1, 'singular': 'byte', 'plural': 'bytes'},
{'prefix': 'KiB', 'divider': 1024**1},
{'prefix': 'MiB', 'divider': 1024**2},
{'prefix': 'GiB', 'divider': 1024**3},
{'prefix': 'TiB', 'divider': 1024**4},
{'prefix': 'PiB', 'divider': 1024**5},
{'prefix': 'KB', 'divider': 1000**1},
{'prefix': 'MB', 'divider': 1000**2},
{'prefix': 'GB', 'divider': 1000**3},
{'prefix': 'TB', 'divider': 1000**4},
{'prefix': 'PB', 'divider': 1000**5},
{'prefix': 'm', 'divider': 1000**2},
]
class InvalidSize(Exception):
@ -906,10 +909,12 @@ def decode_bytes(byte_str, encoding='utf8'):
elif not isinstance(byte_str, bytes):
return byte_str
encodings = [lambda: ('utf8', 'strict'),
lambda: ('iso-8859-1', 'strict'),
lambda: (chardet.detect(byte_str)['encoding'], 'strict'),
lambda: (encoding, 'ignore')]
encodings = [
lambda: ('utf8', 'strict'),
lambda: ('iso-8859-1', 'strict'),
lambda: (chardet.detect(byte_str)['encoding'], 'strict'),
lambda: (encoding, 'ignore'),
]
if encoding is not 'utf8':
encodings.insert(0, lambda: (encoding, 'strict'))
@ -949,7 +954,10 @@ def utf8_encode_structure(data):
if isinstance(data, (list, tuple)):
return type(data)([utf8_encode_structure(d) for d in data])
elif isinstance(data, dict):
return dict([utf8_encode_structure(d) for d in data.items()])
return {
utf8_encode_structure(k): utf8_encode_structure(v)
for k, v in data.items()
}
elif not isinstance(data, bytes):
try:
return data.encode('utf8')
@ -968,7 +976,8 @@ class VersionSplit(object):
"""
def __init__(self, ver):
version_re = re.compile(r"""
version_re = re.compile(
r"""
^
(?P<version>\d+\.\d+) # minimum 'N.N'
(?P<extraversion>(?:\.\d+)*) # any number of extra '.N' segments
@ -978,7 +987,8 @@ class VersionSplit(object):
(?P<prerelversion>\d+(?:\.\d+)*)
)?
(?P<postdev>(\.post(?P<post>\d+))?(\.dev(?P<dev>\d+))?)?
$""", re.VERBOSE)
$""", re.VERBOSE,
)
# Check for PEP 386 compliant version
match = re.search(version_re, ver)
@ -1061,11 +1071,13 @@ def create_localclient_account(append=False):
create_auth_file()
with open(auth_file, 'a' if append else 'w') as _file:
_file.write(':'.join([
'localclient',
sha(str(random.random()).encode('utf8')).hexdigest(),
str(AUTH_LEVEL_ADMIN)
]) + '\n')
_file.write(
':'.join([
'localclient',
sha(str(random.random()).encode('utf8')).hexdigest(),
str(AUTH_LEVEL_ADMIN),
]) + '\n',
)
_file.flush()
os.fsync(_file.fileno())

View file

@ -146,10 +146,12 @@ class Component(object):
elif self._component_state == 'Started':
d = succeed(True)
else:
d = fail(ComponentException('Trying to start component "%s" but it is '
'not in a stopped state. Current state: %s' %
(self._component_name, self._component_state),
traceback.format_stack(limit=4)))
d = fail(ComponentException(
'Trying to start component "%s" but it is '
'not in a stopped state. Current state: %s' %
(self._component_name, self._component_state),
traceback.format_stack(limit=4),
))
return d
def _component_stop(self):
@ -193,10 +195,12 @@ class Component(object):
elif self._component_state == 'Paused':
d = succeed(None)
else:
d = fail(ComponentException('Trying to pause component "%s" but it is '
'not in a started state. Current state: %s' %
(self._component_name, self._component_state),
traceback.format_stack(limit=4)))
d = fail(ComponentException(
'Trying to pause component "%s" but it is '
'not in a started state. Current state: %s' %
(self._component_name, self._component_state),
traceback.format_stack(limit=4),
))
return d
def _component_resume(self):
@ -207,10 +211,12 @@ class Component(object):
d = maybeDeferred(self._component_start_timer)
d.addCallback(on_resume)
else:
d = fail(ComponentException('Trying to resume component "%s" but it is '
'not in a paused state. Current state: %s' %
(self._component_name, self._component_state),
traceback.format_stack(limit=4)))
d = fail(ComponentException(
'Trying to resume component "%s" but it is '
'not in a paused state. Current state: %s' %
(self._component_name, self._component_state),
traceback.format_stack(limit=4),
))
return d
def _component_shutdown(self):

View file

@ -128,7 +128,7 @@ class Config(object):
# These hold the version numbers and they will be set when loaded
self.__version = {
'format': 1,
'file': file_version
'file': file_version,
}
# This will get set with a reactor.callLater whenever a config option
@ -189,7 +189,8 @@ class Config(object):
# Do not allow the type to change unless it is None
if value is not None and not isinstance(
self.__config[key], type(None)) and not isinstance(self.__config[key], type(value)):
self.__config[key], type(None),
) and not isinstance(self.__config[key], type(value)):
try:
oldtype = type(self.__config[key])
value = oldtype(value)
@ -427,8 +428,10 @@ class Config(object):
log.exception(ex)
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.
@ -510,16 +513,20 @@ class Config(object):
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)
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

View file

@ -94,9 +94,11 @@ class _ConfigManager(object):
log.debug('Getting config: %s', config_file)
# Create the config object if not already created
if config_file not in self.config_files:
self.config_files[config_file] = Config(config_file, defaults,
config_dir=self.config_directory,
file_version=file_version)
self.config_files[config_file] = Config(
config_file, defaults,
config_dir=self.config_directory,
file_version=file_version,
)
return self.config_files[config_file]

View file

@ -39,13 +39,15 @@ class AlertManager(component.Component):
self.alert_queue_size = 10000
self.set_alert_queue_size(self.alert_queue_size)
alert_mask = (lt.alert.category_t.error_notification |
lt.alert.category_t.port_mapping_notification |
lt.alert.category_t.storage_notification |
lt.alert.category_t.tracker_notification |
lt.alert.category_t.status_notification |
lt.alert.category_t.ip_block_notification |
lt.alert.category_t.performance_warning)
alert_mask = (
lt.alert.category_t.error_notification |
lt.alert.category_t.port_mapping_notification |
lt.alert.category_t.storage_notification |
lt.alert.category_t.tracker_notification |
lt.alert.category_t.status_notification |
lt.alert.category_t.ip_block_notification |
lt.alert.category_t.performance_warning
)
self.session.apply_settings({'alert_mask': alert_mask})

View file

@ -28,7 +28,8 @@ AUTH_LEVELS_MAPPING = {
'READONLY': AUTH_LEVEL_READONLY,
'DEFAULT': AUTH_LEVEL_NORMAL,
'NORMAL': AUTH_LEVEL_DEFAULT,
'ADMIN': AUTH_LEVEL_ADMIN}
'ADMIN': AUTH_LEVEL_ADMIN,
}
AUTH_LEVELS_MAPPING_REVERSE = {v: k for k, v in AUTH_LEVELS_MAPPING.items()}
@ -45,7 +46,7 @@ class Account(object):
'username': self.username,
'password': self.password,
'authlevel': AUTH_LEVELS_MAPPING_REVERSE[self.authlevel],
'authlevel_int': self.authlevel
'authlevel_int': self.authlevel,
}
def __repr__(self):
@ -98,7 +99,7 @@ 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:
@ -129,8 +130,10 @@ class AuthManager(component.Component):
if authlevel not in AUTH_LEVELS_MAPPING:
raise AuthManagerError('Invalid auth level: %s' % authlevel)
try:
self.__auth[username] = Account(username, password,
AUTH_LEVELS_MAPPING[authlevel])
self.__auth[username] = Account(
username, password,
AUTH_LEVELS_MAPPING[authlevel],
)
self.write_auth_file()
return True
except Exception as ex:
@ -157,7 +160,7 @@ class AuthManager(component.Component):
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]
@ -232,8 +235,10 @@ class AuthManager(component.Component):
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:

View file

@ -109,7 +109,8 @@ class Core(component.Component):
peer_id = self._create_peer_id(DELUGE_VER)
log.debug(
'Starting session (peer_id: %s, user_agent: %s)',
peer_id, user_agent)
peer_id, user_agent,
)
settings_pack = {
'peer_fingerprint': peer_id,
'user_agent': user_agent,
@ -390,7 +391,7 @@ class Core(component.Component):
try:
d = self.torrentmanager.add_async(
filedump=filedump, options=options, filename=filename, save_state=save_state
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)
@ -418,7 +419,8 @@ class Core(component.Component):
try:
return self.torrentmanager.add(
filedump=filedump, options=options, filename=filename)
filedump=filedump, options=options, filename=filename,
)
except RuntimeError as ex:
log.error('There was an error adding the torrent file %s: %s', filename, ex)
raise
@ -441,7 +443,8 @@ class Core(component.Component):
for idx, torrent in enumerate(torrent_files):
try:
yield self.add_torrent_file_async(
torrent[0], torrent[1], torrent[2], save_state=idx == last_index)
torrent[0], torrent[1], torrent[2], save_state=idx == last_index,
)
except AddTorrentError as ex:
log.warn('Error when adding torrent: %s', ex)
errors.append(ex)
@ -651,8 +654,10 @@ class Core(component.Component):
@export
def get_torrent_status(self, torrent_id, keys, diff=False):
torrent_keys, plugin_keys = self.torrentmanager.separate_keys(keys, [torrent_id])
return self.create_torrent_status(torrent_id, torrent_keys, plugin_keys, diff=diff, update=True,
all_keys=not keys)
return self.create_torrent_status(
torrent_id, torrent_keys, plugin_keys, diff=diff, update=True,
all_keys=not keys,
)
@export
def get_torrents_status(self, filter_dict, keys, diff=False):
@ -699,7 +704,7 @@ class Core(component.Component):
@export
def get_config_values(self, keys):
"""Get the config values for the entered keys"""
return dict((key, self.config.get(key)) for key in keys)
return {key: self.config.get(key) for key in keys}
@export
def set_config(self, config):
@ -740,7 +745,7 @@ class Core(component.Component):
'port': proxy_port,
'proxy_hostnames': settings['proxy_hostnames'],
'proxy_peer_connections': settings['proxy_peer_connections'],
'proxy_tracker_connections': settings['proxy_tracker_connections']
'proxy_tracker_connections': settings['proxy_tracker_connections'],
}
return proxy_dict
@ -870,25 +875,32 @@ class Core(component.Component):
return deluge.common.get_path_size(path)
@export
def create_torrent(self, path, tracker, piece_length, comment, target,
webseeds, private, created_by, trackers, add_to_session):
def create_torrent(
self, path, tracker, piece_length, comment, target,
webseeds, private, created_by, trackers, add_to_session,
):
log.debug('creating torrent..')
threading.Thread(target=self._create_torrent_thread,
args=(
path,
tracker,
piece_length,
comment,
target,
webseeds,
private,
created_by,
trackers,
add_to_session)).start()
threading.Thread(
target=self._create_torrent_thread,
args=(
path,
tracker,
piece_length,
comment,
target,
webseeds,
private,
created_by,
trackers,
add_to_session,
),
).start()
def _create_torrent_thread(self, path, tracker, piece_length, comment, target,
webseeds, private, created_by, trackers, add_to_session):
def _create_torrent_thread(
self, path, tracker, piece_length, comment, target,
webseeds, private, created_by, trackers, add_to_session,
):
from deluge import metafile
metafile.make_meta_file(
path,
@ -899,7 +911,8 @@ class Core(component.Component):
webseeds=webseeds,
private=private,
created_by=created_by,
trackers=trackers)
trackers=trackers,
)
log.debug('torrent created!')
if add_to_session:
options = {}
@ -1055,8 +1068,10 @@ class Core(component.Component):
:rtype: bool
"""
d = getPage(b'http://deluge-torrent.org/test_port.php?port=%s' %
self.get_listen_port(), timeout=30)
d = getPage(
b'http://deluge-torrent.org/test_port.php?port=%s' %
self.get_listen_port(), timeout=30,
)
def on_get_page(result):
return bool(int(result))

View file

@ -65,8 +65,10 @@ def is_daemon_running(pid_file):
class Daemon(object):
"""The Deluge Daemon class"""
def __init__(self, listen_interface=None, outgoing_interface=None, interface=None, port=None, standalone=False,
read_only_config_keys=None):
def __init__(
self, listen_interface=None, outgoing_interface=None, interface=None, port=None, standalone=False,
read_only_config_keys=None,
):
"""
Args:
listen_interface (str, optional): The IP address to listen to bittorrent connections on.
@ -98,9 +100,11 @@ class Daemon(object):
SetConsoleCtrlHandler(win_handler)
# Start the core as a thread and join it until it's done
self.core = Core(listen_interface=listen_interface,
outgoing_interface=outgoing_interface,
read_only_config_keys=read_only_config_keys)
self.core = Core(
listen_interface=listen_interface,
outgoing_interface=outgoing_interface,
read_only_config_keys=read_only_config_keys,
)
if port is None:
port = self.core.config['daemon_port']
@ -114,11 +118,13 @@ class Daemon(object):
port=port,
allow_remote=self.core.config['allow_remote'],
listen=not standalone,
interface=interface
interface=interface,
)
log.debug('Listening to UI on: %s:%s and bittorrent on: %s Making connections out on: %s',
interface, port, listen_interface, outgoing_interface)
log.debug(
'Listening to UI on: %s:%s and bittorrent on: %s Making connections out on: %s',
interface, port, listen_interface, outgoing_interface,
)
def start(self):
# Register the daemon and the core RPCs

View file

@ -23,16 +23,26 @@ from deluge.ui.translations_util import set_dummy_trans
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('-o', '--outinterface', metavar='<ip-addr>', dest='outgoing_interface',
action='store', help=_('The IP address for outgoing 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.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(
'-o', '--outinterface', metavar='<ip-addr>', dest='outgoing_interface',
action='store', help=_('The IP address for outgoing 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()
@ -59,8 +69,10 @@ def start_daemon(skip_start=False):
from deluge.core.daemon import is_daemon_running
pid_file = get_config_dir('deluged.pid')
if is_daemon_running(pid_file):
print('Cannot run multiple daemons with same config directory.\n'
'If you believe this is an error, force starting by deleting: %s' % pid_file)
print(
'Cannot run multiple daemons with same config directory.\n'
'If you believe this is an error, force starting by deleting: %s' % pid_file,
)
sys.exit(1)
log = getLogger(__name__)
@ -74,19 +86,23 @@ def start_daemon(skip_start=False):
def run_daemon(options):
try:
from deluge.core.daemon import Daemon
daemon = Daemon(listen_interface=options.listen_interface,
outgoing_interface=options.outgoing_interface,
interface=options.ui_interface,
port=options.port,
read_only_config_keys=options.read_only_config_keys.split(','))
daemon = Daemon(
listen_interface=options.listen_interface,
outgoing_interface=options.outgoing_interface,
interface=options.ui_interface,
port=options.port,
read_only_config_keys=options.read_only_config_keys.split(','),
)
if skip_start:
return daemon
else:
daemon.start()
except CannotListenError as ex:
log.error('Cannot start deluged, listen port in use.\n'
' Check for other running daemons or services using this port: %s:%s',
ex.interface, ex.port)
log.error(
'Cannot start deluged, listen port in use.\n'
' Check for other running daemons or services using this port: %s:%s',
ex.interface, ex.port,
)
sys.exit(1)
except Exception as ex:
log.error('Unable to start deluged: %s', ex)

View file

@ -194,7 +194,7 @@ class FilterManager(component.Component):
tree_keys.remove(cat)
torrent_keys, plugin_keys = self.torrents.separate_keys(tree_keys, torrent_ids)
items = dict((field, self.tree_fields[field]()) for field in tree_keys)
items = {field: self.tree_fields[field]() for field in tree_keys}
for torrent_id in list(torrent_ids):
status = self.core.create_torrent_status(torrent_id, torrent_keys, plugin_keys) # status={key:value}

View file

@ -33,7 +33,8 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, component.Compon
# 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

View file

@ -72,8 +72,10 @@ DEFAULT_PREFS = {
'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_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,
@ -123,7 +125,7 @@ DEFAULT_PREFS = {
'cache_expiry': 60,
'auto_manage_prefer_seeds': False,
'shared': False,
'super_seeding': False
'super_seeding': False,
}
@ -207,19 +209,28 @@ class PreferencesManager(component.Component):
interface = str(self.config['listen_interface'].strip())
interface = interface if interface else '0.0.0.0'
log.debug('Listen Interface: %s, Ports: %s with use_sys_port: %s',
interface, listen_ports, self.config['listen_use_sys_port'])
interfaces = ['%s:%s' % (interface, port) for port in range(listen_ports[0], listen_ports[1]+1)]
log.debug(
'Listen Interface: %s, Ports: %s with use_sys_port: %s',
interface, listen_ports, self.config['listen_use_sys_port'],
)
interfaces = [
'%s:%s' % (interface, port)
for port in range(listen_ports[0], listen_ports[1] + 1)
]
self.core.apply_session_settings(
{'listen_system_port_fallback': self.config['listen_use_sys_port'],
'listen_interfaces': ''.join(interfaces)})
{
'listen_system_port_fallback': self.config['listen_use_sys_port'],
'listen_interfaces': ''.join(interfaces),
},
)
def __set_outgoing_on(self):
""" Set the interface address for outgoing BitTorrent connections."""
outinterface = self.config['outgoing_interface'].strip()
outinterface = outinterface if outinterface else '0.0.0.0'
self.core.apply_session_settings(
{'outgoing_interfaces': outinterface})
{'outgoing_interfaces': outinterface},
)
def _on_set_outgoing_ports(self, key, value):
self.__set_outgoing_ports()
@ -254,7 +265,8 @@ class PreferencesManager(component.Component):
'router.bitcomet.com:6881',
'dht.transmissionbt.com:6881',
'dht.aelitis.com:6881',
])
],
)
self.core.apply_session_settings({
'dht_bootstrap_nodes': ','.join(dht_bootstraps),
'enable_dht': value,
@ -286,10 +298,13 @@ 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}
self.core.apply_session_settings(
{'out_enc_policy': lt.enc_policy(self.config['enc_out_policy']),
'in_enc_policy': lt.enc_policy(self.config['enc_in_policy']),
'allowed_enc_level': lt.enc_level(pe_enc_level[self.config['enc_level']]),
'prefer_rc4': True})
{
'out_enc_policy': lt.enc_policy(self.config['enc_out_policy']),
'in_enc_policy': lt.enc_policy(self.config['enc_in_policy']),
'allowed_enc_level': lt.enc_level(pe_enc_level[self.config['enc_level']]),
'prefer_rc4': True,
},
)
def _on_set_max_connections_global(self, key, value):
self.core.apply_session_setting('connections_limit', value)
@ -376,7 +391,8 @@ class PreferencesManager(component.Component):
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:
@ -392,7 +408,7 @@ class PreferencesManager(component.Component):
'proxy_peer_connections': value['proxy_peer_connections'],
'proxy_tracker_connections': value['proxy_tracker_connections'],
'force_proxy': value['force_proxy'],
'anonymous_mode': value['anonymous_mode']
'anonymous_mode': value['anonymous_mode'],
}
if value['type'] == lt.proxy_type.i2p_proxy:

View file

@ -134,8 +134,10 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
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)
@ -161,11 +163,14 @@ 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',
peer.host, peer.port)
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] = self.AuthLevel(AUTH_LEVEL_NONE, '')
self.transport.sessionno
] = self.AuthLevel(AUTH_LEVEL_NONE, '')
def connectionLost(self, reason=connectionDone): # NOQA: N802
"""
@ -219,16 +224,19 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
exc_type.__name__,
exc_value._args,
exc_value._kwargs,
formated_tb
formated_tb,
))
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(exc_value), exc_type.__name__, formated_tb)
str(exc_value), exc_type.__name__, formated_tb,
)
except WrappedException:
send_error()
except Exception as ex:
@ -249,7 +257,8 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
ret = component.get('AuthManager').authorize(*args, **kwargs)
if ret:
self.factory.authorized_sessions[
self.transport.sessionno] = self.AuthLevel(ret, args[0])
self.transport.sessionno
] = self.AuthLevel(ret, args[0])
self.factory.session_protocols[self.transport.sessionno] = self
except Exception as ex:
send_error()
@ -294,8 +303,10 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
auth_level = self.factory.authorized_sessions[self.transport.sessionno].auth_level
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!',
self.transport.sessionno)
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
# which session is calling it.
@ -514,7 +525,7 @@ class RPCServer(component.Component):
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)
(RPC_EVENT, event.name, event.args),
)
def emit_event_for_session_id(self, session_id, event):
@ -530,14 +541,18 @@ class RPCServer(component.Component):
log.debug('Session ID %s is not valid. Not sending event "%s".', session_id, event.name)
return
if session_id not in self.factory.interested_events:
log.debug('Session ID %s is not interested in any events. Not sending event "%s".',
session_id, event.name)
log.debug(
'Session ID %s is not interested in any events. Not sending event "%s".',
session_id, event.name,
)
return
if event.name not in self.factory.interested_events[session_id]:
log.debug('Session ID %s is not interested in event "%s". Not sending it.', session_id, event.name)
return
log.debug('Sending event "%s" with args "%s" to session id "%s".',
event.name, event.args, session_id)
log.debug(
'Sending event "%s" with args "%s" to session id "%s".',
event.name, event.args, session_id,
)
self.factory.session_protocols[session_id].sendData((RPC_EVENT, event.name, event.args))
def stop(self):

View file

@ -52,7 +52,7 @@ LT_TORRENT_STATE_MAP = {
'finished': 'Seeding',
'seeding': 'Seeding',
'allocating': 'Allocating',
'checking_resume_data': 'Checking'
'checking_resume_data': 'Checking',
}
@ -114,7 +114,7 @@ def convert_lt_files(files):
'index': index,
'path': file_path.replace('\\', '/'),
'size': _file.size,
'offset': _file.offset
'offset': _file.offset,
})
return filelist
@ -172,7 +172,7 @@ class TorrentOptions(dict):
'shared': 'shared',
'stop_at_ratio': 'stop_seed_at_ratio',
'stop_ratio': 'stop_seed_ratio',
'super_seeding': 'super_seeding'
'super_seeding': 'super_seeding',
}
for opt_k, conf_k in options_conf_map.items():
self[opt_k] = config[conf_k]
@ -639,8 +639,10 @@ class Torrent(object):
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)
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,
)
if self.forced_error:
log.debug('Torrent Error state message: %s', self.forced_error.error_message)
@ -699,8 +701,10 @@ class Torrent(object):
eta = 0
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']) -
status.all_time_upload) // status.upload_payload_rate
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
if left > 0:
@ -825,8 +829,10 @@ class Torrent(object):
"""
if not self.has_metadata:
return []
return [progress / _file.size if _file.size else 0.0 for progress, _file in
zip(self.handle.file_progress(), self.torrent_info.files())]
return [
progress / _file.size if _file.size else 0.0 for progress, _file in
zip(self.handle.file_progress(), self.torrent_info.files())
]
def get_tracker_host(self):
"""Get the hostname of the currently connected tracker.
@ -1019,7 +1025,8 @@ class Torrent(object):
'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),
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'],
@ -1061,7 +1068,7 @@ class Torrent(object):
'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,
'time_since_transfer': self.get_time_since_transfer
'time_since_transfer': self.get_time_since_transfer,
}
def pause(self):
@ -1147,9 +1154,11 @@ 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',
self.torrent_id, dest, ex)
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
try:
@ -1183,7 +1192,8 @@ class Torrent(object):
# 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'))
UserWarning('Skipped creating resume_data while in Error state'),
)
else:
self.handle.save_resume_data(flags)
@ -1315,7 +1325,7 @@ class Torrent(object):
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']
on_file_rename_complete, wait_on_folder, _file['index'],
)
new_path = _file['path'].replace(folder, new_folder, 1)
try:

View file

@ -38,7 +38,8 @@ LT_DEFAULT_ADD_TORRENT_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)
lt.add_torrent_params_flags_t.flag_apply_ip_filter
)
class TorrentState: # pylint: disable=old-style-class
@ -48,33 +49,35 @@ class TorrentState: # pylint: disable=old-style-class
This must be old style class to avoid breaking torrent.state file.
"""
def __init__(self,
torrent_id=None,
filename=None,
trackers=None,
storage_mode='sparse',
paused=False,
save_path=None,
max_connections=-1,
max_upload_slots=-1,
max_upload_speed=-1.0,
max_download_speed=-1.0,
prioritize_first_last=False,
sequential_download=False,
file_priorities=None,
queue=None,
auto_managed=True,
is_finished=False,
stop_ratio=2.00,
stop_at_ratio=False,
remove_at_ratio=False,
move_completed=False,
move_completed_path=None,
magnet=None,
owner=None,
shared=False,
super_seeding=False,
name=None):
def __init__(
self,
torrent_id=None,
filename=None,
trackers=None,
storage_mode='sparse',
paused=False,
save_path=None,
max_connections=-1,
max_upload_slots=-1,
max_upload_speed=-1.0,
max_download_speed=-1.0,
prioritize_first_last=False,
sequential_download=False,
file_priorities=None,
queue=None,
auto_managed=True,
is_finished=False,
stop_ratio=2.00,
stop_at_ratio=False,
remove_at_ratio=False,
move_completed=False,
move_completed_path=None,
magnet=None,
owner=None,
shared=False,
super_seeding=False,
name=None,
):
# Build the class atrribute list from args
for key, value in locals().items():
if key == 'self':
@ -113,8 +116,10 @@ class TorrentManager(component.Component):
"""
def __init__(self):
component.Component.__init__(self, 'TorrentManager', interval=5,
depend=['CorePluginManager', 'AlertManager'])
component.Component.__init__(
self, 'TorrentManager', interval=5,
depend=['CorePluginManager', 'AlertManager'],
)
log.debug('TorrentManager init...')
# Set the libtorrent session
self.session = component.get('Core').session
@ -154,8 +159,10 @@ class TorrentManager(component.Component):
self.prev_saved_state = None
# Register set functions
set_config_keys = ['max_connections_per_torrent', 'max_upload_slots_per_torrent',
'max_upload_speed_per_torrent', 'max_download_speed_per_torrent']
set_config_keys = [
'max_connections_per_torrent', 'max_upload_slots_per_torrent',
'max_upload_speed_per_torrent', 'max_download_speed_per_torrent',
]
for config_key in set_config_keys:
on_set_func = getattr(self, ''.join(['on_set_', config_key]))
@ -170,7 +177,7 @@ class TorrentManager(component.Component):
'file_renamed_alert', 'file_error_alert', 'file_completed_alert',
'storage_moved_alert', 'storage_moved_failed_alert', 'state_update_alert',
'state_changed_alert', 'save_resume_data_alert', 'save_resume_data_failed_alert',
'fastresume_rejected_alert'
'fastresume_rejected_alert',
]
for alert_handle in alert_handles:
@ -230,7 +237,8 @@ class TorrentManager(component.Component):
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'):
'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
@ -308,7 +316,7 @@ class TorrentManager(component.Component):
return options
def _build_torrent_params(
self, torrent_info=None, magnet=None, options=None, resume_data=None
self, torrent_info=None, magnet=None, options=None, resume_data=None,
):
"""Create the add_torrent_params dict for adding torrent to libtorrent."""
add_torrent_params = {}
@ -361,10 +369,14 @@ class TorrentManager(component.Component):
add_torrent_params['resume_data'] = resume_data
# Set flags: enable duplicate_is_error & override_resume_data, disable auto_managed.
add_torrent_params['flags'] = ((LT_DEFAULT_ADD_TORRENT_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)
add_torrent_params['flags'] = (
(
LT_DEFAULT_ADD_TORRENT_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
@ -411,7 +423,8 @@ class TorrentManager(component.Component):
options = self._build_torrent_options(options)
__, add_torrent_params = self._build_torrent_params(
torrent_info, magnet, options, resume_data)
torrent_info, magnet, options, resume_data,
)
# We need to pause the AlertManager momentarily to prevent alerts
# for this torrent being generated before a Torrent object is created.
@ -426,7 +439,8 @@ class TorrentManager(component.Component):
raise AddTorrentError('Unable to add torrent to session: %s' % ex)
torrent = self._add_torrent_obj(
handle, options, state, filename, magnet, resume_data, filedump, save_state)
handle, options, state, filename, magnet, resume_data, filedump, save_state,
)
return torrent.torrent_id
def add_async(
@ -470,7 +484,8 @@ class TorrentManager(component.Component):
options = self._build_torrent_options(options)
torrent_id, add_torrent_params = self._build_torrent_params(
torrent_info, magnet, options, resume_data)
torrent_info, magnet, options, resume_data,
)
d = Deferred()
self.torrents_loading[torrent_id] = (d, options, state, filename, magnet, resume_data, filedump, save_state)
@ -509,10 +524,12 @@ class TorrentManager(component.Component):
log.debug('Torrent added: %s', str(handle.info_hash()))
if log.isEnabledFor(logging.INFO):
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')
log.info(
'Torrent %s from user "%s" %s',
name_and_owner['name'],
name_and_owner['owner'],
from_state and 'loaded' or 'added',
)
# Write the .torrent file to the state directory.
if filedump:
@ -525,10 +542,11 @@ class TorrentManager(component.Component):
return torrent
def add_async_callback(
self, handle, d, options, state, filename, magnet, resume_data, filedump, save_state
self, handle, d, options, state, filename, magnet, resume_data, filedump, save_state,
):
torrent = self._add_torrent_obj(
handle, options, state, filename, magnet, resume_data, filedump, save_state)
handle, options, state, filename, magnet, resume_data, filedump, save_state,
)
d.callback(torrent.torrent_id)
@ -670,7 +688,8 @@ class TorrentManager(component.Component):
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
@ -740,7 +759,7 @@ class TorrentManager(component.Component):
torrent.options['owner'],
torrent.options['shared'],
torrent.options['super_seeding'],
torrent.options['name']
torrent.options['name'],
)
state.torrents.append(torrent_state)
return state
@ -1058,9 +1077,11 @@ class TorrentManager(component.Component):
if log.isEnabledFor(logging.DEBUG):
log.debug('Finished %s ', torrent_id)
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:

View file

@ -129,8 +129,10 @@ def deprecated(func):
@wraps(func)
def depr_func(*args, **kwargs):
warnings.simplefilter('always', DeprecationWarning) # Turn off filter
warnings.warn('Call to deprecated function {}.'.format(func.__name__),
category=DeprecationWarning, stacklevel=2)
warnings.warn(
'Call to deprecated function {}.'.format(func.__name__),
category=DeprecationWarning, stacklevel=2,
)
warnings.simplefilter('default', DeprecationWarning) # Reset filter
return func(*args, **kwargs)

View file

@ -63,17 +63,22 @@ 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' % \
dict(daemon_version=self.daemon_version)
msg = (
'Your deluge client is not compatible with the daemon. '
'Please upgrade your client to %(daemon_version)s'
) % {'daemon_version': self.daemon_version}
super(IncompatibleClient, self).__init__(message=msg)
class NotAuthorizedError(_ClientSideRecreateError):
def __init__(self, current_level, required_level):
msg = 'Auth level too low: %(current_level)s < %(required_level)s' % \
dict(current_level=current_level, required_level=required_level)
msg = (
'Auth level too low: %(current_level)s < %(required_level)s'
) % {
'current_level': current_level,
'required_level': required_level,
}
super(NotAuthorizedError, self).__init__(message=msg)
self.current_level = current_level
self.required_level = required_level

View file

@ -34,8 +34,10 @@ class HTTPDownloader(client.HTTPDownloader):
"""
Factory class for downloading files and keeping track of progress.
"""
def __init__(self, url, filename, part_callback=None, headers=None,
force_filename=False, allow_compression=True):
def __init__(
self, url, filename, part_callback=None, headers=None,
force_filename=False, allow_compression=True,
):
"""
:param url: the url to download from
:type url: string
@ -227,8 +229,10 @@ def _download_file(url, filename, callback=None, headers=None, force_filename=Fa
return factory.deferred
def download_file(url, filename, callback=None, headers=None, force_filename=False,
allow_compression=True, handle_redirects=True):
def download_file(
url, filename, callback=None, headers=None, force_filename=False,
allow_compression=True, handle_redirects=True,
):
"""
Downloads a file from a specific URL and returns a Deferred. A callback
function can be specified to be called as parts are received.
@ -259,18 +263,24 @@ def download_file(url, filename, callback=None, headers=None, force_filename=Fal
def on_download_fail(failure):
if failure.check(PageRedirect) and handle_redirects:
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)
result = _download_file(
new_url, filename, callback=callback, headers=headers,
force_filename=force_filename,
allow_compression=allow_compression,
)
result.addCallbacks(on_download_success, on_download_fail)
else:
# Log the failure and pass to the caller
log.warning('Error occurred downloading file from "%s": %s',
url, failure.getErrorMessage())
log.warning(
'Error occurred downloading file from "%s": %s',
url, failure.getErrorMessage(),
)
result = failure
return result
d = _download_file(url, filename, callback=callback, headers=headers,
force_filename=force_filename, allow_compression=allow_compression)
d = _download_file(
url, filename, callback=callback, headers=headers,
force_filename=force_filename, allow_compression=allow_compression,
)
d.addCallbacks(on_download_success, on_download_fail)
return d

View file

@ -45,7 +45,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
@ -88,8 +88,10 @@ class Logging(LoggingLoggerClass):
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)
@ -105,12 +107,14 @@ levels = {
'none': logging.CRITICAL,
'debug': logging.DEBUG,
'trace': 5,
'garbage': 1
'garbage': 1,
}
def setup_logger(level='error', filename=None, filemode='w', logrotate=None,
output_stream=sys.stdout, twisted_observer=True):
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
to that file instead of stdout.
@ -137,7 +141,7 @@ 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':
handler_cls = logging.FileHandler
@ -151,7 +155,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)
@ -214,8 +218,10 @@ def tweak_logging_levels():
if not os.path.isfile(logging_config_file):
return
log = logging.getLogger(__name__)
log.warn('logging.conf found! tweaking logging levels from %s',
logging_config_file)
log.warn(
'logging.conf found! tweaking logging levels from %s',
logging_config_file,
)
with open(logging_config_file, 'r') as _file:
for line in _file:
if line.strip().startswith('#'):
@ -249,9 +255,11 @@ def get_plugin_logger(logger_name):
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__', '')
warnings.warn_explicit(DEPRECATION_WARNING, DeprecationWarning,
module_stack[1], module_stack[2],
caller_module_name)
warnings.warn_explicit(
DEPRECATION_WARNING, DeprecationWarning,
module_stack[1], module_stack[2],
caller_module_name,
)
if 'deluge.plugins.' in logger_name:
return logging.getLogger(logger_name)
@ -291,16 +299,20 @@ class _BackwardsCompatibleLOG(object):
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__', '')
warnings.warn_explicit(DEPRECATION_WARNING, DeprecationWarning,
module_stack[1], module_stack[2],
caller_module_name)
warnings.warn_explicit(
DEPRECATION_WARNING, DeprecationWarning,
module_stack[1], module_stack[2],
caller_module_name,
)
if caller_module:
for member in stack:
module = inspect.getmodule(member[0])
if not module:
continue
if module.__name__ in ('deluge.plugins.pluginbase',
'deluge.plugins.init'):
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)
@ -308,7 +320,7 @@ class _BackwardsCompatibleLOG(object):
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

@ -68,7 +68,7 @@ class TorrentMetadata(object):
raise InvalidPath('Need to set a data_path!')
torrent = {
'info': {}
'info': {},
}
if self.comment:

View file

@ -50,13 +50,15 @@ class RemoteFileProgress(object):
def __call__(self, piece_count, num_pieces):
component.get('RPCServer').emit_event_for_session_id(
self.session_id, CreateTorrentProgressEvent(piece_count, num_pieces)
self.session_id, CreateTorrentProgressEvent(piece_count, num_pieces),
)
def make_meta_file(path, url, piece_length, progress=None, title=None, comment=None,
safe=None, content_type=None, target=None, webseeds=None, name=None,
private=False, created_by=None, trackers=None):
def make_meta_file(
path, url, piece_length, progress=None, title=None, comment=None,
safe=None, content_type=None, target=None, webseeds=None, name=None,
private=False, created_by=None, trackers=None,
):
data = {'creation date': int(gmtime())}
if url:
data['announce'] = url.strip()
@ -147,8 +149,10 @@ def makeinfo(path, piece_length, progress, name=None, content_type=None, private
size = os.path.getsize(f)
p2 = [n.encode('utf8') for n in p]
if content_type:
fs.append({'length': size, 'path': p2,
'content_type': content_type}) # HEREDAVE. bad for batch!
fs.append({
'length': size, 'path': p2,
'content_type': content_type,
}) # HEREDAVE. bad for batch!
else:
fs.append({'length': size, 'path': p2})
with open(f, 'rb') as file_:
@ -173,11 +177,13 @@ def makeinfo(path, piece_length, progress, name=None, content_type=None, private
if not name:
name = os.path.split(path)[1]
return {'pieces': b''.join(pieces),
'piece length': piece_length,
'files': fs,
'name': name.encode('utf8'),
'private': private}
return {
'pieces': b''.join(pieces),
'piece length': piece_length,
'files': fs,
'name': name.encode('utf8'),
'private': private,
}
else:
size = os.path.getsize(path)
if size >= piece_length:
@ -198,15 +204,19 @@ def makeinfo(path, piece_length, progress, name=None, content_type=None, private
progress(piece_count, num_pieces)
name = os.path.split(path)[1].encode('utf8')
if content_type is not None:
return {'pieces': b''.join(pieces),
'piece length': piece_length, 'length': size,
'name': name,
'content_type': content_type,
'private': private}
return {'pieces': b''.join(pieces),
return {
'pieces': b''.join(pieces),
'piece length': piece_length, 'length': size,
'name': name,
'private': private}
'content_type': content_type,
'private': private,
}
return {
'pieces': b''.join(pieces),
'piece length': piece_length, 'length': size,
'name': name,
'private': private,
}
def subfiles(d):

View file

@ -108,10 +108,12 @@ class PluginManagerBase(object):
self.available_plugins = []
for name in self.pkg_env:
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)
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,
)
self.available_plugins.append(self.pkg_env[name][0].project_name)
def enable_plugin(self, plugin_name):
@ -162,7 +164,7 @@ class PluginManagerBase(object):
warnings.warn_explicit(
DEPRECATION_WARNING % name,
DeprecationWarning,
instance.__module__, 0
instance.__module__, 0,
)
if self._component_state == 'Started':
def on_enabled(result, instance):
@ -179,8 +181,10 @@ class PluginManagerBase(object):
return True
def on_started_error(result, instance):
log.error('Failed to start plugin: %s\n%s', plugin_name,
result.getTraceback(elideFrameworkCode=1, detail='brief'))
log.error(
'Failed to start plugin: %s\n%s', plugin_name,
result.getTraceback(elideFrameworkCode=1, detail='brief'),
)
self.plugins[plugin_name.replace('-', ' ')] = instance
self.disable_plugin(plugin_name)
return False

View file

@ -37,7 +37,7 @@ log = logging.getLogger(__name__)
DEFAULT_PREFS = {
'watchdirs': {},
'next_id': 1
'next_id': 1,
}
@ -64,7 +64,7 @@ OPTIONS_AVAILABLE = { # option: builtin
'add_paused': True,
'queue_to_top': False,
'owner': True,
'seed_mode': True
'seed_mode': True,
}
MAX_NUM_ATTEMPTS = 10
@ -91,7 +91,7 @@ class Core(CorePluginBase):
self.watchdirs = self.config['watchdirs']
component.get('EventManager').register_event_handler(
'PreTorrentRemovedEvent', self.__on_pre_torrent_removed
'PreTorrentRemovedEvent', self.__on_pre_torrent_removed,
)
# Dict of Filename:Attempts
@ -109,7 +109,7 @@ class Core(CorePluginBase):
def disable(self):
# disable all running looping calls
component.get('EventManager').deregister_event_handler(
'PreTorrentRemovedEvent', self.__on_pre_torrent_removed
'PreTorrentRemovedEvent', self.__on_pre_torrent_removed,
)
for loopingcall in self.update_timers.values():
loopingcall.stop()
@ -124,12 +124,12 @@ 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'])
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.items():
if options['abspath'] == w['abspath'] and watchdir_id != w_id:
@ -210,8 +210,10 @@ class Core(CorePluginBase):
watchdir = self.watchdirs[watchdir_id]
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.',
watchdir_id)
log.debug(
'Watchdir id %s is not enabled. Disabling it.',
watchdir_id,
)
self.disable_watchdir(watchdir_id)
return
@ -271,8 +273,10 @@ class Core(CorePluginBase):
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)
log.warning(
'Maximum attempts reached while trying to add the '
'torrent file with the path %s', filepath,
)
os.rename(filepath, filepath + '.invalid')
del self.invalid_torrents[filename]
else:
@ -305,8 +309,10 @@ class Core(CorePluginBase):
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)
log.debug(
'Moving added torrent file "%s" to "%s"',
os.path.basename(filepath), copy_torrent_path,
)
shutil.move(filepath, copy_torrent_file)
else:
os.remove(filepath)
@ -322,7 +328,8 @@ class Core(CorePluginBase):
d = component.get('Core').add_torrent_magnet(filedump.strip(), options)
else:
d = component.get('Core').add_torrent_file_async(
filename, base64.encodestring(filedump), options)
filename, base64.encodestring(filedump), options,
)
d.addCallback(on_torrent_added, filename, filepath)
d.addErrback(fail_torrent_add, filepath, magnet)
except AddTorrentError as ex:
@ -331,8 +338,10 @@ class Core(CorePluginBase):
def on_update_watchdir_error(self, failure, watchdir_id):
"""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)
log.error(
'Disabling "%s", error during update: %s',
self.watchdirs[watchdir_id]['path'], failure,
)
@export
def enable_watchdir(self, watchdir_id):
@ -341,7 +350,7 @@ class Core(CorePluginBase):
if w_id not in self.update_timers or not self.update_timers[w_id].running:
self.update_timers[w_id] = LoopingCall(self.update_watchdir, w_id)
self.update_timers[w_id].start(5).addErrback(
self.on_update_watchdir_error, w_id
self.on_update_watchdir_error, w_id,
)
# Update the config
if not self.watchdirs[w_id]['enabled']:
@ -383,8 +392,10 @@ class Core(CorePluginBase):
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 = {}
@ -392,8 +403,10 @@ class Core(CorePluginBase):
if watchdir.get('owner', 'localclient') == session_user:
watchdirs[watchdir_id] = watchdir
log.debug('Current logged in user %s is not an ADMIN, send only '
'their watchdirs: %s', session_user, list(watchdirs))
log.debug(
'Current logged in user %s is not an ADMIN, send only '
'their watchdirs: %s', session_user, list(watchdirs),
)
return watchdirs
def _make_unicode(self, options):
@ -414,7 +427,7 @@ class Core(CorePluginBase):
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.values()]:
raise Exception('Path is already being watched.')
@ -449,9 +462,11 @@ class Core(CorePluginBase):
try:
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',
torrent_id)
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.values():
@ -466,9 +481,13 @@ class Core(CorePluginBase):
if os.path.isfile(torrent_fname_path):
try:
os.remove(torrent_fname_path)
log.info('Removed torrent file "%s" from "%s"',
torrent_fname, copy_torrent_path)
log.info(
'Removed torrent file "%s" from "%s"',
torrent_fname, copy_torrent_path,
)
break
except OSError as ex:
log.info('Failed to removed torrent file "%s" from "%s": %s',
torrent_fname, copy_torrent_path, ex)
log.info(
'Failed to removed torrent file "%s" from "%s": %s',
torrent_fname, copy_torrent_path, ex,
)

View file

@ -37,8 +37,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']
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)
@ -55,7 +57,7 @@ class OptionsDialog(object):
'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_toggle_toggled': self.on_toggle_toggled,
})
self.dialog = self.builder.get_object('options_dialog')
self.dialog.set_transient_for(component.get('Preferences').pref_dialog)
@ -77,22 +79,22 @@ class OptionsDialog(object):
def load_options(self, options):
self.builder.get_object('enabled').set_active(options.get('enabled', True))
self.builder.get_object('append_extension_toggle').set_active(
options.get('append_extension_toggle', False)
options.get('append_extension_toggle', False),
)
self.builder.get_object('append_extension').set_text(
options.get('append_extension', '.added')
options.get('append_extension', '.added'),
)
self.builder.get_object('download_location_toggle').set_active(
options.get('download_location_toggle', False)
options.get('download_location_toggle', False),
)
self.builder.get_object('copy_torrent_toggle').set_active(
options.get('copy_torrent_toggle', False)
options.get('copy_torrent_toggle', False),
)
self.builder.get_object('delete_copy_torrent_toggle').set_active(
options.get('delete_copy_torrent_toggle', False)
options.get('delete_copy_torrent_toggle', False),
)
self.builder.get_object('seed_mode').set_active(
options.get('seed_mode', False)
options.get('seed_mode', False),
)
self.accounts.clear()
self.labels.clear()
@ -120,17 +122,19 @@ class OptionsDialog(object):
self.builder.get_object('isnt_queue_to_top').set_active(True)
if not options.get('auto_managed', True):
self.builder.get_object('isnt_auto_managed').set_active(True)
for field in ['move_completed_path', 'path', 'download_location',
'copy_torrent']:
for field in [
'move_completed_path', 'path', 'download_location',
'copy_torrent',
]:
if client.is_localhost():
self.builder.get_object(field + '_chooser').set_current_folder(
options.get(field, os.path.expanduser('~'))
options.get(field, os.path.expanduser('~')),
)
self.builder.get_object(field + '_chooser').show()
self.builder.get_object(field + '_entry').hide()
else:
self.builder.get_object(field + '_entry').set_text(
options.get(field, '')
options.get(field, ''),
)
self.builder.get_object(field + '_entry').show()
self.builder.get_object(field + '_chooser').hide()
@ -139,33 +143,33 @@ class OptionsDialog(object):
def on_core_config(config):
if client.is_localhost():
self.builder.get_object('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']):
self.builder.get_object('move_completed_toggle').set_active(True)
self.builder.get_object('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']):
self.builder.get_object('copy_torrent_toggle').set_active(True)
self.builder.get_object('copy_torrent_chooser').set_current_folder(
options.get('copy_torrent', config['torrentfiles_location'])
options.get('copy_torrent', config['torrentfiles_location']),
)
else:
self.builder.get_object('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']):
self.builder.get_object('move_completed_toggle').set_active(
options.get('move_completed_toggle', False)
options.get('move_completed_toggle', False),
)
self.builder.get_object('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']):
self.builder.get_object('copy_torrent_toggle').set_active(True)
self.builder.get_object('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']):
@ -180,7 +184,7 @@ class OptionsDialog(object):
for account in accounts:
acc_iter = self.accounts.append()
self.accounts.set_value(
acc_iter, 0, account['username']
acc_iter, 0, account['username'],
)
if account['username'] == owner:
selected_iter = acc_iter
@ -215,7 +219,7 @@ class OptionsDialog(object):
client.core.get_enabled_plugins().addCallback(on_get_enabled_plugins)
if client.get_auth_level() == deluge.common.AUTH_LEVEL_ADMIN:
client.core.get_known_accounts().addCallback(
on_accounts, options.get('owner', client.get_auth_user())
on_accounts, options.get('owner', client.get_auth_user()),
).addErrback(on_accounts_failure)
else:
acc_iter = self.accounts.append()
@ -224,11 +228,13 @@ class OptionsDialog(object):
self.builder.get_object('OwnerCombobox').set_sensitive(False)
def set_sensitive(self):
maintoggles = ['download_location', 'append_extension',
'move_completed', 'label', 'max_download_speed',
'max_upload_speed', 'max_connections',
'max_upload_slots', 'add_paused', 'auto_managed',
'stop_at_ratio', 'queue_to_top', 'copy_torrent']
maintoggles = [
'download_location', 'append_extension',
'move_completed', 'label', 'max_download_speed',
'max_upload_speed', 'max_connections',
'max_upload_slots', 'add_paused', 'auto_managed',
'stop_at_ratio', 'queue_to_top', 'copy_torrent',
]
for maintoggle in maintoggles:
self.on_toggle_toggled(self.builder.get_object(maintoggle + '_toggle'))
@ -278,7 +284,7 @@ class OptionsDialog(object):
try:
options = self.generate_opts()
client.autoadd.set_options(
str(self.watchdir_id), options
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()
@ -308,28 +314,37 @@ class OptionsDialog(object):
if client.is_localhost():
options['path'] = self.builder.get_object('path_chooser').get_filename()
options['download_location'] = self.builder.get_object(
'download_location_chooser').get_filename()
'download_location_chooser',
).get_filename()
options['move_completed_path'] = self.builder.get_object(
'move_completed_path_chooser').get_filename()
'move_completed_path_chooser',
).get_filename()
options['copy_torrent'] = self.builder.get_object(
'copy_torrent_chooser').get_filename()
'copy_torrent_chooser',
).get_filename()
else:
options['path'] = self.builder.get_object('path_entry').get_text()
options['download_location'] = self.builder.get_object(
'download_location_entry').get_text()
'download_location_entry',
).get_text()
options['move_completed_path'] = self.builder.get_object(
'move_completed_path_entry').get_text()
'move_completed_path_entry',
).get_text()
options['copy_torrent'] = self.builder.get_object(
'copy_torrent_entry').get_text()
'copy_torrent_entry',
).get_text()
options['label'] = self.builder.get_object('label').child.get_text().lower()
options['append_extension'] = self.builder.get_object('append_extension').get_text()
options['owner'] = self.accounts[
self.builder.get_object('OwnerCombobox').get_active()][0]
self.builder.get_object('OwnerCombobox').get_active()
][0]
for key in ['append_extension_toggle', 'download_location_toggle',
'label_toggle', 'copy_torrent_toggle',
'delete_copy_torrent_toggle', 'seed_mode']:
for key in [
'append_extension_toggle', 'download_location_toggle',
'label_toggle', 'copy_torrent_toggle',
'delete_copy_torrent_toggle', 'seed_mode',
]:
options[key] = self.builder.get_object(key).get_active()
for spin_id in self.spin_ids:
@ -343,8 +358,10 @@ class OptionsDialog(object):
options[chk_id + '_toggle'] = self.builder.get_object(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'
' files to" directory cannot be the same!'))
raise IncompatibleOption(_(
'"Watch Folder" directory and "Copy of .torrent'
' files to" directory cannot be the same!',
))
return options
@ -357,13 +374,13 @@ class GtkUI(GtkPluginBase):
self.opts_dialog = OptionsDialog()
component.get('PluginManager').register_hook(
'on_apply_prefs', self.on_apply_prefs
'on_apply_prefs', self.on_apply_prefs,
)
component.get('PluginManager').register_hook(
'on_show_prefs', self.on_show_prefs
'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 = {}
@ -386,16 +403,16 @@ class GtkUI(GtkPluginBase):
sw.add(self.treeView)
sw.show_all()
component.get('Preferences').add_page(
_('AutoAdd'), self.builder.get_object('prefs_box')
_('AutoAdd'), self.builder.get_object('prefs_box'),
)
def disable(self):
component.get('Preferences').remove_page(_('AutoAdd'))
component.get('PluginManager').deregister_hook(
'on_apply_prefs', self.on_apply_prefs
'on_apply_prefs', self.on_apply_prefs,
)
component.get('PluginManager').deregister_hook(
'on_show_prefs', self.on_show_prefs
'on_show_prefs', self.on_show_prefs,
)
def create_model(self):
@ -403,14 +420,14 @@ class GtkUI(GtkPluginBase):
for watchdir_id, watchdir in self.watchdirs.items():
store.append([
watchdir_id, watchdir['enabled'],
watchdir.get('owner', 'localclient'), watchdir['path']
watchdir.get('owner', 'localclient'), watchdir['path'],
])
return store
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)
@ -490,7 +507,7 @@ class GtkUI(GtkPluginBase):
for watchdir_id, watchdir in self.watchdirs.items():
self.store.append([
watchdir_id, watchdir['enabled'],
watchdir.get('owner', 'localclient'), watchdir['path']
watchdir.get('owner', 'localclient'), watchdir['path'],
])
# Workaround for cached glade signal appearing when re-enabling plugin in same session
if self.builder.get_object('edit_button'):

View file

@ -45,5 +45,5 @@ setup(
%s = deluge.plugins.%s:GtkUIPlugin
[deluge.plugin.web]
%s = deluge.plugins.%s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower()) * 3)
""" % ((__plugin_name__, __plugin_name__.lower()) * 3),
)

View file

@ -165,5 +165,5 @@ class IP(object):
def __repr__(self):
return '<%s long=%s address="%s">' % (
self.__class__.__name__, self.long, self.address
self.__class__.__name__, self.long, self.address,
)

View file

@ -104,14 +104,14 @@ class Core(CorePluginBase):
self.update_timer = LoopingCall(self.check_import)
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')
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')
@ -189,7 +189,7 @@ class Core(CorePluginBase):
try:
ip = IP.parse(ip)
self.blocklist.add_rule(
ip.address, ip.address, ALLOW_RANGE
ip.address, ip.address, ALLOW_RANGE,
)
saved.add(ip.address)
log.debug('Added %s to whitelisted', ip)
@ -223,15 +223,17 @@ class Core(CorePluginBase):
self.update_timer.stop()
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 '
'do not know if they were blocked before. Re-import '
'current blocklist and re-add whitelisted.')
log.debug(
'IP addresses were removed from the whitelist. Since we '
'do not know if they were blocked before. Re-import '
'current blocklist and re-add whitelisted.',
)
self.has_imported = False
d = self.import_list(deluge.configmanager.get_config_dir('blocklist.cache'))
d.addCallbacks(self.on_import_complete, self.on_import_error)
@ -318,7 +320,7 @@ class Core(CorePluginBase):
self.is_downloading = True
return download_file(
url, deluge.configmanager.get_config_dir('blocklist.download'),
on_retrieve_data, headers
on_retrieve_data, headers,
)
def on_download_complete(self, blocklist):
@ -365,8 +367,10 @@ class Core(CorePluginBase):
else:
log.warning('Blocklist download failed: %s', error_msg)
if self.failed_attempts < self.config['try_times']:
log.debug('Try downloading blocklist again... (%s/%s)',
self.failed_attempts, self.config['try_times'])
log.debug(
'Try downloading blocklist again... (%s/%s)',
self.failed_attempts, self.config['try_times'],
)
self.failed_attempts += 1
d = self.download_list()
d.addCallbacks(self.on_download_complete, self.on_download_error)

View file

@ -17,25 +17,25 @@ import zipfile
def Zipped(reader): # NOQA: N802
"""Blocklist reader for zipped blocklists"""
def open(self):
def _open(self):
z = zipfile.ZipFile(self.file)
f = z.open(z.namelist()[0])
return f
reader.open = open
reader.open = _open
return reader
def GZipped(reader): # NOQA: N802
"""Blocklist reader for gzipped blocklists"""
def open(self):
def _open(self):
return gzip.open(self.file)
reader.open = open
reader.open = _open
return reader
def BZipped2(reader): # NOQA: N802
"""Blocklist reader for bzipped2 blocklists"""
def open(self):
def _open(self):
return bz2.BZ2File(self.file)
reader.open = open
reader.open = _open
return reader

View file

@ -15,19 +15,19 @@ from .readers import EmuleReader, PeerGuardianReader, SafePeerReader
COMPRESSION_TYPES = {
'PK': 'Zip',
'\x1f\x8b': 'GZip',
'BZ': 'BZip2'
'BZ': 'BZip2',
}
DECOMPRESSERS = {
'Zip': Zipped,
'GZip': GZipped,
'BZip2': BZipped2
'BZip2': BZipped2,
}
READERS = {
'Emule': EmuleReader,
'SafePeer': SafePeerReader,
'PeerGuardian': PeerGuardianReader
'PeerGuardian': PeerGuardianReader,
}

View file

@ -35,7 +35,7 @@ class GtkUI(GtkPluginBase):
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
@ -67,7 +67,8 @@ class GtkUI(GtkPluginBase):
self.builder.get_object('image_up_to_date').hide()
self.status_item.set_text(
'Downloading %.2f%%' % (status['file_progress'] * 100))
'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()
@ -79,7 +80,8 @@ class GtkUI(GtkPluginBase):
self.builder.get_object('image_up_to_date').hide()
self.status_item.set_text(
'Importing ' + str(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()
@ -97,12 +99,15 @@ class GtkUI(GtkPluginBase):
self.status_item.set_text('%(num_blocked)s/%(num_whited)s' % status)
self.builder.get_object('label_filesize').set_text(
deluge.common.fsize(status['file_size']))
deluge.common.fsize(status['file_size']),
)
self.builder.get_object('label_modified').set_text(
datetime.fromtimestamp(status['file_date']).strftime('%c'))
datetime.fromtimestamp(status['file_date']).strftime('%c'),
)
self.builder.get_object('label_type').set_text(status['file_type'])
self.builder.get_object('label_url').set_text(
status['file_url'])
status['file_url'],
)
client.blocklist.get_status().addCallback(_on_get_status)
@ -155,18 +160,24 @@ class GtkUI(GtkPluginBase):
self.builder.connect_signals({
'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,
self.whitelist_treeview),
'on_whitelist_add_clicked': (
self.on_add_button_clicked,
self.whitelist_treeview,
),
'on_whitelist_remove_clicked': (
self.on_delete_button_clicked,
self.whitelist_treeview,
),
})
# Set button icons
self.builder.get_object('image_download').set_from_file(
common.get_resource('blocklist_download24.png'))
common.get_resource('blocklist_download24.png'),
)
self.builder.get_object('image_import').set_from_file(
common.get_resource('blocklist_import24.png'))
common.get_resource('blocklist_import24.png'),
)
# Update the preferences page with config values from the core
self._on_show_prefs()
@ -174,13 +185,14 @@ class GtkUI(GtkPluginBase):
# Add the page to the preferences dialog
self.plugin.add_preferences_page(
_('Blocklist'),
self.builder.get_object('blocklist_prefs_box'))
self.builder.get_object('blocklist_prefs_box'),
)
def build_whitelist_model_treeview(self):
self.whitelist_treeview = self.builder.get_object('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()
@ -207,11 +219,15 @@ class GtkUI(GtkPluginBase):
def on_whitelist_treeview_selection_changed(self, selection):
model, selected_connection_iter = selection.get_selected()
if selected_connection_iter:
self.builder.get_object('whitelist_delete').set_property('sensitive',
True)
self.builder.get_object('whitelist_delete').set_property(
'sensitive',
True,
)
else:
self.builder.get_object('whitelist_delete').set_property('sensitive',
False)
self.builder.get_object('whitelist_delete').set_property(
'sensitive',
False,
)
def on_add_button_clicked(self, widget, treeview):
model = treeview.get_model()
@ -228,5 +244,5 @@ class GtkUI(GtkPluginBase):
self.whitelist_model.clear()
for ip in whitelist:
self.whitelist_model.set(
self.whitelist_model.append(), 0, ip, 1, True
self.whitelist_model.append(), 0, ip, 1, True,
)

View file

@ -21,7 +21,7 @@ FORMAT_LIST = [
('gzmule', _('Emule IP list (GZip)')),
('spzip', _('SafePeer Text (Zipped)')),
('pgtext', _('PeerGuardian Text (Uncompressed)')),
('p2bgz', _('PeerGuardian P2B (GZip)'))
('p2bgz', _('PeerGuardian P2B (GZip)')),
]

View file

@ -39,5 +39,5 @@ setup(
%s = deluge.plugins.%s:GtkUIPlugin
[deluge.plugin.web]
%s = deluge.plugins.%s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower()) * 3)
""" % ((__plugin_name__, __plugin_name__.lower()) * 3),
)

View file

@ -26,7 +26,7 @@ from deluge.plugins.pluginbase import CorePluginBase
log = logging.getLogger(__name__)
DEFAULT_CONFIG = {
'commands': []
'commands': [],
}
EXECUTE_ID = 0
@ -36,7 +36,7 @@ EXECUTE_COMMAND = 2
EVENT_MAP = {
'complete': 'TorrentFinishedEvent',
'added': 'TorrentAddedEvent',
'removed': 'TorrentRemovedEvent'
'removed': 'TorrentRemovedEvent',
}
@ -118,8 +118,10 @@ class Core(CorePluginBase):
command = os.path.expandvars(command[EXECUTE_COMMAND])
command = os.path.expanduser(command)
cmd_args = [torrent_id.encode('utf8'), torrent_name.encode('utf8'),
download_location.encode('utf8')]
cmd_args = [
torrent_id.encode('utf8'), torrent_name.encode('utf8'),
download_location.encode('utf8'),
]
if windows_check():
# Escape ampersand on windows (see #2784)
cmd_args = [cmd_arg.replace('&', '^^^&') for cmd_arg in cmd_args]

View file

@ -30,7 +30,7 @@ EXECUTE_COMMAND = 2
EVENT_MAP = {
'complete': _('Torrent Complete'),
'added': _('Torrent Added'),
'removed': _('Torrent Removed')
'removed': _('Torrent Removed'),
}
EVENTS = ['complete', 'added', 'removed']

View file

@ -40,5 +40,5 @@ setup(
%s = deluge.plugins.%s:GtkUIPlugin
[deluge.plugin.web]
%s = deluge.plugins.%s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower()) * 3)
""" % ((__plugin_name__, __plugin_name__.lower()) * 3),
)

View file

@ -30,7 +30,7 @@ log = logging.getLogger(__name__)
DEFAULT_PREFS = {
'extract_path': '',
'use_name_folder': True
'use_name_folder': True,
}
if windows_check():

View file

@ -51,7 +51,7 @@ class GtkUI(GtkPluginBase):
config = {
'extract_path': path,
'use_name_folder': self.builder.get_object('chk_use_name').get_active()
'use_name_folder': self.builder.get_object('chk_use_name').get_active(),
}
client.extractor.set_config(config)

View file

@ -53,5 +53,5 @@ setup(
%s = deluge.plugins.%s:GtkUIPlugin
[deluge.plugin.web]
%s = deluge.plugins.%s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower()) * 3)
""" % ((__plugin_name__, __plugin_name__.lower()) * 3),
)

View file

@ -57,7 +57,7 @@ OPTIONS_DEFAULTS = {
'move_completed': False,
'move_completed_path': '',
'auto_add': False,
'auto_add_trackers': []
'auto_add_trackers': [],
}
NO_LABEL = 'No Label'
@ -108,7 +108,7 @@ class Core(CorePluginBase):
pass
def init_filter_dict(self):
filter_dict = dict([(label, 0) for label in self.labels])
filter_dict = {label: 0 for label in self.labels}
filter_dict['All'] = len(self.torrents)
return filter_dict
@ -208,8 +208,8 @@ class Core(CorePluginBase):
torrent.set_options(
{
'move_completed': options['move_completed'],
'move_completed_path': options['move_completed_path']
}
'move_completed_path': options['move_completed_path'],
},
)
def _unset_torrent_options(self, torrent_id, label_id):
@ -233,8 +233,8 @@ class Core(CorePluginBase):
torrent.set_options(
{
'move_completed': self.core_cfg.config['move_completed'],
'move_completed_path': self.core_cfg.config['move_completed_path']
}
'move_completed_path': self.core_cfg.config['move_completed_path'],
},
)
def _has_auto_match(self, torrent, label_options):
@ -310,7 +310,10 @@ class Core(CorePluginBase):
@export
def get_config(self):
"""see : label_set_config"""
return dict((key, self.config[key]) for key in CORE_OPTIONS if key in self.config.config)
return {
key: self.config[key]
for key in CORE_OPTIONS if key in self.config.config
}
@export
def set_config(self, options):

View file

@ -126,8 +126,10 @@ 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']
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 = [
@ -136,7 +138,7 @@ class OptionsDialog(object):
('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'])
('auto_add', ['auto_add_trackers']),
]
def __init__(self):

View file

@ -44,5 +44,5 @@ setup(
%s = deluge.plugins.%s:GtkUIPlugin
[deluge.plugin.web]
%s = deluge.plugins.%s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower()) * 3)
""" % ((__plugin_name__, __plugin_name__.lower()) * 3),
)

View file

@ -37,7 +37,7 @@ class CustomNotifications(object):
'email': {},
'popup': {},
'blink': {},
'sound': {}
'sound': {},
}
def enable(self):
@ -72,7 +72,7 @@ class CustomNotifications(object):
wrapper, handler = self.custom_notifications[kind][eventtype]
try:
component.get('EventManager').register_event_handler(
eventtype, wrapper
eventtype, wrapper,
)
except KeyError:
from deluge.ui.client import client
@ -83,7 +83,7 @@ class CustomNotifications(object):
wrapper, handler = self.custom_notifications[kind][eventtype]
try:
component.get('EventManager').deregister_event_handler(
eventtype, wrapper
eventtype, wrapper,
)
except KeyError:
from deluge.ui.client import client
@ -99,8 +99,10 @@ 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

View file

@ -41,8 +41,8 @@ DEFAULT_PREFS = {
'smtp_recipients': [],
# Subscriptions
'subscriptions': {
'email': []
}
'email': [],
},
}
@ -53,8 +53,10 @@ class CoreNotifications(CustomNotifications):
def enable(self):
CustomNotifications.enable(self)
self.register_custom_email_notification('TorrentFinishedEvent',
self._on_torrent_finished_event)
self.register_custom_email_notification(
'TorrentFinishedEvent',
self._on_torrent_finished_event,
)
def disable(self):
self.deregister_custom_email_notification('TorrentFinishedEvent')
@ -77,8 +79,10 @@ class CoreNotifications(CustomNotifications):
if not self.config['smtp_enabled']:
return defer.succeed('SMTP notification not enabled.')
subject, message = result
log.debug('Spawning new thread to send email with subject: %s: %s',
subject, message)
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.
return threads.deferToThread(self._notify_email, subject, message)
@ -103,7 +107,8 @@ class CoreNotifications(CustomNotifications):
'smtp_from': self.config['smtp_from'],
'subject': subject,
'smtp_recipients': to_addrs_str,
'date': formatdate()}
'date': formatdate(),
}
headers = """\
From: %(smtp_from)s
To: %(smtp_recipients)s
@ -176,7 +181,7 @@ Date: %(date)s
'downloading "%(name)s", which includes %(num_files)i files.'
'\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
@ -196,7 +201,8 @@ class Core(CorePluginBase, CoreNotifications):
def enable(self):
CoreNotifications.enable(self)
self.config = deluge.configmanager.ConfigManager(
'notifications-core.conf', DEFAULT_PREFS)
'notifications-core.conf', DEFAULT_PREFS,
)
log.debug('ENABLING CORE NOTIFICATIONS')
def disable(self):

View file

@ -67,8 +67,10 @@ DEFAULT_PREFS = {
}
RECIPIENT_FIELD, RECIPIENT_EDIT = list(range(2))
(SUB_EVENT, SUB_EVENT_DOC, SUB_NOT_EMAIL, SUB_NOT_POPUP, SUB_NOT_BLINK,
SUB_NOT_SOUND) = list(range(6))
(
SUB_EVENT, SUB_EVENT_DOC, SUB_NOT_EMAIL, SUB_NOT_POPUP, SUB_NOT_BLINK,
SUB_NOT_SOUND,
) = list(range(6))
SND_EVENT, SND_EVENT_DOC, SND_NAME, SND_PATH = list(range(4))
@ -80,13 +82,13 @@ 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):
@ -146,17 +148,22 @@ class GtkUiNotifications(CustomNotifications):
def handle_custom_blink_notification(self, result, eventtype):
if result:
return defer.maybeDeferred(self.__blink)
return defer.succeed('Will not blink. The returned value from the custom '
'handler was: %s' % result)
return defer.succeed(
'Will not blink. The returned value from the custom '
'handler was: %s' % result,
)
def handle_custom_sound_notification(self, result, eventtype):
if isinstance(result, ''.__class__):
if not result and eventtype in self.config['custom_sounds']:
return defer.maybeDeferred(
self.__play_sound, self.config['custom_sounds'][eventtype])
self.__play_sound, self.config['custom_sounds'][eventtype],
)
return defer.maybeDeferred(self.__play_sound, result)
return defer.succeed('Will not play sound. The returned value from the '
'custom handler was: %s' % result)
return defer.succeed(
'Will not play sound. The returned value from the '
'custom handler was: %s' % result,
)
def __blink(self):
self.systray.blink(True)
@ -219,12 +226,16 @@ class GtkUiNotifications(CustomNotifications):
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')
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
message = _(
'The torrent "%(name)s" including %(num_files)i file(s) '
'has finished downloading.',
) % torrent_status
return title, message
@ -235,7 +246,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
def enable(self):
self.config = deluge.configmanager.ConfigManager(
'notifications-gtk.conf', DEFAULT_PREFS
'notifications-gtk.conf', DEFAULT_PREFS,
)
self.builder = gtk.Builder()
self.builder.add_from_file(get_resource('config.ui'))
@ -248,73 +259,97 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
self.build_notifications_model_populate_treeview()
client.notifications.get_handled_events().addCallback(
self.popuplate_what_needs_handled_events
self.popuplate_what_needs_handled_events,
)
self.builder.connect_signals({
'on_add_button_clicked': (self.on_add_button_clicked,
self.recipients_treeview),
'on_delete_button_clicked': (self.on_delete_button_clicked,
self.recipients_treeview),
'on_add_button_clicked': (
self.on_add_button_clicked,
self.recipients_treeview,
),
'on_delete_button_clicked': (
self.on_delete_button_clicked,
self.recipients_treeview,
),
'on_enabled_toggled': self.on_enabled_toggled,
'on_sound_enabled_toggled': self.on_sound_enabled_toggled,
'on_sounds_edit_button_clicked': self.on_sounds_edit_button_clicked,
'on_sounds_revert_button_clicked': self.on_sounds_revert_button_clicked,
'on_sound_path_update_preview': self.on_sound_path_update_preview
'on_sound_path_update_preview': self.on_sound_path_update_preview,
})
component.get('Preferences').add_page(_('Notifications'), self.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_apply_prefs',
self.on_apply_prefs,
)
component.get('PluginManager').register_hook(
'on_show_prefs',
self.on_show_prefs,
)
if not POPUP_AVAILABLE:
self.builder.get_object('popup_enabled').set_property('sensitive',
False)
self.builder.get_object('popup_enabled').set_property(
'sensitive',
False,
)
if not SOUND_AVAILABLE:
# for widget_name in ('sound_enabled', 'sound_path', 'sounds_page', 'sounds_page_label'):
# self.builder.get_object(widget_name).set_property('sensitive', False)
self.builder.get_object('sound_enabled').set_property('sensitive',
False)
self.builder.get_object('sound_enabled').set_property(
'sensitive',
False,
)
self.builder.get_object('sound_path').set_property('sensitive', False)
self.builder.get_object('sounds_page').set_property('sensitive',
False)
self.builder.get_object('sounds_page_label').set_property('sensitive',
False)
self.builder.get_object('sounds_page').set_property(
'sensitive',
False,
)
self.builder.get_object('sounds_page_label').set_property(
'sensitive',
False,
)
self.systray = component.get('SystemTray')
if not hasattr(self.systray, 'tray'):
# Tray is not beeing used
self.builder.get_object('blink_enabled').set_property('sensitive',
False)
self.builder.get_object('blink_enabled').set_property(
'sensitive',
False,
)
GtkUiNotifications.enable(self)
def disable(self):
GtkUiNotifications.disable(self)
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',
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 build_recipients_model_populate_treeview(self):
# SMTP Recipients treeview/model
self.recipients_treeview = self.builder.get_object('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,
text=RECIPIENT_FIELD,
editable=RECIPIENT_EDIT)
column = gtk.TreeViewColumn(
'Recipients', renderer,
text=RECIPIENT_FIELD,
editable=RECIPIENT_EDIT,
)
column.set_expand(True)
self.recipients_treeview.append_column(column)
self.recipients_treeview.set_model(self.recipients_model)
@ -324,7 +359,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
self.sounds_treeview = self.builder.get_object('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)
@ -360,7 +395,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
self.subscriptions_treeview = self.builder.get_object('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)
@ -426,7 +461,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
SND_EVENT, event_name,
SND_EVENT_DOC, event_doc,
SND_NAME, basename(snd_path),
SND_PATH, snd_path
SND_PATH, snd_path,
)
def populate_subscriptions(self, handled_events, email_subscriptions=None):
@ -443,7 +478,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
SUB_NOT_EMAIL, event_name in email_subscriptions,
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']
SUB_NOT_SOUND, event_name in subscriptions_dict['sound'],
)
def on_apply_prefs(self):
@ -465,8 +500,10 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
old_sound_file = self.config['sound_path']
new_sound_file = self.builder.get_object('sound_path').get_filename()
log.debug('Old Default sound file: %s New one: %s',
old_sound_file, new_sound_file)
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:
log.debug('Custom sound for event "%s": %s', event_name, filename)
@ -482,9 +519,9 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
'subscriptions': {
'popup': current_popup_subscriptions,
'blink': current_blink_subscriptions,
'sound': current_sound_subscriptions
'sound': current_sound_subscriptions,
},
'custom_sounds': custom_sounds
'custom_sounds': custom_sounds,
})
self.config.save()
@ -496,9 +533,11 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
'smtp_pass': self.builder.get_object('smtp_pass').get_text(),
'smtp_from': self.builder.get_object('smtp_from').get_text(),
'smtp_tls': self.builder.get_object('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_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)
@ -517,20 +556,22 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
self.builder.get_object('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.recipients_model.set(
self.recipients_model.append(),
RECIPIENT_FIELD, recipient,
RECIPIENT_EDIT, False,
)
self.builder.get_object('smtp_enabled').set_active(
core_config['smtp_enabled']
core_config['smtp_enabled'],
)
self.builder.get_object('sound_enabled').set_active(
self.config['sound_enabled']
self.config['sound_enabled'],
)
self.builder.get_object('popup_enabled').set_active(
self.config['popup_enabled']
self.config['popup_enabled'],
)
self.builder.get_object('blink_enabled').set_active(
self.config['blink_enabled']
self.config['blink_enabled'],
)
if self.config['sound_path']:
sound_path = self.config['sound_path']
@ -543,19 +584,21 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
client.notifications.get_handled_events().addCallback(
self.popuplate_what_needs_handled_events,
core_config['subscriptions']['email']
core_config['subscriptions']['email'],
)
def on_sound_path_update_preview(self, filechooser):
client.notifications.get_handled_events().addCallback(
self.populate_sounds
self.populate_sounds,
)
def on_add_button_clicked(self, widget, treeview):
model = treeview.get_model()
model.set(model.append(),
RECIPIENT_FIELD, 'USER@HOST',
RECIPIENT_EDIT, True)
model.set(
model.append(),
RECIPIENT_FIELD, 'USER@HOST',
RECIPIENT_EDIT, True,
)
def on_delete_button_clicked(self, widget, treeview):
selection = treeview.get_selection()
@ -570,20 +613,28 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
def on_recipients_treeview_selection_changed(self, selection):
model, selected_connection_iter = selection.get_selected()
if selected_connection_iter:
self.builder.get_object('delete_button').set_property('sensitive',
True)
self.builder.get_object('delete_button').set_property(
'sensitive',
True,
)
else:
self.builder.get_object('delete_button').set_property('sensitive',
False)
self.builder.get_object('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.builder.get_object('delete_button').set_property('sensitive',
True)
self.builder.get_object('delete_button').set_property(
'sensitive',
True,
)
else:
self.builder.get_object('delete_button').set_property('sensitive',
False)
self.builder.get_object('delete_button').set_property(
'sensitive',
False,
)
def on_sounds_treeview_selection_changed(self, selection):
model, selected_iter = selection.get_selected()
@ -605,9 +656,11 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
model, selected_iter = selection.get_selected()
if selected_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']))
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')
@ -617,10 +670,12 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
path = model.get(selected_iter, SND_PATH)[0]
dialog = gtk.FileChooserDialog(
title=_('Choose Sound File'),
buttons=(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK)
buttons=(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK,
),
)
dialog.set_filename(path)
@ -629,34 +684,48 @@ class GtkUI(GtkPluginBase, GtkUiNotifications):
new_filename = dialog.get_filename()
dialog.destroy()
log.debug(new_filename)
model.set(selected_iter,
SND_PATH, new_filename,
SND_NAME, basename(new_filename))
model.set(
selected_iter,
SND_PATH, new_filename,
SND_NAME, basename(new_filename),
)
d = defer.maybeDeferred(dialog.run)
d.addCallback(update_model)
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',
'smtp_pass', 'smtp_tls', 'smtp_from',
'smtp_recipients'):
self.builder.get_object(widget_name).set_property('sensitive',
widget.get_active())
for widget_name in (
'smtp_host', 'smtp_port', 'smtp_user', 'smtp_pass',
'smtp_pass', 'smtp_tls', 'smtp_from',
'smtp_recipients',
):
self.builder.get_object(widget_name).set_property(
'sensitive',
widget.get_active(),
)
def on_sound_enabled_toggled(self, widget):
if widget.get_active():
self.builder.get_object('sound_path').set_property('sensitive', True)
self.builder.get_object('sounds_page').set_property('sensitive',
True)
self.builder.get_object('sounds_page_label').set_property('sensitive',
True)
self.builder.get_object('sounds_page').set_property(
'sensitive',
True,
)
self.builder.get_object('sounds_page_label').set_property(
'sensitive',
True,
)
else:
self.builder.get_object('sound_path').set_property('sensitive', False)
self.builder.get_object('sounds_page').set_property('sensitive',
False)
self.builder.get_object('sounds_page_label').set_property('sensitive',
False)
self.builder.get_object('sounds_page').set_property(
'sensitive',
False,
)
self.builder.get_object('sounds_page_label').set_property(
'sensitive',
False,
)
# for widget_name in ('sounds_path', 'sounds_page', 'sounds_page_label'):
# self.builder.get_object(widget_name).set_property('sensitive',

View file

@ -34,7 +34,7 @@ class TestEmailNotifications(component.Component):
self.n = 1
self.events = [
FooEvent(),
CustomEvent()
CustomEvent(),
]
self.events_classes = []
@ -45,21 +45,21 @@ class TestEmailNotifications(component.Component):
# component.get('CorePlugin.Notifications').register_custom_email_notification(
component.get('Notifications').register_custom_email_notification(
event.__class__.__name__,
self.custom_email_message_provider
self.custom_email_message_provider,
)
elif self.__imp == 'gtk':
notifications_component = component.get('Notifications')
notifications_component.register_custom_popup_notification(
event.__class__.__name__,
self.custom_popup_message_provider
self.custom_popup_message_provider,
)
notifications_component.register_custom_blink_notification(
event.__class__.__name__,
self.custom_blink_message_provider
self.custom_blink_message_provider,
)
notifications_component.register_custom_sound_notification(
event.__class__.__name__,
self.custom_sound_message_provider
self.custom_sound_message_provider,
)
self.lc.start(60, False)

View file

@ -52,5 +52,5 @@ setup(
%s = deluge.plugins.%s:GtkUIPlugin
[deluge.plugin.web]
%s = deluge.plugins.%s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower()) * 3)
""" % ((__plugin_name__, __plugin_name__.lower()) * 3),
)

View file

@ -32,13 +32,13 @@ DEFAULT_PREFS = {
'low_active': -1,
'low_active_down': -1,
'low_active_up': -1,
'button_state': [[0] * 7 for dummy in range(24)]
'button_state': [[0] * 7 for dummy in range(24)],
}
STATES = {
0: 'Green',
1: 'Yellow',
2: 'Red'
2: 'Red',
}
CONTROLLED_SETTINGS = [
@ -46,7 +46,7 @@ CONTROLLED_SETTINGS = [
'max_upload_speed',
'max_active_limit',
'max_active_downloading',
'max_active_seeding'
'max_active_seeding',
]
@ -127,7 +127,7 @@ class Core(CorePluginBase):
'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)
'upload_rate_limit': int(self.config['low_up'] * 1024),
}
component.get('Core').apply_session_settings(settings)
# Resume the session if necessary

View file

@ -31,8 +31,10 @@ DAYS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
class SchedulerSelectWidget(gtk.DrawingArea):
def __init__(self, hover):
super(SchedulerSelectWidget, self).__init__()
self.set_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK |
gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.LEAVE_NOTIFY_MASK)
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)
@ -40,9 +42,11 @@ class SchedulerSelectWidget(gtk.DrawingArea):
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],
[204 / 255, 0 / 255, 0 / 255]]
self.colors = [
[115 / 255, 210 / 255, 22 / 255],
[237 / 255, 212 / 255, 0 / 255],
[204 / 255, 0 / 255, 0 / 255],
]
self.button_state = [[0] * 7 for dummy in range(24)]
self.start_point = [0, 0]
@ -69,11 +73,15 @@ class SchedulerSelectWidget(gtk.DrawingArea):
for y in range(7):
for x in range(24):
context.set_source_rgba(self.colors[self.button_state[x][y]][0],
self.colors[self.button_state[x][y]][1],
self.colors[self.button_state[x][y]][2], 0.7)
context.rectangle(width * (6 * x / 145 + 1 / 145), height * (6 * y / 43 + 1 / 43),
5 * width / 145, 5 * height / 43)
context.set_source_rgba(
self.colors[self.button_state[x][y]][0],
self.colors[self.button_state[x][y]][1],
self.colors[self.button_state[x][y]][2], 0.7,
)
context.rectangle(
width * (6 * x / 145 + 1 / 145), height * (6 * y / 43 + 1 / 43),
5 * width / 145, 5 * height / 43,
)
context.fill_preserve()
context.set_source_rgba(0.5, 0.5, 0.5, 0.5)
context.stroke()
@ -123,9 +131,11 @@ class SchedulerSelectWidget(gtk.DrawingArea):
if self.get_point(event) != self.hover_point:
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')
self.hover_label.set_text(
self.hover_days[self.hover_point[1]] +
' ' + 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]]]
@ -153,7 +163,8 @@ class GtkUI(GtkPluginBase):
image=get_resource('green.png'),
text='',
callback=self.on_status_item_clicked,
tooltip='Scheduler')
tooltip='Scheduler',
)
def on_state_deferred(state):
self.state = state

View file

@ -44,5 +44,5 @@ setup(
%s = deluge.plugins.%s:GtkUIPlugin
[deluge.plugin.web]
%s = deluge.plugins.%s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower()) * 3)
""" % ((__plugin_name__, __plugin_name__.lower()) * 3),
)

View file

@ -32,7 +32,7 @@ DEFAULT_TOTALS = {
'total_download': 0,
'total_payload_upload': 0,
'total_payload_download': 0,
'stats': {}
'stats': {},
}
log = logging.getLogger(__name__)
@ -85,7 +85,7 @@ class Core(CorePluginBase):
'dht_cache_nodes',
'dht_torrents',
'num_peers',
'num_connections'
'num_connections',
)
self.update_stats()
@ -121,9 +121,11 @@ class Core(CorePluginBase):
pass
stats['num_connections'] = stats['num_peers'] + stats['peer.num_peers_half_open']
stats['dht_cache_nodes'] = stats['dht.dht_node_cache']
stats.update(self.core.get_config_values(['max_download',
'max_upload',
'max_num_connections']))
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:
@ -193,7 +195,8 @@ class Core(CorePluginBase):
@export
def get_session_totals(self):
return self.core.get_session_status(
['total_upload', 'total_download', 'total_payload_upload', 'total_payload_download'])
['total_upload', 'total_download', 'total_payload_upload', 'total_payload_download'],
)
@export
def set_config(self, config):

View file

@ -69,7 +69,7 @@ class Graph(object):
self.mean_selected = True
self.legend_selected = True
self.max_selected = True
self.black = (0, 0, 0,)
self.black = (0, 0, 0)
self.interval = 2 # 2 secs
self.text_bg = (255, 255, 255, 128) # prototyping
self.set_left_axis()
@ -83,7 +83,7 @@ class Graph(object):
'label': label,
'line': line,
'fill': fill,
'color': color
'color': color,
}
def set_stats(self, stats):
@ -273,7 +273,8 @@ class Graph(object):
self.ctx.line_to(
int(right - (len(values) - 1) * step),
bottom)
bottom,
)
self.ctx.close_path()
def draw_value_poly(self, values, color, max_value, bounds, fill=False):

View file

@ -45,7 +45,9 @@ DEFAULT_CONF = {
},
'seeds_graph': {
'num_peers': str(gtk.gdk.Color('blue')),
}}}
},
},
}
def neat_time(column, cell, model, data):
@ -126,9 +128,11 @@ class GraphsTab(Tab):
# set a clip region
context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
context.clip()
self.graph.draw_to_context(context,
self.graph_widget.allocation.width,
self.graph_widget.allocation.height)
self.graph.draw_to_context(
context,
self.graph_widget.allocation.width,
self.graph_widget.allocation.height,
)
# Do not propagate the event
return False
@ -153,12 +157,18 @@ class GraphsTab(Tab):
self.graph_widget = self.bandwidth_graph
self.graph = Graph()
colors = self.colors['bandwidth_graph']
self.graph.add_stat('download_rate', label='Download Rate',
color=gtk_to_graph_color(colors['download_rate']))
self.graph.add_stat('upload_rate', label='Upload Rate',
color=gtk_to_graph_color(colors['upload_rate']))
self.graph.set_left_axis(formatter=fspeed_shortform, min=10240,
formatter_scale=size_formatter_scale)
self.graph.add_stat(
'download_rate', label='Download Rate',
color=gtk_to_graph_color(colors['download_rate']),
)
self.graph.add_stat(
'upload_rate', label='Upload Rate',
color=gtk_to_graph_color(colors['upload_rate']),
)
self.graph.set_left_axis(
formatter=fspeed_shortform, min=10240,
formatter_scale=size_formatter_scale,
)
def select_connections_graph(self):
log.debug('Selecting connections graph')
@ -183,9 +193,11 @@ class GraphsTab(Tab):
def set_colors(self, colors):
self.colors = colors
# Fake switch page to update the graph colors (HACKY)
self._on_notebook_switch_page(self.notebook,
None, # This is unused
self.notebook.get_current_page())
self._on_notebook_switch_page(
self.notebook,
None, # This is unused
self.notebook.get_current_page(),
)
def _on_intervals_changed(self, intervals):
liststore = gtk.ListStore(int)

View file

@ -46,10 +46,10 @@ class StatsTestCase(BaseTestCase):
raise unittest.SkipTest('WebUi plugin not available for testing')
totals = yield client.stats.get_totals()
self.assertEquals(totals['total_upload'], 0)
self.assertEquals(totals['total_payload_upload'], 0)
self.assertEquals(totals['total_payload_download'], 0)
self.assertEquals(totals['total_download'], 0)
self.assertEqual(totals['total_upload'], 0)
self.assertEqual(totals['total_payload_upload'], 0)
self.assertEqual(totals['total_payload_download'], 0)
self.assertEqual(totals['total_download'], 0)
# print_totals(totals)
@defer.inlineCallbacks
@ -59,10 +59,10 @@ class StatsTestCase(BaseTestCase):
raise unittest.SkipTest('WebUi plugin not available for testing')
totals = yield client.stats.get_session_totals()
self.assertEquals(totals['total_upload'], 0)
self.assertEquals(totals['total_payload_upload'], 0)
self.assertEquals(totals['total_payload_download'], 0)
self.assertEquals(totals['total_download'], 0)
self.assertEqual(totals['total_upload'], 0)
self.assertEqual(totals['total_payload_upload'], 0)
self.assertEqual(totals['total_payload_download'], 0)
self.assertEqual(totals['total_download'], 0)
# print_totals(totals)
@pytest.mark.gtkui

View file

@ -48,5 +48,5 @@ setup(
%s = deluge.plugins.%s:GtkUIPlugin
[deluge.plugin.web]
%s = deluge.plugins.%s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower()) * 3)
""" % ((__plugin_name__, __plugin_name__.lower()) * 3),
)

View file

@ -28,8 +28,10 @@ class GtkUI(GtkPluginBase):
self.core = client.toggle
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)

View file

@ -45,5 +45,5 @@ setup(
%s = deluge.plugins.%s:GtkUIPlugin
[deluge.plugin.web]
%s = deluge.plugins.%s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower()) * 3)
""" % ((__plugin_name__, __plugin_name__.lower()) * 3),
)

View file

@ -33,7 +33,7 @@ log = logging.getLogger(__name__)
DEFAULT_PREFS = {
'enabled': False,
'ssl': False,
'port': 8112
'port': 8112,
}

View file

@ -49,7 +49,7 @@ class GtkUI(GtkPluginBase):
config = {
'enabled': self.builder.get_object('enabled_checkbutton').get_active(),
'ssl': self.builder.get_object('ssl_checkbutton').get_active(),
'port': self.builder.get_object('port_spinbutton').get_value_as_int()
'port': self.builder.get_object('port_spinbutton').get_value_as_int(),
}
client.webui.set_config(config)
@ -75,8 +75,10 @@ class GtkUI(GtkPluginBase):
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

@ -42,5 +42,5 @@ setup(
%s = deluge.plugins.%s:CorePlugin
[deluge.plugin.gtkui]
%s = deluge.plugins.%s:GtkUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower()) * 2)
""" % ((__plugin_name__, __plugin_name__.lower()) * 2),
)

View file

@ -73,8 +73,8 @@ __all__ = ['dumps', 'loads']
py3 = sys.version_info[0] >= 3
if py3:
long = int # pylint: disable=redefined-builtin
unicode = str # pylint: disable=redefined-builtin
long = int # noqa: A001, pylint: disable=redefined-builtin
unicode = str # noqa: A001, pylint: disable=redefined-builtin
def int2byte(c):
return bytes([c])
@ -434,9 +434,13 @@ def test():
f1 = struct.unpack('!f', struct.pack('!f', 25.5))[0]
f2 = struct.unpack('!f', struct.pack('!f', 29.3))[0]
f3 = struct.unpack('!f', struct.pack('!f', -0.6))[0]
ld = (({b'a': 15, b'bb': f1, b'ccc': f2, b'': (f3, (), False, True, b'')}, (b'a', 10**20),
tuple(range(-100000, 100000)), b'b' * 31, b'b' * 62, b'b' * 64, 2**30, 2**33, 2**62,
2**64, 2**30, 2**33, 2**62, 2**64, False, False, True, -1, 2, 0),)
ld = (
(
{b'a': 15, b'bb': f1, b'ccc': f2, b'': (f3, (), False, True, b'')}, (b'a', 10**20),
tuple(range(-100000, 100000)), b'b' * 31, b'b' * 62, b'b' * 64, 2**30, 2**33, 2**62,
2**64, 2**30, 2**33, 2**62, 2**64, False, False, True, -1, 2, 0,
),
)
assert loads(dumps(ld)) == ld
d = dict(zip(range(-100000, 100000), range(-100000, 100000)))
d.update({b'a': 20, 20: 40, 40: 41, f1: f2, f2: f3, f3: False, False: True, True: False})
@ -444,15 +448,15 @@ def test():
assert loads(dumps(ld)) == ld
ld = (b'', b'a' * 10, b'a' * 100, b'a' * 1000, b'a' * 10000, b'a' * 100000, b'a' * 1000000, b'a' * 10000000)
assert loads(dumps(ld)) == ld
ld = tuple([dict(zip(range(n), range(n))) for n in range(100)]) + (b'b',)
ld = tuple(dict(zip(range(n), range(n))) for n in range(100)) + (b'b',)
assert loads(dumps(ld)) == ld
ld = tuple([dict(zip(range(n), range(-n, 0))) for n in range(100)]) + (b'b',)
ld = tuple(dict(zip(range(n), range(-n, 0))) for n in range(100)) + (b'b',)
assert loads(dumps(ld)) == ld
ld = tuple([tuple(range(n)) for n in range(100)]) + (b'b',)
ld = tuple(tuple(range(n)) for n in range(100)) + (b'b',)
assert loads(dumps(ld)) == ld
ld = tuple([b'a' * n for n in range(1000)]) + (b'b',)
ld = tuple(b'a' * n for n in range(1000)) + (b'b',)
assert loads(dumps(ld)) == ld
ld = tuple([b'a' * n for n in range(1000)]) + (None, True, None)
ld = tuple(b'a' * n for n in range(1000)) + (None, True, None)
assert loads(dumps(ld)) == ld
assert loads(dumps(None)) is None
assert loads(dumps({None: None})) == {None: None}

View file

@ -20,10 +20,14 @@ 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(
'-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')
@ -71,7 +75,7 @@ def create_plugin():
'python_path': python_path,
'url': options.url,
'configdir': options.configdir,
'current_year': datetime.utcnow().year
'current_year': datetime.utcnow().year,
}
filename = os.path.join(path, filename)

View file

@ -33,20 +33,34 @@ 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(
'--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()
@ -80,7 +94,8 @@ if options.max_active_seeding:
if options.max_download_speed:
if is_float_digit(options.max_download_speed) and (
float(options.max_download_speed) >= 0.0 or float(options.max_download_speed) == -1.0):
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')
@ -88,7 +103,8 @@ if options.max_download_speed:
if options.max_upload_speed:
if is_float_digit(options.max_upload_speed) and (
float(options.max_upload_speed) >= 0.0 or float(options.max_upload_speed) == -1.0):
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')

View file

@ -25,9 +25,11 @@ class BaseTestCase(unittest.TestCase):
def setUp(self): # NOQA: N803
if len(component._ComponentRegistry.components) != 0:
warnings.warn('The component._ComponentRegistry.components is not empty on test setup.\n'
'This is probably caused by another test that did not clean up after finishing!: %s' %
component._ComponentRegistry.components)
warnings.warn(
'The component._ComponentRegistry.components is not empty on test setup.\n'
'This is probably caused by another test that did not clean up after finishing!: %s' %
component._ComponentRegistry.components,
)
d = maybeDeferred(self.set_up)
def on_setup_error(error):

View file

@ -209,8 +209,10 @@ class ProcessOutputHandler(protocol.ProcessProtocol):
print('\n%s' % prefixed)
def start_core(listen_port=58846, logfile=None, timeout=10, timeout_msg=None,
custom_script='', print_stdout=True, print_stderr=True, extra_callbacks=None):
def start_core(
listen_port=58846, logfile=None, timeout=10, timeout_msg=None,
custom_script='', print_stdout=True, print_stderr=True, extra_callbacks=None,
):
"""Start the deluge core as a daemon.
Args:
@ -242,7 +244,7 @@ try:
daemon = deluge.core.daemon_entry.start_daemon(skip_start=True)
%s
daemon.start()
except:
except Exception:
import traceback
sys.stderr.write('Exception raised:\\n %%s' %% traceback.format_exc())
""" % (config_directory, listen_port, custom_script)
@ -254,11 +256,17 @@ except:
# Specify the triggers for daemon log output
default_core_cb['triggers'] = [
{'expr': 'Finished loading ', 'value': lambda reader, data, data_all: reader},
{'expr': 'Could not 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)}
{
'expr': 'Could not 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)

View file

@ -36,8 +36,10 @@ class DaemonBase(object):
return d
@defer.inlineCallbacks
def start_core(self, arg, custom_script='', logfile='', print_stdout=True, print_stderr=True, timeout=5,
port_range=10, extra_callbacks=None):
def start_core(
self, arg, custom_script='', logfile='', print_stdout=True, print_stderr=True, timeout=5,
port_range=10, extra_callbacks=None,
):
if logfile == '':
logfile = 'daemon_%s.log' % self.id()
@ -52,12 +54,14 @@ 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!',
custom_script=custom_script,
print_stdout=print_stdout,
print_stderr=print_stderr,
extra_callbacks=extra_callbacks)
d, self.core = common.start_core(
listen_port=self.listen_port, logfile=logfile,
timeout=timeout, timeout_msg='Timeout!',
custom_script=custom_script,
print_stdout=print_stdout,
print_stderr=print_stderr,
extra_callbacks=extra_callbacks,
)
yield d
except CannotListenError as ex:
exception_error = ex

View file

@ -26,5 +26,5 @@ class AuthManagerTestCase(BaseTestCase):
def test_authorize(self):
self.assertEqual(
self.auth.authorize(*get_localhost_auth()),
AUTH_LEVEL_ADMIN
AUTH_LEVEL_ADMIN,
)

View file

@ -36,8 +36,10 @@ class NoVersionSendingDaemonSSLProxy(DaemonSSLProxy):
class NoVersionSendingClient(Client):
def connect(self, host='127.0.0.1', port=58846, username='', password='',
skip_authentication=False):
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)
@ -116,7 +118,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
def on_failure(failure):
self.assertEqual(
failure.trap(error.BadLoginError),
error.BadLoginError
error.BadLoginError,
)
self.assertEqual(failure.value.message, 'Password does not match')
self.addCleanup(client.disconnect)
@ -131,7 +133,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
def on_failure(failure):
self.assertEqual(
failure.trap(error.BadLoginError),
error.BadLoginError
error.BadLoginError,
)
self.assertEqual(failure.value.message, 'Username does not exist')
self.addCleanup(client.disconnect)
@ -146,7 +148,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
def on_failure(failure):
self.assertEqual(
failure.trap(error.AuthenticationRequired),
error.AuthenticationRequired
error.AuthenticationRequired,
)
self.assertEqual(failure.value.username, username)
self.addCleanup(client.disconnect)
@ -179,13 +181,13 @@ class ClientTestCase(BaseTestCase, DaemonBase):
username, password = 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):
self.assertEqual(
failure.trap(error.IncompatibleClient),
error.IncompatibleClient
error.IncompatibleClient,
)
self.addCleanup(no_version_sending_client.disconnect)

View file

@ -116,17 +116,19 @@ class CommonTestCase(unittest.TestCase):
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)
@ -135,7 +137,8 @@ class CommonTestCase(unittest.TestCase):
def test_archive_files(self):
arc_filelist = [
get_test_data_file('test.torrent'),
get_test_data_file('deluge.png')]
get_test_data_file('deluge.png'),
]
arc_filepath = archive_files('test-arc', arc_filelist)
with tarfile.open(arc_filepath, 'r') as tar:

View file

@ -137,7 +137,8 @@ class ComponentTestClass(BaseTestCase):
self.assertRaises(
component.ComponentAlreadyRegistered,
ComponentTester,
'test_register_exception_c1')
'test_register_exception_c1',
)
def test_stop_component(self):
def on_stop(result, c):
@ -230,11 +231,15 @@ class ComponentTestClass(BaseTestCase):
result = yield component.start()
self.assertEqual(
[(result[0][0], result[0][1].value)],
[(defer.FAILURE,
[(
defer.FAILURE,
component.ComponentException(
'Trying to start component "%s" but it is '
'not in a stopped state. Current state: %s' %
('test_pause_c1', 'Paused'), ''))])
('test_pause_c1', 'Paused'), '',
),
)],
)
def test_shutdown(self):
def on_shutdown(result, c1):

View file

@ -75,8 +75,10 @@ class TopLevelResource(Resource):
self.putChild('cookie', CookieResource())
self.putChild('partial', PartialDownload())
self.putChild('redirect', RedirectResource())
self.putChild('ubuntu-9.04-desktop-i386.iso.torrent',
File(common.get_test_data_file('ubuntu-9.04-desktop-i386.iso.torrent')))
self.putChild(
'ubuntu-9.04-desktop-i386.iso.torrent',
File(common.get_test_data_file('ubuntu-9.04-desktop-i386.iso.torrent')),
)
class CoreTestCase(BaseTestCase):
@ -152,7 +154,7 @@ class CoreTestCase(BaseTestCase):
from deluge.bencode import bdecode, bencode
with open(filename, 'rb') as _file:
info_hash = sha(bencode(bdecode(_file.read())[b'info'])).hexdigest()
self.assertEquals(torrent_id, info_hash)
self.assertEqual(torrent_id, info_hash)
def test_add_torrent_file_invalid_filedump(self):
options = {}

View file

@ -31,8 +31,10 @@ class ErrorTestCase(unittest.TestCase):
def test_incompatible_client(self):
version = '1.3.6'
e = deluge.error.IncompatibleClient(version)
self.assertEqual(str(e), 'Your deluge client is not compatible with the daemon. \
Please upgrade your client to %s' % version)
self.assertEqual(
str(e), 'Your deluge client is not compatible with the daemon. \
Please upgrade your client to %s' % version,
)
def test_not_authorized_error(self):
current_level = 5

View file

@ -85,8 +85,10 @@ class FilesTabTestCase(BaseTestCase):
return _verify_treestore(treestore.get_iter_root(), tree)
def test_files_tab(self):
self.filestab.files_list[self.t_id] = ({'index': 0, 'path': '1/test_10.txt', 'offset': 0, 'size': 13},
{'index': 1, 'path': 'test_100.txt', 'offset': 13, 'size': 14})
self.filestab.files_list[self.t_id] = (
{'index': 0, 'path': '1/test_10.txt', 'offset': 0, 'size': 13},
{'index': 1, 'path': 'test_100.txt', 'offset': 13, 'size': 14},
)
self.filestab.update_files()
self.filestab._on_torrentfilerenamed_event(self.t_id, self.index, '2/test_100.txt')
@ -96,8 +98,10 @@ class FilesTabTestCase(BaseTestCase):
self.assertTrue(ret)
def test_files_tab2(self):
self.filestab.files_list[self.t_id] = ({'index': 0, 'path': '1/1/test_10.txt', 'offset': 0, 'size': 13},
{'index': 1, 'path': 'test_100.txt', 'offset': 13, 'size': 14})
self.filestab.files_list[self.t_id] = (
{'index': 0, 'path': '1/1/test_10.txt', 'offset': 0, 'size': 13},
{'index': 1, 'path': 'test_100.txt', 'offset': 13, 'size': 14},
)
self.filestab.update_files()
self.filestab._on_torrentfilerenamed_event(self.t_id, self.index, '1/1/test_100.txt')
@ -107,8 +111,10 @@ class FilesTabTestCase(BaseTestCase):
self.assertTrue(ret)
def test_files_tab3(self):
self.filestab.files_list[self.t_id] = ({'index': 0, 'path': '1/test_10.txt', 'offset': 0, 'size': 13},
{'index': 1, 'path': 'test_100.txt', 'offset': 13, 'size': 14})
self.filestab.files_list[self.t_id] = (
{'index': 0, 'path': '1/test_10.txt', 'offset': 0, 'size': 13},
{'index': 1, 'path': 'test_100.txt', 'offset': 13, 'size': 14},
)
self.filestab.update_files()
self.filestab._on_torrentfilerenamed_event(self.t_id, self.index, '1/test_100.txt')
@ -118,20 +124,30 @@ class FilesTabTestCase(BaseTestCase):
self.assertTrue(ret)
def test_files_tab4(self):
self.filestab.files_list[self.t_id] = ({'index': 0, 'path': '1/test_10.txt', 'offset': 0, 'size': 13},
{'index': 1, 'path': '1/test_100.txt', 'offset': 13, 'size': 14})
self.filestab.files_list[self.t_id] = (
{'index': 0, 'path': '1/test_10.txt', 'offset': 0, 'size': 13},
{'index': 1, 'path': '1/test_100.txt', 'offset': 13, 'size': 14},
)
self.filestab.update_files()
self.filestab._on_torrentfilerenamed_event(self.t_id, self.index, '1/2/test_100.txt')
ret = self.verify_treestore(self.filestab.treestore, [['1/', [['2/', [['test_100.txt']]],
['test_10.txt']]]])
ret = self.verify_treestore(
self.filestab.treestore, [[
'1/', [
['2/', [['test_100.txt']]],
['test_10.txt'],
],
]],
)
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
self.assertTrue(ret)
def test_files_tab5(self):
self.filestab.files_list[self.t_id] = ({'index': 0, 'path': '1/test_10.txt', 'offset': 0, 'size': 13},
{'index': 1, 'path': '2/test_100.txt', 'offset': 13, 'size': 14})
self.filestab.files_list[self.t_id] = (
{'index': 0, 'path': '1/test_10.txt', 'offset': 0, 'size': 13},
{'index': 1, 'path': '2/test_100.txt', 'offset': 13, 'size': 14},
)
self.filestab.update_files()
self.filestab._on_torrentfilerenamed_event(self.t_id, self.index, '1/test_100.txt')

View file

@ -43,8 +43,10 @@ class RenameResource(Resource):
def render(self, request):
filename = request.args.get('filename', ['renamed_file'])[0]
request.setHeader(b'Content-Type', b'text/plain')
request.setHeader(b'Content-Disposition', b'attachment; filename=' +
filename)
request.setHeader(
b'Content-Disposition', b'attachment; filename=' +
filename,
)
return b'This file should be called ' + filename

View file

@ -38,7 +38,7 @@ class JSONBase(BaseTestCase, DaemonBase):
def connect_client(self, *args, **kwargs):
return client.connect(
'localhost', self.listen_port, username=kwargs.get('user', ''),
password=kwargs.get('password', '')
password=kwargs.get('password', ''),
)
def disconnect_client(self, *args):
@ -219,18 +219,24 @@ class JSONRequestFailedTestCase(JSONBase, WebServerMockBase):
daemon.rpcserver.register_object(test)
"""
from twisted.internet.defer import Deferred
extra_callback = {'deferred': Deferred(), 'types': ['stderr'],
'timeout': 10,
'triggers': [{'expr': 'in test_raise_error',
'value': lambda reader, data, data_all: 'Test'}]}
extra_callback = {
'deferred': Deferred(), 'types': ['stderr'],
'timeout': 10,
'triggers': [{
'expr': 'in test_raise_error',
'value': lambda reader, data, data_all: 'Test',
}],
}
def on_test_raise(*args):
self.assertTrue('Unhandled error in Deferred:' in self.core.stderr_out)
self.assertTrue('in test_raise_error' in self.core.stderr_out)
extra_callback['deferred'].addCallback(on_test_raise)
d.addCallback(self.start_core, custom_script=custom_script, print_stdout=False, print_stderr=False,
timeout=5, extra_callbacks=[extra_callback])
d.addCallback(
self.start_core, custom_script=custom_script, print_stdout=False, print_stderr=False,
timeout=5, extra_callbacks=[extra_callback],
)
d.addCallbacks(self.connect_client, self.terminate_core)
return d
@ -257,7 +263,8 @@ class JSONRequestFailedTestCase(JSONBase, WebServerMockBase):
self.assertEqual(
response['error']['message'],
'Failure: [Failure instance: Traceback (failure with no frames):'
" <class 'deluge.error.DelugeError'>: DelugeERROR\n]")
" <class 'deluge.error.DelugeError'>: DelugeERROR\n]",
)
self.assertEqual(response['error']['code'], 4)
request.write = write

View file

@ -31,8 +31,10 @@ class TorrentTestCase(BaseTestCase):
def setup_config(self):
config_dir = common.set_tmp_config_dir()
core_config = deluge.config.Config('core.conf', defaults=deluge.core.preferencesmanager.DEFAULT_PREFS,
config_dir=config_dir)
core_config = deluge.config.Config(
'core.conf', defaults=deluge.core.preferencesmanager.DEFAULT_PREFS,
config_dir=config_dir,
)
core_config.save()
def set_up(self):
@ -77,8 +79,10 @@ class TorrentTestCase(BaseTestCase):
return atp
def test_set_prioritize_first_last_pieces(self):
piece_indexes = [0, 1, 50, 51, 52, 110, 111, 112, 113, 200, 201, 202, 212,
213, 214, 215, 216, 217, 457, 458, 459, 460, 461, 462]
piece_indexes = [
0, 1, 50, 51, 52, 110, 111, 112, 113, 200, 201, 202, 212,
213, 214, 215, 216, 217, 457, 458, 459, 460, 461, 462,
]
self.run_test_set_prioritize_first_last_pieces('dir_with_6_files.torrent', piece_indexes)
def run_test_set_prioritize_first_last_pieces(self, torrent_file, prioritized_piece_indexes):
@ -169,7 +173,7 @@ class TorrentTestCase(BaseTestCase):
'num_seeds': 16777215, 'sequential_download': 0, 'announce_to_trackers': 1,
'peers': '\n\x00\x02\x0f=\xc6SC\x17]\xd8}\x7f\x00\x00\x01=\xc6', 'finished_time': 13399,
'last_upload': 13399, 'trackers': [[]], 'super_seeding': 0,
'file sizes': [[512000, 1411826586]], 'last_download': 13399
'file sizes': [[512000, 1411826586]], 'last_download': 13399,
}
torrent_state = TorrentState(
torrent_id='2dc5d0e71a66fe69649a640d39cb00a259704973',
@ -185,7 +189,8 @@ class TorrentTestCase(BaseTestCase):
filedump = _file.read()
resume_data = utf8_encode_structure(resume_data)
torrent_id = self.core.torrentmanager.add(
state=torrent_state, filedump=filedump, resume_data=lt.bencode(resume_data))
state=torrent_state, filedump=filedump, resume_data=lt.bencode(resume_data),
)
torrent = self.core.torrentmanager.torrents[torrent_id]
def assert_resume_data():

View file

@ -42,26 +42,30 @@ setup_translations()
@pytest.mark.gtkui
class TorrentviewTestCase(BaseTestCase):
default_column_index = ['filter', 'torrent_id', 'dirty', '#',
'Name',
'Size', 'Downloaded', 'Uploaded', 'Remaining',
'Progress',
'Seeds', 'Peers', 'Seeds:Peers',
'Down Speed', 'Up Speed', 'Down Limit', 'Up Limit',
'ETA', 'Ratio', 'Avail',
'Added', 'Completed', 'Complete Seen',
'Tracker', 'Download Folder', 'Owner', 'Shared']
default_liststore_columns = [bool, str, bool, int,
str, str, # Name
TYPE_UINT64, TYPE_UINT64, TYPE_UINT64, TYPE_UINT64,
float, str, # Progress
int, int, int, int, float, # Seeds, Peers
int, int, float, float,
int, float, float, # ETA, Ratio, Avail
int, int, int,
str, str, # Tracker
str, str,
bool] # shared
default_column_index = [
'filter', 'torrent_id', 'dirty', '#',
'Name',
'Size', 'Downloaded', 'Uploaded', 'Remaining',
'Progress',
'Seeds', 'Peers', 'Seeds:Peers',
'Down Speed', 'Up Speed', 'Down Limit', 'Up Limit',
'ETA', 'Ratio', 'Avail',
'Added', 'Completed', 'Complete Seen',
'Tracker', 'Download Folder', 'Owner', 'Shared',
]
default_liststore_columns = [
bool, str, bool, int,
str, str, # Name
TYPE_UINT64, TYPE_UINT64, TYPE_UINT64, TYPE_UINT64,
float, str, # Progress
int, int, int, int, float, # Seeds, Peers
int, int, float, float,
int, float, float, # ETA, Ratio, Avail
int, int, int,
str, str, # Tracker
str, str,
bool,
] # shared
def set_up(self):
if libs_available is False:
@ -89,10 +93,14 @@ class TorrentviewTestCase(BaseTestCase):
# Add a text column
test_col = 'Test column'
self.torrentview.add_text_column(test_col, status_field=['label'])
self.assertEqual(len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 1)
self.assertEqual(len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 1)
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 1,
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 1,
)
self.assertEqual(self.torrentview.column_index[-1], test_col)
self.assertEqual(self.torrentview.columns[test_col].column_indices, [32])
@ -106,10 +114,14 @@ class TorrentviewTestCase(BaseTestCase):
test_col2 = 'Test column2'
self.torrentview.add_text_column(test_col2, status_field=['label2'])
self.assertEqual(len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 2)
self.assertEqual(len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 2)
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 2,
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 2,
)
# test_col
self.assertEqual(self.torrentview.column_index[-2], test_col)
self.assertEqual(self.torrentview.columns[test_col].column_indices, [32])
@ -140,10 +152,14 @@ class TorrentviewTestCase(BaseTestCase):
# Remove test_col
self.torrentview.remove_column(test_col)
self.assertEqual(len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 1)
self.assertEqual(len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 1)
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 1,
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 1,
)
self.assertEqual(self.torrentview.column_index[-1], test_col2)
self.assertEqual(self.torrentview.columns[test_col2].column_indices, [32])
@ -159,10 +175,14 @@ class TorrentviewTestCase(BaseTestCase):
# Add a column with multiple column types
test_col3 = 'Test column3'
self.torrentview.add_progress_column(test_col3, status_field=['progress', 'label3'], col_types=[float, str])
self.assertEqual(len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 2)
self.assertEqual(len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 1)
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 2,
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 1,
)
self.assertEqual(self.torrentview.column_index[-1], test_col3)
self.assertEqual(self.torrentview.columns[test_col3].column_indices, [32, 33])

View file

@ -118,10 +118,12 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
"""
self.transfer = TransferTestClass()
self.msg1 = (0, 1, {'key_int': 1242429423}, {'key_str': b'some string'}, {'key_bool': True})
self.msg2 = (2, 3, {'key_float': 12424.29423},
{'key_unicode': 'some string'},
{'key_dict_with_tuple': {'key_tuple': (1, 2, 3)}},
{'keylist': [4, '5', 6.7]})
self.msg2 = (
2, 3, {'key_float': 12424.29423},
{'key_unicode': 'some string'},
{'key_dict_with_tuple': {'key_tuple': (1, 2, 3)}},
{'keylist': [4, '5', 6.7]},
)
self.msg1_expected_compressed_base64 = 'RAAAADF4nDvKwJjenp1aGZ+ZV+Lgxfv9PYRXXFLU'\
'XZyfm6oAZGTmpad3gAST8vNznAEAJhSQ'

View file

@ -33,11 +33,23 @@ class UICommonTestCase(unittest.TestCase):
ti = TorrentInfo(filename)
files = ti.files_tree['unicode_filenames']
self.assertTrue((b'\xe3\x83\x86\xe3\x82\xaf\xe3\x82\xb9\xe3\x83\xbb\xe3\x83'
b'\x86\xe3\x82\xaf\xe3\x82\xb5\xe3\x83\xb3.mkv').decode('utf8') in files)
self.assertTrue((b'\xd0\x9c\xd0\xb8\xd1\x85\xd0\xb0\xd0\xb8\xd0\xbb \xd0\x93'
b'\xd0\xbe\xd1\x80\xd0\xb1\xd0\xb0\xd1\x87\xd1\x91\xd0\xb2.mkv').decode('utf8') in files)
self.assertTrue(
(
b'\xe3\x83\x86\xe3\x82\xaf\xe3\x82\xb9\xe3\x83\xbb\xe3\x83'
b'\x86\xe3\x82\xaf\xe3\x82\xb5\xe3\x83\xb3.mkv'
).decode('utf8') in files,
)
self.assertTrue(
(
b'\xd0\x9c\xd0\xb8\xd1\x85\xd0\xb0\xd0\xb8\xd0\xbb \xd0\x93'
b'\xd0\xbe\xd1\x80\xd0\xb1\xd0\xb0\xd1\x87\xd1\x91\xd0\xb2.mkv'
).decode('utf8') in files,
)
self.assertTrue(b"Alisher ibn G'iyosiddin Navoiy.mkv".decode('utf8') in files)
self.assertTrue(b'Ascii title.mkv'.decode('utf8') in files)
self.assertTrue((b'\xe0\xa6\xb8\xe0\xa7\x81\xe0\xa6\x95\xe0\xa7\x81\xe0\xa6\xae\xe0\xa6\xbe'
b'\xe0\xa6\xb0 \xe0\xa6\xb0\xe0\xa6\xbe\xe0\xa7\x9f.mkv').decode('utf8') in files)
self.assertTrue(
(
b'\xe0\xa6\xb8\xe0\xa7\x81\xe0\xa6\x95\xe0\xa7\x81\xe0\xa6\xae\xe0\xa6\xbe'
b'\xe0\xa6\xb0 \xe0\xa6\xb0\xe0\xa6\xbe\xe0\xa7\x9f.mkv'
).decode('utf8') in files,
)

View file

@ -60,7 +60,7 @@ class StringFileDescriptor(object):
class UIBaseTestCase(object):
def __init__(self):
self.var = dict()
self.var = {}
def set_up(self):
common.set_tmp_config_dir()
@ -339,8 +339,10 @@ class ConsoleUIWithDaemonBaseTestCase(UIWithDaemonBaseTestCase):
@defer.inlineCallbacks
def test_console_command_status(self):
username, password = get_localhost_auth()
self.patch(sys, 'argv', self.var['sys_arg_cmd'] + ['--port'] + ['58900'] + ['--username'] +
[username] + ['--password'] + [password] + ['status'])
self.patch(
sys, 'argv', self.var['sys_arg_cmd'] + ['--port'] + ['58900'] + ['--username'] +
[username] + ['--password'] + [password] + ['status'],
)
fd = StringFileDescriptor(sys.stdout)
self.patch(sys, 'stdout', fd)

View file

@ -72,8 +72,8 @@ class WebAPITestCase(WebServerTestBase):
'233f23632af0a74748bc5dd1d8717564748877baa16420e6898e17e8aa365e6e': {
'login': 'skrot',
'expires': 1460030877.0,
'level': 10
}
'level': 10,
},
}
self.deluge_web.web_api.set_config(config)
web_config = component.get('DelugeWeb').config.config
@ -147,7 +147,10 @@ class WebAPITestCase(WebServerTestBase):
ret['contents'], {
'azcvsupdater_2.6.2.jar': {
'priority': 4, 'index': 0, 'offset': 0, 'progress': 0.0, 'path':
'azcvsupdater_2.6.2.jar', 'type': 'file', 'size': 307949}})
'azcvsupdater_2.6.2.jar', 'type': 'file', 'size': 307949,
},
},
)
@defer.inlineCallbacks
def test_download_torrent_from_url(self):
@ -170,7 +173,10 @@ class WebAPITestCase(WebServerTestBase):
d = yield agent.request(
b'POST',
b'http://127.0.0.1:%s/json' % self.webserver_listen_port,
Headers({b'User-Agent': [b'Twisted Web Client Example'],
b'Content-Type': [b'application/json']}),
FileBodyProducer(BytesIO(bad_body)))
Headers({
b'User-Agent': [b'Twisted Web Client Example'],
b'Content-Type': [b'application/json'],
}),
FileBodyProducer(BytesIO(bad_body)),
)
yield d

View file

@ -42,12 +42,16 @@ class WebServerTestCase(WebServerTestBase, WebServerMockBase):
# UnicodeDecodeError: 'utf8' codec can't decode byte 0xe5 in position 0: invalid continuation byte
filename = get_test_data_file('filehash_field.torrent')
input_file = '{"params": ["%s"], "method": "web.get_torrent_info", "id": 22}' % filename
headers = {'User-Agent': ['Twisted Web Client Example'],
'Content-Type': ['application/json']}
headers = {
'User-Agent': ['Twisted Web Client Example'],
'Content-Type': ['application/json'],
}
url = 'http://127.0.0.1:%s/json' % self.webserver_listen_port
d = yield agent.request(b'POST', url.encode('utf-8'), Headers(utf8_encode_structure(headers)),
FileBodyProducer(BytesIO(input_file.encode('utf-8'))))
d = yield agent.request(
b'POST', url.encode('utf-8'), Headers(utf8_encode_structure(headers)),
FileBodyProducer(BytesIO(input_file.encode('utf-8'))),
)
try:
body = yield twisted.web.client.readBody(d)
except AttributeError:

View file

@ -28,12 +28,14 @@ class _Reporter(object):
self.klass = klass
deluge = _Reporter('Deluge reporter that suppresses Stacktrace from TODO tests',
'twisted.plugins.delugereporter',
description='Deluge Reporter',
longOpt='deluge-reporter',
shortOpt=None,
klass='DelugeReporter')
deluge = _Reporter(
'Deluge reporter that suppresses Stacktrace from TODO tests',
'twisted.plugins.delugereporter',
description='Deluge Reporter',
longOpt='deluge-reporter',
shortOpt=None,
klass='DelugeReporter',
)
class DelugeReporter(TreeReporter):

View file

@ -100,7 +100,7 @@ class Win32IcoFile(object):
def sizes(self):
"""Get a list of all available icon sizes and color depths."""
return set((h['width'], h['height']) for h in self.entry)
return {(h['width'], h['height']) for h in self.entry}
def get_image(self, size, bpp=False):
"""Get an image from the icon
@ -171,7 +171,7 @@ class Win32IcoFile(object):
im.size, # (w, h)
alpha_bytes, # source chars
'raw', # raw decoder
('L', 0, -1) # 8bpp inverted, unpadded, reversed
('L', 0, -1), # 8bpp inverted, unpadded, reversed
)
# apply mask image as alpha channel
@ -198,7 +198,7 @@ class Win32IcoFile(object):
im.size, # (w, h)
mask_data, # source chars
'raw', # raw decoder
('1;I', w // 8, -1) # 1bpp inverted, padded, reversed
('1;I', w // 8, -1), # 1bpp inverted, padded, reversed
)
# now we have two images, im is XOR image and mask is AND image
@ -215,7 +215,8 @@ class Win32IcoFile(object):
def __repr__(self):
s = 'Microsoft Icon: %d images (max %dx%d %dbpp)' % (
len(self.entry), self.entry[0]['width'], self.entry[0]['height'],
self.entry[0]['bpp'])
self.entry[0]['bpp'],
)
return s
# end Win32IcoFile

View file

@ -170,26 +170,48 @@ class BaseArgParser(argparse.ArgumentParser):
self.process_arg_group = False
self.group = self.add_argument_group(_('Common Options'))
if common_help:
self.group.add_argument('-h', '--help', action=HelpAction,
help=_('Print this help message'))
self.group.add_argument('-V', '--version', action='version', version='%(prog)s ' + get_version(),
help=_('Print version information'))
self.group.add_argument('-v', action='version', version='%(prog)s ' + get_version(),
help=argparse.SUPPRESS) # Deprecated arg
self.group.add_argument('-c', '--config', metavar='<config>',
help=_('Set the config directory path'))
self.group.add_argument('-l', '--logfile', metavar='<logfile>',
help=_('Output to specified logfile instead of stdout'))
self.group.add_argument('-L', '--loglevel', choices=[l for k in deluge.log.levels for l in (k, k.upper())],
help=_('Set the log level (none, error, warning, info, debug)'), metavar='<level>')
self.group.add_argument('--logrotate', nargs='?', const='2M', metavar='<max-size>',
help=_('Enable logfile rotation, with optional maximum logfile size, '
'default: %(const)s (Logfile rotation count is 5)'))
self.group.add_argument('-q', '--quiet', action='store_true',
help=_('Quieten logging output (Same as `--loglevel none`)'))
self.group.add_argument('--profile', metavar='<profile-file>', nargs='?', default=False,
help=_('Profile %(prog)s with cProfile. Outputs to stdout '
'unless a filename is specified'))
self.group.add_argument(
'-h', '--help', action=HelpAction,
help=_('Print this help message'),
)
self.group.add_argument(
'-V', '--version', action='version', version='%(prog)s ' + get_version(),
help=_('Print version information'),
)
self.group.add_argument(
'-v', action='version', version='%(prog)s ' + get_version(),
help=argparse.SUPPRESS,
) # Deprecated arg
self.group.add_argument(
'-c', '--config', metavar='<config>',
help=_('Set the config directory path'),
)
self.group.add_argument(
'-l', '--logfile', metavar='<logfile>',
help=_('Output to specified logfile instead of stdout'),
)
self.group.add_argument(
'-L', '--loglevel', choices=[l for k in deluge.log.levels for l in (k, k.upper())],
help=_('Set the log level (none, error, warning, info, debug)'), metavar='<level>',
)
self.group.add_argument(
'--logrotate', nargs='?', const='2M', metavar='<max-size>',
help=_(
'Enable logfile rotation, with optional maximum logfile size, '
'default: %(const)s (Logfile rotation count is 5)',
),
)
self.group.add_argument(
'-q', '--quiet', action='store_true',
help=_('Quieten logging output (Same as `--loglevel none`)'),
)
self.group.add_argument(
'--profile', metavar='<profile-file>', nargs='?', default=False,
help=_(
'Profile %(prog)s with cProfile. Outputs to stdout '
'unless a filename is specified',
),
)
def parse_args(self, args=None):
"""Parse UI arguments and handle common and process group options.
@ -251,8 +273,10 @@ class BaseArgParser(argparse.ArgumentParser):
logrotate = common.parse_human_size(options.logrotate)
# Setup the logger
deluge.log.setup_logger(level=options.loglevel, filename=options.logfile, filemode=logfile_mode,
logrotate=logrotate, output_stream=self.log_stream)
deluge.log.setup_logger(
level=options.loglevel, filename=options.logfile, filemode=logfile_mode,
logrotate=logrotate, output_stream=self.log_stream,
)
if options.config:
if not set_config_dir(options.config):
@ -300,14 +324,24 @@ class BaseArgParser(argparse.ArgumentParser):
self.process_arg_group = True
self.group = self.add_argument_group(_('Process Control Options'))
self.group.add_argument('-P', '--pidfile', metavar='<pidfile>', action='store',
help=_('Pidfile to store the process id'))
self.group.add_argument(
'-P', '--pidfile', metavar='<pidfile>', action='store',
help=_('Pidfile to store the process id'),
)
if not common.windows_check():
self.group.add_argument('-d', '--do-not-daemonize', dest='donotdaemonize', action='store_true',
help=_('Do not daemonize (fork) this process'))
self.group.add_argument('-f', '--fork', dest='donotdaemonize', action='store_false',
help=argparse.SUPPRESS) # Deprecated arg
self.group.add_argument('-U', '--user', metavar='<user>', action='store',
help=_('Change to this user on startup (Requires root)'))
self.group.add_argument('-g', '--group', metavar='<group>', action='store',
help=_('Change to this group on startup (Requires root)'))
self.group.add_argument(
'-d', '--do-not-daemonize', dest='donotdaemonize', action='store_true',
help=_('Do not daemonize (fork) this process'),
)
self.group.add_argument(
'-f', '--fork', dest='donotdaemonize', action='store_false',
help=argparse.SUPPRESS,
) # Deprecated arg
self.group.add_argument(
'-U', '--user', metavar='<user>', action='store',
help=_('Change to this user on startup (Requires root)'),
)
self.group.add_argument(
'-g', '--group', metavar='<group>', action='store',
help=_('Change to this group on startup (Requires root)'),
)

View file

@ -98,8 +98,10 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
log.debug('Received invalid message: type is not tuple')
return
if len(request) < 3:
log.debug('Received invalid message: number of items in '
'response is %s', len(request))
log.debug(
'Received invalid message: number of items in '
'response is %s', len(request),
)
return
message_type = request[0]
@ -163,8 +165,10 @@ class DelugeRPCProtocol(DelugeTransferProtocol):
log.debug(msg)
except Exception:
import traceback
log.error('Failed to handle RPC_ERROR (Old daemon?): %s\nLocal error: %s',
request[2], traceback.format_exc())
log.error(
'Failed to handle RPC_ERROR (Old daemon?): %s\nLocal error: %s',
request[2], traceback.format_exc(),
)
d.errback(exception)
del self.__rpc_requests[request_id]
@ -195,17 +199,23 @@ class DelugeRPCClientFactory(ClientFactory):
self.event_handlers = event_handlers
def startedConnecting(self, connector): # NOQA: N802
log.debug('Connecting to daemon at "%s:%s"...',
connector.host, connector.port)
log.debug(
'Connecting to daemon at "%s:%s"...',
connector.host, connector.port,
)
def clientConnectionFailed(self, connector, reason): # NOQA: N802
log.debug('Connection to daemon at "%s:%s" failed: %s',
connector.host, connector.port, reason.value)
log.debug(
'Connection to daemon at "%s:%s" failed: %s',
connector.host, connector.port, reason.value,
)
self.daemon.connect_deferred.errback(reason)
def clientConnectionLost(self, connector, reason): # NOQA: N802
log.debug('Connection lost to daemon at "%s:%s" reason: %s',
connector.host, connector.port, reason.value)
log.debug(
'Connection lost to daemon at "%s:%s" reason: %s',
connector.host, connector.port, reason.value,
)
self.daemon.host = None
self.daemon.port = None
self.daemon.username = None
@ -262,9 +272,11 @@ class DaemonSSLProxy(DaemonProxy):
log.debug('sslproxy.connect()')
self.host = host
self.port = port
self.__connector = reactor.connectSSL(self.host, self.port,
self.__factory,
ssl.ClientContextFactory())
self.__connector = reactor.connectSSL(
self.host, self.port,
self.__factory,
ssl.ClientContextFactory(),
)
self.connect_deferred = defer.Deferred()
self.daemon_info_deferred = defer.Deferred()
@ -384,8 +396,10 @@ class DaemonSSLProxy(DaemonProxy):
log.debug('%s.authenticate: %s', self.__class__.__name__, username)
login_deferred = defer.Deferred()
d = self.call('daemon.login', username, password, client_version=get_version())
d.addCallbacks(self.__on_login, self.__on_login_fail, callbackArgs=[username, login_deferred],
errbackArgs=[login_deferred])
d.addCallbacks(
self.__on_login, self.__on_login_fail, callbackArgs=[username, login_deferred],
errbackArgs=[login_deferred],
)
return login_deferred
def __on_login(self, result, username, login_deferred):
@ -396,7 +410,8 @@ class DaemonSSLProxy(DaemonProxy):
if self.__factory.event_handlers:
self.call('daemon.set_event_interest', list(self.__factory.event_handlers))
self.call('core.get_auth_levels_mappings').addCallback(
self.__on_auth_levels_mappings)
self.__on_auth_levels_mappings,
)
login_deferred.callback(result)
@ -434,9 +449,11 @@ class DaemonStandaloneProxy(DaemonProxy):
self.host = 'localhost'
self.port = 58846
# Running in standalone mode, it's safe to import auth level
from deluge.core.authmanager import (AUTH_LEVEL_ADMIN,
AUTH_LEVELS_MAPPING,
AUTH_LEVELS_MAPPING_REVERSE)
from deluge.core.authmanager import (
AUTH_LEVEL_ADMIN,
AUTH_LEVELS_MAPPING,
AUTH_LEVELS_MAPPING_REVERSE,
)
self.username = 'localclient'
self.authentication_level = AUTH_LEVEL_ADMIN
self.auth_levels_mapping = AUTH_LEVELS_MAPPING
@ -528,8 +545,10 @@ class Client(object):
self.disconnect_callback = None
self.__started_standalone = False
def connect(self, host='127.0.0.1', port=58846, username='', password='',
skip_authentication=False):
def connect(
self, host='127.0.0.1', port=58846, username='', password='',
skip_authentication=False,
):
"""
Connects to a daemon process.
@ -635,8 +654,11 @@ class Client(object):
from errno import ENOENT
if ex.errno == ENOENT:
log.error(
_('Deluge cannot find the `deluged` executable, check that '
'the deluged package is installed, or added to your PATH.'))
_(
'Deluge cannot find the `deluged` executable, check that '
'the deluged package is installed, or added to your PATH.',
),
)
else:
log.exception(ex)
except Exception as ex:

View file

@ -134,14 +134,14 @@ TORRENT_DATA_FIELD = {
'pieces':
{'name': _('Pieces'), 'status': ['num_pieces', 'piece_length']},
'seed_rank':
{'name': _('Seed Rank'), 'status': ['seed_rank']}
{'name': _('Seed Rank'), 'status': ['seed_rank']},
}
TRACKER_STATUS_TRANSLATION = [
_('Error'),
_('Warning'),
_('Announce OK'),
_('Announce Sent')
_('Announce Sent'),
]
PREFS_CATOG_TRANS = {
@ -154,7 +154,7 @@ PREFS_CATOG_TRANS = {
'cache': _('Cache'),
'other': _('Other'),
'daemon': _('Daemon'),
'plugins': _('Plugins')
'plugins': _('Plugins'),
}
FILE_PRIORITY = {
@ -178,7 +178,7 @@ del _
DISK_CACHE_KEYS = [
'disk.num_blocks_read', 'disk.num_blocks_written', 'disk.num_read_ops', 'disk.num_write_ops',
'disk.num_blocks_cache_hits', 'read_hit_ratio', 'write_hit_ratio', 'disk.disk_blocks_in_use',
'disk.read_cache_blocks'
'disk.read_cache_blocks',
]
@ -279,13 +279,13 @@ class TorrentInfo(object):
'type': 'file',
'index': 0,
'length': self.__m_metadata['info']['length'],
'download': True
}
}
'download': True,
},
},
}
else:
self.__m_files_tree = {
self.__m_name: (0, self.__m_metadata['info']['length'], True)
self.__m_name: (0, self.__m_metadata['info']['length'], True),
}
self.__m_files = []
@ -298,13 +298,13 @@ class TorrentInfo(object):
self.__m_files.append({
'path': f['path'],
'size': f['length'],
'download': True
'download': True,
})
else:
self.__m_files.append({
'path': self.__m_name,
'size': self.__m_metadata['info']['length'],
'download': True
'download': True,
})
def as_dict(self, *keys):
@ -315,7 +315,7 @@ class TorrentInfo(object):
:param keys: a number of key strings
:type keys: string
"""
return dict([(key, getattr(self, key)) for key in keys])
return {key: getattr(self, key) for key in keys}
@property
def name(self):
@ -400,7 +400,7 @@ class FileTree2(object):
if child is None:
parent['contents'][directory] = {
'type': 'dir',
'contents': {}
'contents': {},
}
parent = parent['contents'][directory]
return parent, path
@ -411,12 +411,12 @@ class FileTree2(object):
parent, path = get_parent(path)
parent['contents'][path] = {
'type': 'dir',
'contents': {}
'contents': {},
}
else:
parent, path = get_parent(path)
parent['contents'][path] = {
'type': 'file'
'type': 'file',
}
def get_tree(self):
@ -443,13 +443,13 @@ class FileTree2(object):
full_path = os.path.join(parent_path, path).replace('\\', '/')
if directory['contents'][path]['type'] == 'dir':
directory['contents'][path] = callback(
full_path, directory['contents'][path]
) or directory['contents'][path]
full_path, directory['contents'][path],
) or directory['contents'][path]
walk(directory['contents'][path], full_path)
else:
directory['contents'][path] = callback(
full_path, directory['contents'][path]
) or directory['contents'][path]
full_path, directory['contents'][path],
) or directory['contents'][path]
walk(self.tree, '')
def __str__(self):

View file

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from deluge.ui.console.cmdline.command import BaseCommand

View file

@ -35,8 +35,10 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('-p', '--path', dest='path', help=_('download folder for torrent'))
parser.add_argument('torrents', metavar='<torrent>', nargs='+',
help=_('One or more torrent files, URLs or magnet URIs'))
parser.add_argument(
'torrents', metavar='<torrent>', nargs='+',
help=_('One or more torrent files, URLs or magnet URIs'),
)
def handle(self, options):
self.console = component.get('ConsoleUI')
@ -62,11 +64,13 @@ class Command(BaseCommand):
if deluge.common.is_url(torrent):
self.console.write('{!info!}Attempting to add torrent from url: %s' % torrent)
deferreds.append(client.core.add_torrent_url(torrent, t_options).addCallback(on_success).addErrback(
on_fail))
on_fail,
))
elif deluge.common.is_magnet(torrent):
self.console.write('{!info!}Attempting to add torrent from magnet uri: %s' % torrent)
deferreds.append(client.core.add_torrent_magnet(torrent, t_options).addCallback(on_success).addErrback(
on_fail))
on_fail,
))
else:
# Just a file
if urlparse(torrent).scheme == 'file':
@ -85,7 +89,7 @@ class Command(BaseCommand):
deferreds.append(
client.core.add_torrent_file_async(
filename, filedump, t_options,
).addCallback(on_success).addErrback(on_fail)
).addCallback(on_success).addErrback(on_fail),
)
return defer.DeferredList(deferreds)

View file

@ -59,7 +59,7 @@ STATUS_KEYS = [
'total_uploaded',
'total_payload_download',
'total_payload_upload',
'time_added'
'time_added',
]
# Add filter specific state to torrent states
@ -82,21 +82,33 @@ class Command(BaseCommand):
"""
def add_arguments(self, parser):
parser.add_argument('-v', '--verbose', action='store_true', default=False, dest='verbose',
help=_('Show more information per torrent.'))
parser.add_argument('-d', '--detailed', action='store_true', default=False, dest='detailed',
help=_('Show more detailed information including files and peers.'))
parser.add_argument('-s', '--state', action='store', dest='state',
help=_('Show torrents with state STATE: %s.' % (', '.join(STATES))))
parser.add_argument(
'-v', '--verbose', action='store_true', default=False, dest='verbose',
help=_('Show more information per torrent.'),
)
parser.add_argument(
'-d', '--detailed', action='store_true', default=False, dest='detailed',
help=_('Show more detailed information including files and peers.'),
)
parser.add_argument(
'-s', '--state', action='store', dest='state',
help=_('Show torrents with state STATE: %s.' % (', '.join(STATES))),
)
parser.add_argument('--sort', action='store', type=str, default='', dest='sort', help=self.sort_help)
parser.add_argument('--sort-reverse', action='store', type=str, default='', dest='sort_rev',
help=_('Same as --sort but items are in reverse order.'))
parser.add_argument('torrent_ids', metavar='<torrent-id>', nargs='*',
help=_('One or more torrent ids. If none is given, list all'))
parser.add_argument(
'--sort-reverse', action='store', type=str, default='', dest='sort_rev',
help=_('Same as --sort but items are in reverse order.'),
)
parser.add_argument(
'torrent_ids', metavar='<torrent-id>', nargs='*',
help=_('One or more torrent ids. If none is given, list all'),
)
def add_subparser(self, subparsers):
parser = subparsers.add_parser(self.name, prog=self.name, help=self.__doc__,
description=self.__doc__, epilog=self.epilog)
parser = subparsers.add_parser(
self.name, prog=self.name, help=self.__doc__,
description=self.__doc__, epilog=self.epilog,
)
self.add_arguments(parser)
def handle(self, options):
@ -251,7 +263,8 @@ class Command(BaseCommand):
colors.state_color['Seeding'],
fspeed(peer['up_speed']),
colors.state_color['Downloading'],
fspeed(peer['down_speed']))
fspeed(peer['down_speed']),
)
s += '\n'
self.console.write(s[:-1])
@ -280,10 +293,12 @@ class Command(BaseCommand):
if status['state'] != 'Seeding':
s += sep
s += '{!info!}Down Speed: {!input!}%s' % fspeed(
status['download_payload_rate'], shortform=True)
status['download_payload_rate'], shortform=True,
)
s += sep
s += '{!info!}Up Speed: {!input!}%s' % fspeed(
status['upload_payload_rate'], shortform=True)
status['upload_payload_rate'], shortform=True,
)
self.console.write(s)
if status['state'] in ('Seeding', 'Downloading', 'Queued'):
@ -294,7 +309,8 @@ class Command(BaseCommand):
s += '{!info!}Availability: {!input!}%.2f' % status['distributed_copies']
s += sep
s += '{!info!}Seed Rank: {!input!}%s' % f_seedrank_dash(
status['seed_rank'], status['seeding_time'])
status['seed_rank'], status['seeding_time'],
)
self.console.write(s)
total_done = fsize(status['total_done'], shortform=True)
@ -321,7 +337,8 @@ class Command(BaseCommand):
s = '{!info!}Last Transfer: {!input!}%s' % format_time(status['time_since_transfer'])
s += sep
s += '{!info!}Complete Seen: {!input!}%s' % format_date_never(
status['last_seen_complete'])
status['last_seen_complete'],
)
self.console.write(s)
s = '{!info!}Tracker: {!input!}%s' % status['tracker_host']
@ -366,14 +383,18 @@ class Command(BaseCommand):
dl_info += '%s' % ftotal_sized(status['all_time_download'], status['total_payload_download'])
if status['download_payload_rate'] > 0:
dl_info += ' @ %s%s' % (down_color, fspeed(
status['download_payload_rate'], shortform=True))
dl_info += ' @ %s%s' % (
down_color,
fspeed(status['download_payload_rate'], shortform=True),
)
ul_info = ' {!info!}UL: {!input!}'
ul_info += '%s' % ftotal_sized(status['total_uploaded'], status['total_payload_upload'])
if status['upload_payload_rate'] > 0:
ul_info += ' @ %s%s' % (up_color, fspeed(
status['upload_payload_rate'], shortform=True))
ul_info += ' @ %s%s' % (
up_color,
fspeed(status['upload_payload_rate'], shortform=True),
)
eta = ' {!info!}ETA: {!magenta!}%s' % format_time(status['eta'])

View file

@ -33,7 +33,7 @@ torrent_options = {
'stop_ratio': float,
'remove_at_ratio': bool,
'move_completed': bool,
'move_completed_path': str
'move_completed_path': str,
}
@ -43,8 +43,10 @@ class Command(BaseCommand):
usage = _('Usage: manage <torrent-id> [--set <key> <value>] [<key> [<key>...] ]')
def add_arguments(self, parser):
parser.add_argument('torrent', metavar='<torrent>',
help=_('an expression matched against torrent ids and torrent names'))
parser.add_argument(
'torrent', metavar='<torrent>',
help=_('an expression matched against torrent ids and torrent names'),
)
set_group = parser.add_argument_group('setting a value')
set_group.add_argument('-s', '--set', action='store', metavar='<key>', help=_('set value for this key'))
set_group.add_argument('values', metavar='<value>', nargs='+', help=_('Value to set'))

View file

@ -21,8 +21,10 @@ class Command(BaseCommand):
usage = 'pause [ * | <torrent-id> [<torrent-id> ...] ]'
def add_arguments(self, parser):
parser.add_argument('torrent_ids', metavar='<torrent-id>', nargs='+',
help=_('One or more torrent ids. Use "*" to pause all torrents'))
parser.add_argument(
'torrent_ids', metavar='<torrent-id>', nargs='+',
help=_('One or more torrent ids. Use "*" to pause all torrents'),
)
def handle(self, options):
self.console = component.get('ConsoleUI')

View file

@ -20,14 +20,20 @@ class Command(BaseCommand):
"""Manage plugins"""
def add_arguments(self, parser):
parser.add_argument('-l', '--list', action='store_true', default=False, dest='list',
help=_('Lists available plugins'))
parser.add_argument('-s', '--show', action='store_true', default=False, dest='show',
help=_('Shows enabled plugins'))
parser.add_argument(
'-l', '--list', action='store_true', default=False, dest='list',
help=_('Lists available plugins'),
)
parser.add_argument(
'-s', '--show', action='store_true', default=False, dest='show',
help=_('Shows enabled plugins'),
)
parser.add_argument('-e', '--enable', dest='enable', nargs='+', help=_('Enables a plugin'))
parser.add_argument('-d', '--disable', dest='disable', nargs='+', help=_('Disables a plugin'))
parser.add_argument('-r', '--reload', action='store_true', default=False, dest='reload',
help=_('Reload list of available plugins'))
parser.add_argument(
'-r', '--reload', action='store_true', default=False, dest='reload',
help=_('Reload list of available plugins'),
)
parser.add_argument('-i', '--install', help=_('Install a plugin from an .egg file'))
def handle(self, options):

View file

@ -21,8 +21,10 @@ class Command(BaseCommand):
usage = _('Usage: resume [ * | <torrent-id> [<torrent-id> ...] ]')
def add_arguments(self, parser):
parser.add_argument('torrent_ids', metavar='<torrent-id>', nargs='+',
help=_('One or more torrent ids. Use "*" to resume all torrents'))
parser.add_argument(
'torrent_ids', metavar='<torrent-id>', nargs='+',
help=_('One or more torrent ids. Use "*" to resume all torrents'),
)
def handle(self, options):
self.console = component.get('ConsoleUI')

View file

@ -25,10 +25,14 @@ class Command(BaseCommand):
aliases = ['del']
def add_arguments(self, parser):
parser.add_argument('--remove_data', action='store_true', default=False,
help=_('Also removes the torrent data'))
parser.add_argument('-c', '--confirm', action='store_true', default=False,
help=_('List the matching torrents without removing.'))
parser.add_argument(
'--remove_data', action='store_true', default=False,
help=_('Also removes the torrent data'),
)
parser.add_argument(
'-c', '--confirm', action='store_true', default=False,
help=_('List the matching torrents without removing.'),
)
parser.add_argument('torrent_ids', metavar='<torrent-id>', nargs='+', help=_('One or more torrent ids'))
def handle(self, options):
@ -36,9 +40,11 @@ class Command(BaseCommand):
torrent_ids = self.console.match_torrents(options.torrent_ids)
if not options.confirm:
self.console.write('{!info!}%d %s %s{!info!}' % (len(torrent_ids),
_n('torrent', 'torrents', len(torrent_ids)),
_n('match', 'matches', len(torrent_ids))))
self.console.write('{!info!}%d %s %s{!info!}' % (
len(torrent_ids),
_n('torrent', 'torrents', len(torrent_ids)),
_n('match', 'matches', len(torrent_ids)),
))
for t_id in torrent_ids:
name = self.console.get_torrent_name(t_id)
self.console.write('* %-50s (%s)' % (name, t_id))

View file

@ -26,11 +26,17 @@ class Command(BaseCommand):
"""Shows various status information from the daemon"""
def add_arguments(self, parser):
parser.add_argument('-r', '--raw', action='store_true', default=False, dest='raw',
help=_('Raw values for upload/download rates (without KiB/s suffix)'
'(useful for scripts that want to do their own parsing)'))
parser.add_argument('-n', '--no-torrents', action='store_false', default=True, dest='show_torrents',
help=_('Do not show torrent status (Improves command speed)'))
parser.add_argument(
'-r', '--raw', action='store_true', default=False, dest='raw',
help=_(
'Raw values for upload/download rates (without KiB/s suffix)'
'(useful for scripts that want to do their own parsing)',
),
)
parser.add_argument(
'-n', '--no-torrents', action='store_false', default=True, dest='show_torrents',
help=_('Do not show torrent status (Improves command speed)'),
)
def handle(self, options):
self.console = component.get('ConsoleUI')

View file

@ -22,8 +22,10 @@ class Command(BaseCommand):
aliases = ['reannounce']
def add_arguments(self, parser):
parser.add_argument('torrent_ids', metavar='<torrent-id>', nargs='+',
help='One or more torrent ids. "*" updates all torrents')
parser.add_argument(
'torrent_ids', metavar='<torrent-id>', nargs='+',
help='One or more torrent ids. "*" updates all torrents',
)
def handle(self, options):
self.console = component.get('ConsoleUI')

View file

@ -30,8 +30,12 @@ log = logging.getLogger(__name__)
def load_commands(command_dir):
def get_command(name):
command = getattr(__import__('deluge.ui.console.cmdline.commands.%s' % name,
{}, {}, ['Command']), 'Command')()
command = getattr(
__import__(
'deluge.ui.console.cmdline.commands.%s' % name,
{}, {}, ['Command'],
), 'Command',
)()
command._name = name
return command
@ -67,29 +71,45 @@ class Console(UI):
def __init__(self, *args, **kwargs):
super(Console, self).__init__('console', *args, log_stream=LogStream(), **kwargs)
group = self.parser.add_argument_group(_('Console Options'),
_('These daemon connect options will be '
'used for commands, or if console ui autoconnect is enabled.'))
group.add_argument('-d', '--daemon', metavar='<ip_addr>', dest='daemon_addr',
help=_('Deluge daemon IP address to connect to (default 127.0.0.1)'), default='127.0.0.1')
group.add_argument('-p', '--port', metavar='<port>', dest='daemon_port', type=int,
help=_('Deluge daemon port to connect to (default 58846)'), default='58846')
group.add_argument('-U', '--username', metavar='<user>', dest='daemon_user',
help=_('Deluge daemon username to use when connecting'))
group.add_argument('-P', '--password', metavar='<pass>', dest='daemon_pass',
help=_('Deluge daemon password to use when connecting'))
group = self.parser.add_argument_group(
_('Console Options'),
_(
'These daemon connect options will be '
'used for commands, or if console ui autoconnect is enabled.',
),
)
group.add_argument(
'-d', '--daemon', metavar='<ip_addr>', dest='daemon_addr',
help=_('Deluge daemon IP address to connect to (default 127.0.0.1)'), default='127.0.0.1',
)
group.add_argument(
'-p', '--port', metavar='<port>', dest='daemon_port', type=int,
help=_('Deluge daemon port to connect to (default 58846)'), default='58846',
)
group.add_argument(
'-U', '--username', metavar='<user>', dest='daemon_user',
help=_('Deluge daemon username to use when connecting'),
)
group.add_argument(
'-P', '--password', metavar='<pass>', dest='daemon_pass',
help=_('Deluge daemon password to use when connecting'),
)
# To properly print help message for the console commands ( e.g. deluge-console info -h),
# we add a subparser for each command which will trigger the help/usage when given
from deluge.ui.console.parser import ConsoleCommandParser # import here because (see top)
self.console_parser = ConsoleCommandParser(parents=[self.parser], add_help=False, prog=self.parser.prog,
description='Starts the Deluge console interface',
formatter_class=lambda prog:
DelugeTextHelpFormatter(prog, max_help_position=33, width=90))
self.console_parser = ConsoleCommandParser(
parents=[self.parser], add_help=False, prog=self.parser.prog,
description='Starts the Deluge console interface',
formatter_class=lambda prog:
DelugeTextHelpFormatter(prog, max_help_position=33, width=90),
)
self.parser.subparser = self.console_parser
self.console_parser.base_parser = self.parser
subparsers = self.console_parser.add_subparsers(title=_('Console Commands'), help=_('Description'),
description=_('The following console commands are available:'),
metavar=_('Command'), dest='command')
subparsers = self.console_parser.add_subparsers(
title=_('Console Commands'), help=_('Description'),
description=_('The following console commands are available:'),
metavar=_('Command'), dest='command',
)
from deluge.ui.console import UI_PATH # Must import here
self.console_cmds = load_commands(os.path.join(UI_PATH, 'cmdline', 'commands'))
for cmd in sorted(self.console_cmds):
@ -116,5 +136,7 @@ class Console(UI):
log.exception(ex)
raise
return deluge.common.run_profiled(run, self.options, output_file=self.options.profile,
do_profile=self.options.profile)
return deluge.common.run_profiled(
run, self.options, output_file=self.options.profile,
do_profile=self.options.profile,
)

View file

@ -49,7 +49,7 @@ DEFAULT_CONSOLE_PREFS = {
'sidebar_width': 25,
'separate_complete': True,
'move_selection': True,
'columns': {}
'columns': {},
},
'addtorrents': {
'show_misc_files': False, # TODO: Showing/hiding this
@ -63,7 +63,7 @@ DEFAULT_CONSOLE_PREFS = {
'third_tab_lists_all': False,
'torrents_per_tab_press': 15,
'save_command_history': True,
}
},
}
@ -207,8 +207,10 @@ Please use commands from the command line, e.g.:\n
if not self.interactive and options.parsed_cmds[0].command == 'connect':
d = commander.exec_command(options.parsed_cmds.pop(0))
else:
log.info('connect: host=%s, port=%s, username=%s, password=%s',
options.daemon_addr, options.daemon_port, options.daemon_user, options.daemon_pass)
log.info(
'connect: host=%s, port=%s, username=%s, password=%s',
options.daemon_addr, options.daemon_port, options.daemon_user, options.daemon_pass,
)
d = client.connect(options.daemon_addr, options.daemon_port, options.daemon_user, options.daemon_pass)
d.addCallback(on_connect)
d.addErrback(on_connect_fail)
@ -279,8 +281,10 @@ Please use commands from the command line, e.g.:\n
# which can cause issues as the popup's screen will not be destroyed.
# This can lead to the popup border being visible for short periods
# while the current modes' screen is repainted.
log.error('Mode "%s" still has popups available after being paused.'
' Ensure all popups are removed on pause!', mode.popup.title)
log.error(
'Mode "%s" still has popups available after being paused.'
' Ensure all popups are removed on pause!', mode.popup.title,
)
d.addCallback(on_mode_paused, self.active_mode)
reactor.removeReader(self.active_mode)
@ -418,8 +422,10 @@ Please use commands from the command line, e.g.:\n
def tab_complete_path(self, line, path_type='file', ext='', sort='name', dirs_first=True):
if self.interactive and isinstance(self.active_mode, deluge.ui.console.modes.cmdline.CmdLine):
return self.active_mode.tab_complete_path(line, path_type=path_type, ext=ext,
sort=sort, dirs_first=dirs_first)
return self.active_mode.tab_complete_path(
line, path_type=path_type, ext=ext,
sort=sort, dirs_first=dirs_first,
)
def on_client_disconnect(self):
component.stop()
@ -474,10 +480,12 @@ Please use commands from the command line, e.g.:\n
config['language'] = DEFAULT_CONSOLE_PREFS['language']
# Migrate column settings
columns = ['queue', 'size', 'state', 'progress', 'seeds', 'peers', 'downspeed', 'upspeed',
'eta', 'ratio', 'avail', 'added', 'tracker', 'savepath', 'downloaded', 'uploaded',
'remaining', 'owner', 'downloading_time', 'seeding_time', 'completed', 'seeds_peers_ratio',
'complete_seen', 'down_limit', 'up_limit', 'shared', 'name']
columns = [
'queue', 'size', 'state', 'progress', 'seeds', 'peers', 'downspeed', 'upspeed',
'eta', 'ratio', 'avail', 'added', 'tracker', 'savepath', 'downloaded', 'uploaded',
'remaining', 'owner', 'downloading_time', 'seeding_time', 'completed', 'seeds_peers_ratio',
'complete_seen', 'down_limit', 'up_limit', 'shared', 'name',
]
column_name_mapping = {
'downspeed': 'download_speed',
'upspeed': 'upload_speed',
@ -487,7 +495,7 @@ Please use commands from the command line, e.g.:\n
'complete_seen': 'last_seen_complete',
'down_limit': 'max_download_speed',
'up_limit': 'max_upload_speed',
'downloading_time': 'active_time'
'downloading_time': 'active_time',
}
from deluge.ui.console.modes.torrentlist.torrentview import default_columns

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